18
18
namespace onnxruntime {
19
19
namespace openvino_ep {
20
20
void ParseConfigOptions (ProviderInfo& pi ) {
21
-
22
21
if (pi .config_options == nullptr )
23
22
return ;
24
23
@@ -58,23 +57,29 @@ bool ParseBooleanOption(const ProviderOptions& provider_options, std::string opt
58
57
return false ;
59
58
}
60
59
61
- std::string ParseDeviceType (std::shared_ptr<OVCore> ov_core, const ProviderOptions& provider_options, std::string option_name) {
62
- // This function normally does not check if the selected device is available, but does some sanity checks
63
- // Only if the device is not standard, then availability is checked.
64
- // Availability is checked for the selected device in the OpenVINOExecutionProvider constructor
65
-
60
+ std::string ParseDeviceType (std::shared_ptr<OVCore> ov_core, const ProviderOptions& provider_options) {
61
+ std::set<std::string> supported_device_types = {" CPU" , " GPU" , " NPU" };
62
+ std::set<std::string> supported_device_modes = {" AUTO" , " HETERO" , " MULTI" };
66
63
std::vector<std::string> devices_to_check;
67
64
std::string selected_device;
68
- if (provider_options.contains (option_name)) {
69
- selected_device = provider_options.at (option_name);
70
- // If we have multiple device configuration, we need to check all of them
71
- if ((selected_device.find (" HETERO:" ) == 0 ) ||
72
- (selected_device.find (" MULTI:" ) == 0 ) ||
73
- (selected_device.find (" BATCH:" ) == 0 ) ||
74
- (selected_device.find (" AUTO:" ) == 0 )) {
75
- auto delimit = selected_device.find (" :" );
76
- const auto & devices = selected_device.substr (delimit + 1 );
77
- devices_to_check = split (devices, ' ,' );
65
+ std::vector<std::string> luid_list;
66
+ std::string device_mode = " " ;
67
+ std::map<std::string, std::string> ov_luid_map;
68
+
69
+ if (provider_options.contains (" device_type" )) {
70
+ selected_device = provider_options.at (" device_type" );
71
+ std::erase (selected_device, ' ' );
72
+ if (selected_device == " AUTO" ) return selected_device;
73
+
74
+ if (auto delimit = selected_device.find (" :" ); delimit != std::string::npos) {
75
+ device_mode = selected_device.substr (0 , delimit);
76
+ if (supported_device_modes.contains (device_mode)) {
77
+ const auto & devices = selected_device.substr (delimit + 1 );
78
+ devices_to_check = split (devices, ' ,' );
79
+ ORT_ENFORCE (devices_to_check.size () > 0 , " Modes should have devices listed based on priority" );
80
+ } else {
81
+ ORT_THROW (" [ERROR] [OpenVINO] Invalid device_type is selected. Supported modes are AUTO/HETERO/MULTI" );
82
+ }
78
83
} else {
79
84
devices_to_check.push_back (selected_device);
80
85
}
@@ -102,9 +107,18 @@ std::string ParseDeviceType(std::shared_ptr<OVCore> ov_core, const ProviderOptio
102
107
#endif
103
108
}
104
109
105
- // Devices considered to be supported by default
106
- std::unordered_set<std::string> supported_device_types = {" CPU" , " GPU" , " NPU" };
110
+ // Get the LUID passed from the provider option in a comma separated string list
111
+ // Compare each of the LUID's against the LUID obtained using ov property and map with the right device
112
+ if (provider_options.contains (" device_luid" )) {
113
+ std::string luid_str = provider_options.at (" device_luid" );
114
+ std::erase (luid_str, ' ' );
115
+ luid_list = split (luid_str, ' ,' );
116
+ }
117
+
118
+ bool all_devices_found = true ;
119
+
107
120
for (auto device : devices_to_check) {
121
+ bool device_found = false ;
108
122
// Check deprecated device format (CPU_FP32, GPU.0_FP16, etc.) and remove the suffix in place
109
123
// Suffix will be parsed in ParsePrecision
110
124
if (auto delimit = device.find (" _" ); delimit != std::string::npos) {
@@ -113,26 +127,57 @@ std::string ParseDeviceType(std::shared_ptr<OVCore> ov_core, const ProviderOptio
113
127
// Just the device name without .0, .1, etc. suffix
114
128
auto device_prefix = device;
115
129
// Check if device index is appended (.0, .1, etc.), if so, remove it
116
- if (auto delimit = device_prefix.find (" ." ); delimit != std::string::npos) {
130
+ if (auto delimit = device_prefix.find (" ." ); delimit != std::string::npos)
117
131
device_prefix = device_prefix.substr (0 , delimit);
118
- if (device_prefix == " CPU" )
119
- ORT_THROW (" [ERROR] [OpenVINO] CPU device is only supported without index, CPU.x is illegal.\n " );
132
+ if (supported_device_types.contains (device_prefix)) {
133
+ try {
134
+ std::vector<std::string> available_devices = ov_core->GetAvailableDevices (device_prefix);
135
+ // Here we need to find the full device name (with .idx, but without _precision)
136
+ if (std::find (std::begin (available_devices), std::end (available_devices), device) != std::end (available_devices))
137
+ device_found = true ;
138
+ if (device_prefix != " CPU" && luid_list.size () > 0 ) {
139
+ for (auto dev : available_devices) {
140
+ ov::device::LUID ov_luid = OVCore::Get ()->core .get_property (dev, ov::device::luid);
141
+ std::stringstream ov_luid_str;
142
+ ov_luid_str << ov_luid;
143
+ ov_luid_map.emplace (ov_luid_str.str (), dev);
144
+ }
145
+ }
146
+ } catch (const char * msg) {
147
+ ORT_THROW (msg);
148
+ }
120
149
}
121
- // Only device is not supported by default (some exotic device), check if it's available
122
- if (!supported_device_types.contains (device_prefix)) {
123
- std::vector<std::string> available_devices = ov_core->GetAvailableDevices ();
124
- // Here we need to find the full device name (with .idx, but without _precision)
125
- if (std::find (std::begin (available_devices), std::end (available_devices), device) == std::end (available_devices)) {
126
- ORT_THROW (
127
- " [ERROR] [OpenVINO] You have selected wrong configuration value for the key 'device_type'. "
128
- " Select from 'CPU', 'GPU', 'NPU', 'GPU.x' where x = 0,1,2 and so on or from"
129
- " HETERO/MULTI/AUTO/BATCH options available. \n " );
150
+ all_devices_found = all_devices_found && device_found;
151
+ }
152
+ if (luid_list.size () > 0 ) {
153
+ std::string ov_luid_devices;
154
+ for (auto luid_str : luid_list) {
155
+ if (ov_luid_map.contains (luid_str)) {
156
+ if (!ov_luid_devices.empty ()) ov_luid_devices = ov_luid_devices + " ," ;
157
+ ov_luid_devices = ov_luid_devices + ov_luid_map.at (luid_str);
158
+ } else {
159
+ ORT_THROW (" Invalid device_luid is set" );
160
+ }
161
+ }
162
+ if (!device_mode.empty ()) {
163
+ selected_device = device_mode + " :" + ov_luid_devices;
164
+ for (auto dev_str : devices_to_check) {
165
+ auto default_dev = split (dev_str, ' .' )[0 ];
166
+ if (ov_luid_devices.find (default_dev) == std::string::npos)
167
+ selected_device = selected_device + " ," + dev_str;
130
168
}
169
+ } else {
170
+ selected_device = ov_luid_devices;
131
171
}
132
172
}
133
- // All devices have passed the check, return selected device
134
- LOGS_DEFAULT (INFO) << " [OpenVINO-EP] Choosing Device: " << selected_device;
135
- return selected_device;
173
+ // If invalid device is chosen error is thrown
174
+ if (!all_devices_found)
175
+ ORT_THROW (
176
+ " [ERROR] [OpenVINO] You have selected wrong configuration value for the key 'device_type'. "
177
+ " Select from 'CPU', 'GPU', 'NPU', 'GPU.x' where x = 0,1,2 and so on or from"
178
+ " HETERO/MULTI/AUTO/BATCH options available. \n " );
179
+ else
180
+ return selected_device;
136
181
}
137
182
138
183
void ParseProviderOptions ([[maybe_unused]] ProviderInfo& result, [[maybe_unused]] const ProviderOptions& config_options) {}
@@ -175,12 +220,22 @@ struct OpenVINO_Provider : Provider {
175
220
ProviderInfo pi ;
176
221
pi .config_options = config_options;
177
222
223
+ // Lambda function to check for invalid keys and throw an error
224
+ auto validateKeys = [&]() {
225
+ for (const auto & pair : provider_options) {
226
+ if (pi .valid_provider_keys .find (pair.first ) == pi .valid_provider_keys .end ()) {
227
+ ORT_THROW (" Invalid provider_option key: " + pair.first );
228
+ }
229
+ }
230
+ };
231
+ validateKeys ();
232
+
178
233
std::string bool_flag = " " ;
179
234
180
235
// Minor optimization: we'll hold an OVCore reference to ensure we don't create a new core between ParseDeviceType and
181
236
// (potential) SharedContext creation.
182
237
auto ov_core = OVCore::Get ();
183
- pi .device_type = ParseDeviceType (ov_core, provider_options, " device_type " );
238
+ pi .device_type = ParseDeviceType (ov_core, provider_options);
184
239
185
240
if (provider_options.contains (" device_id" )) {
186
241
std::string dev_id = provider_options.at (" device_id" ).data ();
@@ -303,12 +358,15 @@ struct OpenVINO_Provider : Provider {
303
358
<< " Executing with num_streams=1" ;
304
359
}
305
360
}
306
- pi .enable_opencl_throttling = ParseBooleanOption (provider_options, " enable_opencl_throttling" );
361
+ try {
362
+ pi .enable_opencl_throttling = ParseBooleanOption (provider_options, " enable_opencl_throttling" );
307
363
308
- pi .enable_qdq_optimizer = ParseBooleanOption (provider_options, " enable_qdq_optimizer" );
309
-
310
- pi .disable_dynamic_shapes = ParseBooleanOption (provider_options, " disable_dynamic_shapes" );
364
+ pi .enable_qdq_optimizer = ParseBooleanOption (provider_options, " enable_qdq_optimizer" );
311
365
366
+ pi .disable_dynamic_shapes = ParseBooleanOption (provider_options, " disable_dynamic_shapes" );
367
+ } catch (std::string msg) {
368
+ ORT_THROW (msg);
369
+ }
312
370
// Always true for NPU plugin or when passed .
313
371
if (pi .device_type .find (" NPU" ) != std::string::npos) {
314
372
pi .disable_dynamic_shapes = true ;
0 commit comments