-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[CoreML] Create EP by AppendExecutionProvider #22675
base: main
Are you sure you want to change the base?
Conversation
96b7f1d
to
530000a
Compare
fb7042f
to
2339e3d
Compare
coreml_version_(coreml::util::CoreMLVersion()) { | ||
coreml_flags_ = options.count("coreml_flags") ? std::stoi(options.at("coreml_flags")) : 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: would be good to define the option names as constants in a header
Can we also add options so the current flags don't need to be used? Some might fold together like the flags to choose device might be in an option called 'MLComputeUnits' and allow 'MLComputeUnitsCPUAndNeuralEngine|MLComputeUnitsCPUAndGPU|MLComputeUnitsCPUOnly|MLComputeUnitsAll' to be provided as a value. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
define the option names as constants in a header
seems not avaible for now. Other EPs used option names as well and we don't have onnxruntime_provider_options_config_keys.h
.
Too much changes involved for this pattern.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can support both provider_options: "MLComputeUnits" and "coreml_flags". "coreml_flags" is compataible with the old API which is essential as the old API is used in many place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can the option names be defined in include\onnxruntime\core\providers\coreml\coreml_provider_factory.h?
Optional for an external user to include that file with the new setup.
Option names are completely EP specific so I don't think we'd want an onnxruntime_provider_options_config_keys.h.
I wasn't suggesting getting rid of support for the existing coreml_flags. Just that a user should be forced to use coreml_flags for older settings, and an option key/value for newer ones. Ideally it's one (old style) or the other (new style).
@@ -439,7 +439,7 @@ select from 'TF8', 'TF16', 'UINT8', 'FLOAT', 'ITENSOR'. \n)"); | |||
} | |||
} | |||
// COREML_FLAG_CREATE_MLPROGRAM | |||
Ort::ThrowOnError(OrtSessionOptionsAppendExecutionProvider_CoreML(session_options, coreml_flags)); | |||
session_options.AppendExecutionProvider("Coreml", {{"coreml_flags", std::to_string(coreml_flags)}}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May be better to convert this is just pass through option key/value pairs instead of setting flags (assuming we add options that cover the current flags). That way it doesn't need an update in the future.
We should have some shared parsing code though instead of so many different EPs parsing for a '|' to find the key and value. It's a little ridiculous that DNNL, CUDA, TensorRT, QNN, SNPE, DML, ACL and VitisAI are all repeating the same basic logic. Maybe ParseSessionConfigs in test/perftest/command_args_parser.cc can be used. Move it into a shared helper and call to create unordered_map<string, string> for the key/value pairs. The EP specific code can validate values using that map.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can commit the suggested changes from lintrunner.
261d1bc
to
43c882f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can commit the suggested changes from lintrunner.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can commit the suggested changes from lintrunner.
static const char* const kCoremlProviderOption_MLModelFormat = "MLModelFormat"; | ||
static const char* const kCoremlProviderOption_MLAllowStaticInputShapes = "MLAllowStaticInputShapes"; | ||
static const char* const kCoremlProviderOption_MLEnableOnSubgraphs = "MLEnableOnSubgraphs"; | ||
static const char* const kCoremlProviderOption_MLModelCacheDir = "MLModelCacheDir"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need the 'ML' prefix on these values? It makes sense to me for MLComputeUnits as that maps to a CoreML enum, but I'm not sure that any of the others do.
We should also provide clear documentation on what is valid/expected for each value even if it's simply copied from the flags doco.
A user might discover this file first so would also be good to mention that these values are intended to be used with Ort.::SessionOptions::AppendExecutionProvider (C++ API)/SessionOptionsAppendExecutionProvider (C API). #Closed
* @param error Optional error information set if an error occurs. | ||
* @return Whether the provider was enabled successfully. | ||
*/ | ||
- (BOOL)appendCoreMLExecutionProviderWithOptions_v2:(NSDictionary*)provider_options |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A user of appendCoreMLExecutionProviderWithOptions can easily look at the documentation for ORTCoreMLExecutionProviderOptions to know what is available. How should they discover the provider options that can be used here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. All avaiable key-valus are listed in the comments.
@@ -12,9 +12,14 @@ namespace coreml { | |||
class Model; | |||
} | |||
|
|||
struct CoreMLOptions { | |||
uint32_t coreml_flags = 0; | |||
std::string cache_path; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: can we keep changes to add supporting a cache path in a separate PR?
Also wondering if this is going to grow better if we keep it separate from coreml_flags. It's a little hard to see what is supported with the current setup. If we define the full set of options in this struct, and we populate those from either the flags, or the provider options, it's clear what the full set of options is.
I'd suggest making CoreMLOptions a class and make it responsible for validation. Can have a ctor for flags and one for provider options. That way all the validation is done in one place and it's clear which class is responsible for validation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it's good to seperate cache path in another PR.
If we make different flag has its own variable to mark it. How can we capatiable it with current coreml_flags
?
Besides, we can easily pass coreml_flags(uint32_t) to object-c. can we pass a class from c++ to obect-c directly?
include/onnxruntime/core/providers/coreml/coreml_provider_factory.h
Outdated
Show resolved
Hide resolved
// Error: must use a '|' to separate the key and value for session configuration entries. | ||
return false; | ||
} | ||
|
||
std::string key(token_sv.substr(0, pos)); | ||
std::string value(token_sv.substr(pos + 1)); | ||
|
||
auto it = session_configs.find(key); | ||
if (it != session_configs.end()) { | ||
// Error: specified duplicate session configuration entry: {key} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we throw from here with the specific error info instead of duplicating the throw with the 'use | to separate values' message in multiple places, which may not be the actual cause of the failure? #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good. I add another available_keys
for early check.
Co-authored-by: Scott McKay <[email protected]>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
44c9e88
to
7ac7cfd
Compare
include/onnxruntime/core/providers/coreml/coreml_provider_factory.h
Outdated
Show resolved
Hide resolved
include/onnxruntime/core/providers/coreml/coreml_provider_factory.h
Outdated
Show resolved
Hide resolved
Co-authored-by: Scott McKay <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can commit the suggested changes from lintrunner.
Co-authored-by: Scott McKay <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can commit the suggested changes from lintrunner.
Description
Motivation and Context