Skip to content

Commit

Permalink
Adress comments
Browse files Browse the repository at this point in the history
  • Loading branch information
wejoncy committed Nov 21, 2024
1 parent b81160f commit 6479c13
Show file tree
Hide file tree
Showing 15 changed files with 119 additions and 110 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,13 @@ enum COREMLFlags {

// MLComputeUnits can be one of the following values:
// 'MLComputeUnitsCPUAndNeuralEngine|MLComputeUnitsCPUAndGPU|MLComputeUnitsCPUOnly|MLComputeUnitsAll'
// these values are intended to be used with Ort.::SessionOptions::AppendExecutionProvider(C++ API)
// /SessionOptionsAppendExecutionProvider (C API). For the old API, use COREMLFlags instead.
static const char* const kCoremlProviderOption_MLComputeUnits = "MLComputeUnits";
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";
static const char* const kCoremlProviderOption_ModelFormat = "ModelFormat";
static const char* const kCoremlProviderOption_RequireStaticInputShapes = "RequireStaticInputShapes";
static const char* const kCoremlProviderOption_EnableOnSubgraphs = "EnableOnSubgraphs";
static const char* const kCoremlProviderOption_ModelCacheDir = "ModelCacheDir";

#ifdef __cplusplus
extern "C" {
Expand Down
11 changes: 9 additions & 2 deletions objectivec/include/ort_coreml_execution_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,18 @@ NS_ASSUME_NONNULL_BEGIN
* decreasing priority.
*
* @param provider_options The CoreML execution provider options in dict.
* available keys-values: more detail in onnxruntime/core/providers/coreml/coreml_provider_factory.cc
* kCoremlProviderOption_MLComputeUnits: one of "MLComputeUnitsCPUAndNeuralEngine",
* "MLComputeUnitsCPUAndGPU", "MLComputeUnitsCPUOnly", "MLComputeUnitsAll"
* kCoremlProviderOption_ModelFormat: one of "MLProgram", "NeuralNetwork"
* kCoremlProviderOption_RequireStaticInputShapes: "1" or "0"
* kCoremlProviderOption_EnableOnSubgraphs: "1" or "0"
* kCoremlProviderOption_ModelCacheDir: path to the model cache directory
* @param error Optional error information set if an error occurs.
* @return Whether the provider was enabled successfully.
*/
- (BOOL)appendCoreMLExecutionProviderWithOptions_v2:(NSDictionary*)provider_options
error:(NSError**)error;
- (BOOL)appendCoreMLExecutionProviderWithOptionsV2:(NSDictionary*)provider_options
error:(NSError**)error;
@end

NS_ASSUME_NONNULL_END
6 changes: 3 additions & 3 deletions objectivec/test/ort_session_test.mm
Original file line number Diff line number Diff line change
Expand Up @@ -226,10 +226,10 @@ - (void)testAppendCoreMLEP {
- (void)testAppendCoreMLEP_v2 {
NSError* err = nil;
ORTSessionOptions* sessionOptions = [ORTSessionTest makeSessionOptions];
NSDictionary* provider_options = @{@"MLEnableOnSubgraphs" : @"1"}; // set an arbitrary option
NSDictionary* provider_options = @{@"EnableOnSubgraphs" : @"1"}; // set an arbitrary option

BOOL appendResult = [sessionOptions appendCoreMLExecutionProviderWithOptions_v2:provider_options
error:&err];
BOOL appendResult = [sessionOptions appendCoreMLExecutionProviderWithOptionsV2:provider_options
error:&err];

if (!ORTIsCoreMLExecutionProviderAvailable()) {
ORTAssertBoolResultUnsuccessful(appendResult, err);
Expand Down
45 changes: 44 additions & 1 deletion onnxruntime/core/providers/coreml/coreml_execution_provider.cc
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,52 @@ namespace onnxruntime {

constexpr const char* COREML = "CoreML";

void CoreMLOptions::ValidateAndParseProviderOption(const ProviderOptions& options) {
const std::unordered_map<std::string, COREMLFlags> available_computeunits_options = {
{"CPUAndNeuralEngine", COREML_FLAG_ONLY_ENABLE_DEVICE_WITH_ANE},
{"CPUAndGPU", COREML_FLAG_USE_CPU_AND_GPU},
{"CPUOnly", COREML_FLAG_USE_CPU_ONLY},
{"ALL", COREML_FLAG_USE_NONE},
};
const std::unordered_map<std::string, COREMLFlags> available_modelformat_options = {
{"MLProgram", COREML_FLAG_CREATE_MLPROGRAM},
{"NeuralNetwork", COREML_FLAG_USE_NONE},
};
std::unordered_set<std::string> valid_options = {
kCoremlProviderOption_MLComputeUnits,
kCoremlProviderOption_ModelFormat,
kCoremlProviderOption_RequireStaticInputShapes,
kCoremlProviderOption_EnableOnSubgraphs,
kCoremlProviderOption_ModelCacheDir,
};
// Validate the options
for (const auto& option : options) {
if (valid_options.find(option.first) == valid_options.end()) {
ORT_THROW("Unknown option: ", option.first);
}
if (kCoremlProviderOption_MLComputeUnits == option.first) {
if (available_computeunits_options.find(option.second) == available_computeunits_options.end()) {
ORT_THROW("Invalid value for option ", option.first, ": ", option.second);
} else {
coreml_flags_ |= available_computeunits_options.at(option.second);
}
} else if (kCoremlProviderOption_ModelFormat == option.first) {
if (available_modelformat_options.find(option.second) == available_modelformat_options.end()) {
ORT_THROW("Invalid value for option ", option.first, ": ", option.second);
} else {
coreml_flags_ |= available_modelformat_options.at(option.second);
}
} else if (kCoremlProviderOption_RequireStaticInputShapes == option.first) {
coreml_flags_ |= COREML_FLAG_ONLY_ALLOW_STATIC_INPUT_SHAPES;
} else if (kCoremlProviderOption_EnableOnSubgraphs == option.first) {
coreml_flags_ |= COREML_FLAG_ENABLE_ON_SUBGRAPH;
}
}
}

CoreMLExecutionProvider::CoreMLExecutionProvider(const CoreMLOptions& options)
: IExecutionProvider{onnxruntime::kCoreMLExecutionProvider},
coreml_flags_(options.coreml_flags),
coreml_flags_(options.CoreMLFlags()),
coreml_version_(coreml::util::CoreMLVersion()) {
LOGS_DEFAULT(VERBOSE) << "CoreML version: " << coreml_version_;
if (coreml_version_ < MINIMUM_COREML_VERSION) {
Expand Down
15 changes: 12 additions & 3 deletions onnxruntime/core/providers/coreml/coreml_execution_provider.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,18 @@ namespace coreml {
class Model;
}

struct CoreMLOptions {
uint32_t coreml_flags = 0;
std::string cache_path;
class CoreMLOptions {
uint32_t coreml_flags_ = 0;

public:
CoreMLOptions(uint32_t coreml_flags) : coreml_flags_(coreml_flags) {}
CoreMLOptions(const ProviderOptions& options) {
ValidateAndParseProviderOption(options);
}
uint32_t CoreMLFlags() const { return coreml_flags_; }

private:
void ValidateAndParseProviderOption(const ProviderOptions& options);
};

class CoreMLExecutionProvider : public IExecutionProvider {
Expand Down
55 changes: 3 additions & 52 deletions onnxruntime/core/providers/coreml/coreml_provider_factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,55 +10,6 @@ using namespace onnxruntime;

namespace onnxruntime {

namespace {
CoreMLOptions ParseProviderOption(const ProviderOptions& options) {
CoreMLOptions coreml_options;
const std::unordered_map<std::string, COREMLFlags> available_computeunits_options = {
{"MLComputeUnitsCPUAndNeuralEngine", COREML_FLAG_ONLY_ENABLE_DEVICE_WITH_ANE},
{"MLComputeUnitsCPUAndGPU", COREML_FLAG_USE_CPU_AND_GPU},
{"MLComputeUnitsCPUOnly", COREML_FLAG_USE_CPU_ONLY},
{"MLComputeUnitsAll", COREML_FLAG_USE_NONE},
};
const std::unordered_map<std::string, COREMLFlags> available_modelformat_options = {
{"MLProgram", COREML_FLAG_CREATE_MLPROGRAM},
{"NeuralNetwork", COREML_FLAG_USE_NONE},
};
std::unordered_set<std::string> valid_options = {
kCoremlProviderOption_MLComputeUnits,
kCoremlProviderOption_MLModelFormat,
kCoremlProviderOption_MLAllowStaticInputShapes,
kCoremlProviderOption_MLEnableOnSubgraphs,
kCoremlProviderOption_MLModelCacheDir,
};
// Validate the options
for (const auto& option : options) {
if (valid_options.find(option.first) == valid_options.end()) {
ORT_THROW("Unknown option: ", option.first);
}
if (kCoremlProviderOption_MLComputeUnits == option.first) {
if (available_computeunits_options.find(option.second) == available_computeunits_options.end()) {
ORT_THROW("Invalid value for option ", option.first, ": ", option.second);
} else {
coreml_options.coreml_flags |= available_computeunits_options.at(option.second);
}
} else if (kCoremlProviderOption_MLModelFormat == option.first) {
if (available_modelformat_options.find(option.second) == available_modelformat_options.end()) {
ORT_THROW("Invalid value for option ", option.first, ": ", option.second);
} else {
coreml_options.coreml_flags |= available_modelformat_options.at(option.second);
}
} else if (kCoremlProviderOption_MLAllowStaticInputShapes == option.first) {
coreml_options.coreml_flags |= COREML_FLAG_ONLY_ALLOW_STATIC_INPUT_SHAPES;
} else if (kCoremlProviderOption_MLEnableOnSubgraphs == option.first) {
coreml_options.coreml_flags |= COREML_FLAG_ENABLE_ON_SUBGRAPH;
} else if (kCoremlProviderOption_MLModelCacheDir == option.first) {
coreml_options.cache_path = option.second;
}
}

return coreml_options;
}
} // namespace
struct CoreMLProviderFactory : IExecutionProviderFactory {
CoreMLProviderFactory(const CoreMLOptions& options)
: options_(options) {}
Expand All @@ -73,13 +24,13 @@ std::unique_ptr<IExecutionProvider> CoreMLProviderFactory::CreateProvider() {
}

std::shared_ptr<IExecutionProviderFactory> CoreMLProviderFactoryCreator::Create(uint32_t coreml_flags) {
CoreMLOptions coreml_options;
coreml_options.coreml_flags = coreml_flags;
CoreMLOptions coreml_options(coreml_flags);
return std::make_shared<onnxruntime::CoreMLProviderFactory>(coreml_options);
}

std::shared_ptr<IExecutionProviderFactory> CoreMLProviderFactoryCreator::Create(const ProviderOptions& options) {
return std::make_shared<onnxruntime::CoreMLProviderFactory>(ParseProviderOption(options));
CoreMLOptions coreml_options(options);
return std::make_shared<onnxruntime::CoreMLProviderFactory>(coreml_options);
}
} // namespace onnxruntime

Expand Down
2 changes: 1 addition & 1 deletion onnxruntime/test/perftest/command_args_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ namespace perftest {
"\t [Example] [For NNAPI EP] -e nnapi -i \"NNAPI_FLAG_USE_FP16 NNAPI_FLAG_USE_NCHW NNAPI_FLAG_CPU_DISABLED\"\n"
"\n"
"\t [CoreML only] [ModelFormat]:[MLProgram, NeuralNetwork] Create an ML Program model or Neural Network. Default is NeuralNetwork.\n"
"\t [CoreML only] [MLComputeUnits]:[CPUAndNeuralEngine CPUAndGPU CPUAndGPU CPUOnly] Specify to limit the backend device/s used to run the model.\n"
"\t [CoreML only] [MLComputeUnits]:[CPUAndNeuralEngine CPUAndGPU ALL CPUOnly] Specify to limit the backend device used to run the model.\n"
"\t [CoreML only] [AllowStaticInputShapes]:[0 1].\n"
"\t [CoreML only] [EnableOnSubgraphs]:[0 1].\n"
"\t [CoreML only] [ModelCacheDir]: a path to cached compiled coreml model.\n"
Expand Down
47 changes: 15 additions & 32 deletions onnxruntime/test/perftest/ort_test_session.cc
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ OnnxRuntimeTestSession::OnnxRuntimeTestSession(Ort::Env& env, std::random_device
std::string ov_string = performance_test_config.run_config.ep_runtime_config_string;
#endif // defined(_MSC_VER)
int num_threads = 0;
if (!ParseSessionConfigs(ov_string, provider_options)) {
if (!ParseSessionConfigs(ov_string, provider_options, {"num_of_threads"})) {
ORT_THROW(
"[ERROR] Use a '|' to separate the key and value for the "
"run-time option you are trying to use.\n");
Expand All @@ -89,10 +89,6 @@ OnnxRuntimeTestSession::OnnxRuntimeTestSession(Ort::Env& env, std::random_device
" set number of threads or use '0' for default\n");
// If the user doesnt define num_threads, auto detect threads later
}
} else {
ORT_THROW(
"[ERROR] [OneDNN] wrong key type entered. "
"Choose from the following runtime key options that are available for OneDNN. ['num_of_threads']\n");
}
}
dnnl_options.threadpool_args = static_cast<void*>(&num_threads);
Expand Down Expand Up @@ -214,7 +210,7 @@ OnnxRuntimeTestSession::OnnxRuntimeTestSession(Ort::Env& env, std::random_device
#else
std::string option_string = performance_test_config.run_config.ep_runtime_config_string;
#endif
if (!ParseSessionConfigs(option_string, provider_options)) {
if (!ParseSessionConfigs(option_string, provider_options, {"backend_path", "profiling_file_path", "profiling_level", "rpc_control_latency", "vtcm_mb", "soc_model", "device_id", "htp_performance_mode", "qnn_saver_path", "htp_graph_finalization_optimization_mode", "qnn_context_priority", "htp_arch", "enable_htp_fp16_precision", "offload_graph_io_quantization"})) {
ORT_THROW(
"[ERROR] Use a '|' to separate the key and value for the "
"run-time option you are trying to use.\n");
Expand Down Expand Up @@ -278,11 +274,6 @@ OnnxRuntimeTestSession::OnnxRuntimeTestSession(Ort::Env& env, std::random_device
std::string str = str_stream.str();
ORT_THROW("Wrong value for ", key, ". select from: ", str);
}
} else {
ORT_THROW(R"(Wrong key type entered. Choose from options: ['backend_path',
'profiling_level', 'profiling_file_path', 'rpc_control_latency', 'vtcm_mb', 'htp_performance_mode',
'qnn_saver_path', 'htp_graph_finalization_optimization_mode', 'qnn_context_priority', 'soc_model',
'htp_arch', 'device_id', 'enable_htp_fp16_precision', 'offload_graph_io_quantization'])");
}
}
session_options.AppendExecutionProvider("QNN", provider_options);
Expand All @@ -296,7 +287,7 @@ OnnxRuntimeTestSession::OnnxRuntimeTestSession(Ort::Env& env, std::random_device
#else
std::string option_string = performance_test_config.run_config.ep_runtime_config_string;
#endif
if (!ParseSessionConfigs(option_string, provider_options)) {
if (!ParseSessionConfigs(option_string, provider_options, {"runtime", "priority", "buffer_type", "enable_init_cache"})) {
ORT_THROW(
"[ERROR] Use a '|' to separate the key and value for the "
"run-time option you are trying to use.\n");
Expand All @@ -320,8 +311,6 @@ select from 'TF8', 'TF16', 'UINT8', 'FLOAT', 'ITENSOR'. \n)");
if (value != "1") {
ORT_THROW("Set to 1 to enable_init_cache.");
}
} else {
ORT_THROW("Wrong key type entered. Choose from options: ['runtime', 'priority', 'buffer_type', 'enable_init_cache'] \n");
}
}

Expand Down Expand Up @@ -370,32 +359,27 @@ select from 'TF8', 'TF16', 'UINT8', 'FLOAT', 'ITENSOR'. \n)");
#ifdef __APPLE__
#ifdef USE_COREML
std::string ov_string = performance_test_config.run_config.ep_runtime_config_string;
if (!ParseSessionConfigs(ov_string, provider_options)) {
if (!ParseSessionConfigs(ov_string, provider_options, {kCoremlProviderOption_MLComputeUnits, kCoremlProviderOption_ModelFormat, kCoremlProviderOption_RequireStaticInputShapes, kCoremlProviderOption_EnableOnSubgraphs})) {
ORT_THROW(
"[ERROR] Use a '|' to separate the key and value for the "
"run-time option you are trying to use.\n");
}

std::unordered_map<std::string, std::string> available_options = {
{"MLComputeUnitsCPUAndNeuralEngine", "1"},
{"MLComputeUnitsCPUAndGPU", "1"},
{"MLComputeUnitsCPUOnly", "1"},
{"MLComputeUnitsAll", "1"},
{"CPUAndNeuralEngine", "1"},
{"CPUAndGPU", "1"},
{"CPUOnly", "1"},
{"ALL", "1"},
};
for (const auto& provider_option : provider_options) {
if (provider_option.first == kCoremlProviderOption_MLComputeUnits &&
available_options.find(provider_option.second) != available_options.end()) {
} else if (provider_option.first == kCoremlProviderOption_MLModelFormat &&
} else if (provider_option.first == kCoremlProviderOption_ModelFormat &&
(provider_option.second == "MLProgram" || provider_option.second == "NeuralNetwork")) {
} else if (provider_option.first == kCoremlProviderOption_MLAllowStaticInputShapes &&
} else if (provider_option.first == kCoremlProviderOption_RequireStaticInputShapes &&
(provider_option.second == "1" || provider_option.second == "0")) {
} else if (provider_option.first == kCoremlProviderOption_MLEnableOnSubgraphs &&
} else if (provider_option.first == kCoremlProviderOption_EnableOnSubgraphs &&
(provider_option.second == "0" || provider_option.second == "1")) {
} else {
ORT_THROW(
"[ERROR] [CoreML] wrong key type entered. Choose from the following runtime key options "
"that are available for CoreML. "
"['MLComputeUnits', 'ModelFormat', 'AllowStaticInputShapes', 'EnableOnSubgraphs'] \n");
}
}
// COREML_FLAG_CREATE_MLPROGRAM
Expand All @@ -413,7 +397,9 @@ select from 'TF8', 'TF16', 'UINT8', 'FLOAT', 'ITENSOR'. \n)");
#else
std::string ov_string = performance_test_config.run_config.ep_runtime_config_string;
#endif
if (!ParseSessionConfigs(ov_string, provider_options)) {
if (!ParseSessionConfigs(ov_string, provider_options,
{"device_filter", "performance_preference", "disable_metacommands",
"enable_graph_capture", "enable_graph_serialization"})) {
ORT_THROW(
"[ERROR] Use a '|' to separate the key and value for the "
"run-time option you are trying to use.\n");
Expand Down Expand Up @@ -488,7 +474,7 @@ select from 'TF8', 'TF16', 'UINT8', 'FLOAT', 'ITENSOR'. \n)");
std::string ov_string = performance_test_config.run_config.ep_runtime_config_string;
#endif // defined(_MSC_VER)
bool enable_fast_math = false;
if (!ParseSessionConfigs(ov_string, provider_options)) {
if (!ParseSessionConfigs(ov_string, provider_options, {"enable_fast_math"})) {
ORT_THROW(
"[ERROR] Use a '|' to separate the key and value for the "
"run-time option you are trying to use.\n");
Expand All @@ -503,9 +489,6 @@ select from 'TF8', 'TF16', 'UINT8', 'FLOAT', 'ITENSOR'. \n)");
"[ERROR] [ACL] You have selcted an invalid value for the key 'enable_fast_math'. "
"Select from 'true' or 'false' \n");
}
} else {
ORT_THROW(
"[ERROR] [ACL] Unrecognized option: ", key);
}
}
Ort::ThrowOnError(
Expand Down
20 changes: 16 additions & 4 deletions onnxruntime/test/perftest/strings_helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@
#include <sstream>

#include "strings_helper.h"
#include "core/common/common.h"

namespace onnxruntime {
namespace perftest {

bool ParseSessionConfigs(const std::string& configs_string,
std::unordered_map<std::string, std::string>& session_configs) {
std::unordered_map<std::string, std::string>& session_configs,
const std::unordered_set<std::string>& available_keys) {
std::istringstream ss(configs_string);
std::string token;

Expand All @@ -25,17 +27,27 @@ bool ParseSessionConfigs(const std::string& configs_string,

auto pos = token_sv.find("|");
if (pos == std::string_view::npos || pos == 0 || pos == token_sv.length()) {
// Error: must use a '|' to separate the key and value for session configuration entries.
return false;
ORT_THROW("Use a '|' to separate the key and value for the run-time option you are trying to use.\n");
}

std::string key(token_sv.substr(0, pos));
std::string value(token_sv.substr(pos + 1));

if (available_keys.empty() == false && available_keys.count(key) == 0) {
// Error: unknown option: {key}
std::string available_keys_str;
for (const auto& key : available_keys) {
available_keys_str += key;
available_keys_str += ", ";
}
ORT_THROW("[ERROR] wrong key type entered.: ", key,
" Choose from the following runtime key options that are available. ", available_keys_str);
}

auto it = session_configs.find(key);
if (it != session_configs.end()) {
// Error: specified duplicate session configuration entry: {key}
return false;
ORT_THROW("Specified duplicate session configuration entry: ", key);
}

session_configs.insert(std::make_pair(std::move(key), std::move(value)));
Expand Down
Loading

0 comments on commit 6479c13

Please sign in to comment.