diff --git a/objectivec/include/onnxruntime.h b/objectivec/include/onnxruntime.h index 3521eb673f..c859f6a191 100644 --- a/objectivec/include/onnxruntime.h +++ b/objectivec/include/onnxruntime.h @@ -5,6 +5,7 @@ // the headers below can also be imported individually #import "ort_coreml_execution_provider.h" +#import "ort_xnnpack_execution_provider.h" #import "ort_enums.h" #import "ort_env.h" #import "ort_session.h" diff --git a/objectivec/include/ort_session.h b/objectivec/include/ort_session.h index bac82c32d4..3b6b755413 100644 --- a/objectivec/include/ort_session.h +++ b/objectivec/include/ort_session.h @@ -105,6 +105,18 @@ NS_ASSUME_NONNULL_BEGIN */ - (nullable instancetype)initWithError:(NSError**)error NS_SWIFT_NAME(init()); +/** + * Available since 1.14. + * Appends an execution provider to the session configuration options. + * The execution provider list is ordered by decreasing priority + * @param providerName Provider name. For example, "xnnpack". + * @param providerOptions Provider-specific options. For example, for provider "xnnpack", {"intra_op_num_threads": "2"}. + * @param error Optional error information set if an error occurs. + * @return Whether the execution provider was appended successfully + */ +- (BOOL)appendExecutionProvider:(NSString*)providerName + providerOptions:(NSDictionary*)providerOptions + error:(NSError**)error; /** * Sets the number of threads used to parallelize the execution within nodes. * A value of 0 means ORT will pick a default value. diff --git a/objectivec/include/ort_xnnpack_execution_provider.h b/objectivec/include/ort_xnnpack_execution_provider.h new file mode 100644 index 0000000000..489fd4351d --- /dev/null +++ b/objectivec/include/ort_xnnpack_execution_provider.h @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import + +#import "ort_session.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Options for configuring the Xnnpack execution provider. + */ +@interface ORTXnnpackExecutionProviderOptions : NSObject + +/** + * How many threads used for the Xnnpack execution provider. + */ +@property int intra_op_num_threads; + +@end + +@interface ORTSessionOptions (ORTSessionOptionsXnnpackEP) + +/** + * Available since 1.14. + * Enables the Xnnpack execution provider in the session configuration options. + * It is appended to the execution provider list which is ordered by + * decreasing priority. + * + * @param options The Xnnpack execution provider configuration options. + * @param error Optional error information set if an error occurs. + * @return Whether the provider was enabled successfully. + */ +- (BOOL)appendXnnpackExecutionProviderWithOptions:(ORTXnnpackExecutionProviderOptions*)options + error:(NSError**)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/objectivec/src/ort_session.mm b/objectivec/src/ort_session.mm index f23c5367fb..829b8691ca 100644 --- a/objectivec/src/ort_session.mm +++ b/objectivec/src/ort_session.mm @@ -213,6 +213,24 @@ NS_ASSUME_NONNULL_BEGIN ORT_OBJC_API_IMPL_CATCH_RETURNING_NULLABLE(error) } +- (BOOL)appendExecutionProvider:(NSString*)providerName + providerOptions:(NSDictionary*)providerOptions + error:(NSError**)error { + try { + std::unordered_map options; + NSArray* keys = [providerOptions allKeys]; + + for (NSString* key in keys) { + NSString* value = [providerOptions objectForKey:key]; + options.emplace(key.UTF8String, value.UTF8String); + } + + _sessionOptions->AppendExecutionProvider(providerName.UTF8String, options); + return YES; + } + ORT_OBJC_API_IMPL_CATCH_RETURNING_BOOL(error); +} + - (BOOL)setIntraOpNumThreads:(int)intraOpNumThreads error:(NSError**)error { try { diff --git a/objectivec/src/ort_xnnpack_execution_provider.mm b/objectivec/src/ort_xnnpack_execution_provider.mm new file mode 100644 index 0000000000..34927055b1 --- /dev/null +++ b/objectivec/src/ort_xnnpack_execution_provider.mm @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import "ort_xnnpack_execution_provider.h" + +#import "src/cxx_api.h" +#import "src/error_utils.h" +#import "src/ort_session_internal.h" + +NS_ASSUME_NONNULL_BEGIN + +@implementation ORTXnnpackExecutionProviderOptions + +@end + +@implementation ORTSessionOptions (ORTSessionOptionsXnnpackEP) + +- (BOOL)appendXnnpackExecutionProviderWithOptions:(ORTXnnpackExecutionProviderOptions*)options + error:(NSError**)error { + try { + NSDictionary* provider_options = @{ + @"intra_op_num_threads" : [NSString stringWithFormat:@"%d", options.intra_op_num_threads] + }; + return [self appendExecutionProvider:@"XNNPACK" providerOptions:provider_options error:error]; + } + ORT_OBJC_API_IMPL_CATCH_RETURNING_BOOL(error); +} + +@end + +NS_ASSUME_NONNULL_END diff --git a/objectivec/test/ort_session_test.mm b/objectivec/test/ort_session_test.mm index 0ba3321de1..790ad1c04f 100644 --- a/objectivec/test/ort_session_test.mm +++ b/objectivec/test/ort_session_test.mm @@ -4,6 +4,7 @@ #import #import "ort_coreml_execution_provider.h" +#import "ort_xnnpack_execution_provider.h" #import "ort_env.h" #import "ort_session.h" #import "ort_value.h" @@ -215,6 +216,28 @@ NS_ASSUME_NONNULL_BEGIN ORTAssertNullableResultSuccessful(session, err); } +- (void)testAppendXnnpackEP { + NSError* err = nil; + ORTSessionOptions* sessionOptions = [ORTSessionTest makeSessionOptions]; + ORTXnnpackExecutionProviderOptions* XnnpackOptions = [[ORTXnnpackExecutionProviderOptions alloc] init]; + XnnpackOptions.intra_op_num_threads = 2; + + BOOL appendResult = [sessionOptions appendXnnpackExecutionProviderWithOptions:XnnpackOptions + error:&err]; + // Without xnnpack EP in building also can pass the test + NSString* err_msg = [err localizedDescription]; + if (!appendResult && [err_msg containsString:@"XNNPACK execution provider is not supported in this build. "]) { + return; + } + + ORTAssertBoolResultSuccessful(appendResult, err); + + ORTSession* session = [[ORTSession alloc] initWithEnv:self.ortEnv + modelPath:[ORTSessionTest getAddModelPath] + sessionOptions:sessionOptions + error:&err]; + ORTAssertNullableResultSuccessful(session, err); +} @end NS_ASSUME_NONNULL_END