@@ -433,45 +433,85 @@ struct OpenVINO_Provider : Provider {
433
433
return std::make_shared<OpenVINOProviderFactory>(pi, SharedContext::Get ());
434
434
}
435
435
436
- Status CreateIExecutionProvider (const OrtHardwareDevice* const * /* devices*/ ,
436
+ Status CreateIExecutionProvider (const OrtHardwareDevice* const * devices,
437
437
const OrtKeyValuePairs* const * ep_metadata,
438
438
size_t num_devices,
439
439
ProviderOptions& provider_options,
440
440
const OrtSessionOptions& session_options,
441
441
const OrtLogger& logger,
442
442
std::unique_ptr<IExecutionProvider>& ep) override {
443
- if (num_devices != 1 ) {
444
- return Status (common::ONNXRUNTIME, ORT_EP_FAIL, " OpenVINO EP only supports one device." );
443
+ // Check if no devices are provided
444
+ if (num_devices == 0 ) {
445
+ return Status (common::ONNXRUNTIME, ORT_EP_FAIL, " No devices provided to CreateEp" );
445
446
}
446
447
447
448
// Block setting certain provider options via AppendExecutionProvider_V2
449
+ // TODO: Expand this out and give better guidance for keys that should now flow through load_config.
448
450
const std::unordered_set<std::string> blocked_provider_keys = {
449
451
" device_type" , " device_id" , " device_luid" , " cache_dir" , " precision" ,
450
452
" context" , " num_of_threads" , " model_priority" , " num_streams" ,
451
- " enable_opencl_throttling" , " enable_qdq_optimizer" , " disable_dynamic_shapes"
452
- };
453
+ " enable_opencl_throttling" , " enable_qdq_optimizer" , " disable_dynamic_shapes" };
453
454
454
455
for (const auto & key : blocked_provider_keys) {
455
456
if (provider_options.find (key) != provider_options.end ()) {
456
- return Status (common::ONNXRUNTIME, ORT_INVALID_ARGUMENT,
457
- " OpenVINO EP: Option '" + key + " ' cannot be set explicitly when using AppendExecutionProvider_V2." );
457
+ return Status (common::ONNXRUNTIME, ORT_INVALID_ARGUMENT,
458
+ " OpenVINO EP: Option '" + key + " ' cannot be set explicitly when using AppendExecutionProvider_V2." );
458
459
}
459
460
}
460
461
461
- // Extract device type from EP metadata
462
- const auto & device_meta_data = ep_metadata[0 ];
463
- auto it = device_meta_data->Entries ().find (" ov_device" );
464
- if (it == device_meta_data->Entries ().end ()) {
465
- return Status (common::ONNXRUNTIME, ORT_INVALID_ARGUMENT, " OpenVINO EP device metadata not found." );
462
+ const char * ov_device_key = " ov_device" ;
463
+ const char * ov_meta_device_key = " ov_meta_device" ;
464
+
465
+ // Create a unique list of ov_devices that were passed in.
466
+ std::unordered_set<std::string_view> unique_ov_devices;
467
+ std::vector<std::string_view> ordered_unique_ov_devices;
468
+ for (size_t i = 0 ; i < num_devices; ++i) {
469
+ const auto & device_meta_data = ep_metadata[i];
470
+ auto ov_device_it = device_meta_data->Entries ().find (ov_device_key);
471
+ if (ov_device_it == device_meta_data->Entries ().end ()) {
472
+ return Status (common::ONNXRUNTIME, ORT_INVALID_ARGUMENT, " OpenVINO EP device metadata not found." );
473
+ }
474
+ auto &ov_device = ov_device_it->second ;
475
+
476
+ // Add to ordered_unique only if not already present
477
+ if (unique_ov_devices.insert (ov_device).second ) {
478
+ ordered_unique_ov_devices.push_back (ov_device);
479
+ }
480
+ }
481
+
482
+ std::string ov_meta_device_type = " NONE" ;
483
+ {
484
+ auto ov_meta_device_it = ep_metadata[0 ]->Entries ().find (ov_meta_device_key);
485
+ if (ov_meta_device_it != ep_metadata[0 ]->Entries ().end ()) {
486
+ ov_meta_device_type = ov_meta_device_it->second ;
487
+ }
466
488
}
467
489
468
- std::string metadata_device_type = it-> second ;
490
+ bool is_meta_device_factory = (ov_meta_device_type != " NONE " ) ;
469
491
470
- // If user didn't specify device_type, use the one from metadata
471
- if (provider_options. find ( " device_type " ) == provider_options. end ()) {
472
- provider_options[ " device_type " ] = metadata_device_type;
492
+ if (ordered_unique_ov_devices. size () > 1 && !is_meta_device_factory) {
493
+ LOGS_DEFAULT (WARNING) << " [OpenVINO EP] Multiple devices were specified that are not OpenVINO meta devices. Using first ov_device only: " << ordered_unique_ov_devices. at ( 0 );
494
+ ordered_unique_ov_devices. resize ( 1 ); // Use only the first device if not a meta device factory
473
495
}
474
496
497
+ std::string ov_device_string;
498
+ if (is_meta_device_factory) {
499
+ // Build up a meta device string based on the devices that are passed in. E.g. AUTO:NPU,GPU.0,CPU
500
+ ov_device_string = ov_meta_device_type;
501
+ ov_device_string += " :" ;
502
+ }
503
+
504
+ bool prepend_comma = false ;
505
+ for (const auto & ov_device : ordered_unique_ov_devices) {
506
+ if (prepend_comma) {
507
+ ov_device_string += " ," ;
508
+ }
509
+ ov_device_string += ov_device;
510
+ prepend_comma = true ;
511
+ }
512
+
513
+ provider_options[" device_type" ] = ov_device_string;
514
+
475
515
// Parse provider info with the device type
476
516
ProviderInfo pi;
477
517
const auto & config_options = session_options.GetConfigOptions ();
0 commit comments