[Objective-C API] Enable CoreML EP (#7914)

Enable CoreML EP in Objective-C API.
This commit is contained in:
Edward Chen 2021-06-03 18:59:10 -07:00 committed by GitHub
parent ed5fd919ef
commit ab973dce33
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 144 additions and 5 deletions

View file

@ -45,6 +45,7 @@ set(OBJC_ROOT "${REPO_ROOT}/objectivec")
# explicitly list them here so it is easy to see what is included
set(onnxruntime_objc_headers
"${OBJC_ROOT}/include/onnxruntime.h"
"${OBJC_ROOT}/include/ort_coreml_execution_provider.h"
"${OBJC_ROOT}/include/ort_enums.h"
"${OBJC_ROOT}/include/ort_env.h"
"${OBJC_ROOT}/include/ort_session.h"
@ -68,9 +69,15 @@ target_include_directories(onnxruntime_objc
PUBLIC
"${OBJC_ROOT}/include"
PRIVATE
"${ONNXRUNTIME_ROOT}/include/onnxruntime/core/session"
"${ONNXRUNTIME_INCLUDE_DIR}/core/session"
"${OBJC_ROOT}")
if(onnxruntime_USE_COREML)
target_include_directories(onnxruntime_objc
PRIVATE
"${ONNXRUNTIME_INCLUDE_DIR}/core/providers/coreml")
endif()
find_library(FOUNDATION_LIB Foundation REQUIRED)
target_link_libraries(onnxruntime_objc

View file

@ -5,7 +5,7 @@
#include "onnxruntime_c_api.h"
// COREMLFlags are bool options we want to set for CoreML EP
// This enum is defined as bit flats, and cannot have negative value
// This enum is defined as bit flags, and cannot have negative value
// To generate an uint32_t coreml_flags for using with OrtSessionOptionsAppendExecutionProvider_CoreML below,
// uint32_t coreml_flags = 0;
// coreml_flags |= COREML_FLAG_USE_CPU_ONLY;

View file

@ -5,7 +5,7 @@
#include "onnxruntime_c_api.h"
// NNAPIFlags are bool options we want to set for NNAPI EP
// This enum is defined as bit flats, and cannot have negative value
// This enum is defined as bit flags, and cannot have negative value
// To generate an uint32_t nnapi_flags for using with OrtSessionOptionsAppendExecutionProvider_Nnapi below,
// uint32_t nnapi_flags = 0;
// nnapi_flags |= NNAPI_FLAG_USE_FP16;

View file

@ -4,6 +4,7 @@
// this header contains the entire ONNX Runtime Objective-C API
// the headers below can also be imported individually
#import "ort_coreml_execution_provider.h"
#import "ort_enums.h"
#import "ort_env.h"
#import "ort_session.h"

View file

@ -0,0 +1,54 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#import <Foundation/Foundation.h>
#import "ort_session.h"
NS_ASSUME_NONNULL_BEGIN
/**
* Gets whether the CoreML execution provider is available.
*/
BOOL ORTIsCoreMLExecutionProviderAvailable();
/**
* Options for configuring the CoreML execution provider.
*/
@interface ORTCoreMLExecutionProviderOptions : NSObject
/**
* Whether the CoreML execution provider should run on CPU only.
*/
@property BOOL useCPUOnly;
/**
* Whether the CoreML execution provider is enabled on subgraphs.
*/
@property BOOL enableOnSubgraphs;
/**
* Whether the CoreML execution provider is only enabled for devices with Apple
* Neural Engine (ANE).
*/
@property BOOL onlyEnableForDevicesWithANE;
@end
@interface ORTSessionOptions (ORTSessionOptionsCoreMLEP)
/**
* Enables the CoreML execution provider in the session configuration options.
* It is appended to the execution provider list which is ordered by
* decreasing priority.
*
* @param options The CoreML execution provider configuration options.
* @param[out] error Optional error information set if an error occurs.
* @return Whether the provider was enabled successfully.
*/
- (BOOL)appendCoreMLExecutionProviderWithOptions:(ORTCoreMLExecutionProviderOptions*)options
error:(NSError**)error;
@end
NS_ASSUME_NONNULL_END

View file

@ -0,0 +1,53 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#import "ort_coreml_execution_provider.h"
#if __has_include("coreml_provider_factory.h")
#define ORT_OBJC_API_COREML_EP_AVAILABLE 1
#else
#define ORT_OBJC_API_COREML_EP_AVAILABLE 0
#endif
#if ORT_OBJC_API_COREML_EP_AVAILABLE
#include "coreml_provider_factory.h"
#endif
#import "src/error_utils.h"
#import "src/ort_session_internal.h"
NS_ASSUME_NONNULL_BEGIN
BOOL ORTIsCoreMLExecutionProviderAvailable() {
return ORT_OBJC_API_COREML_EP_AVAILABLE ? YES : NO;
}
@implementation ORTCoreMLExecutionProviderOptions
@end
@implementation ORTSessionOptions (ORTSessionOptionsCoreMLEP)
- (BOOL)appendCoreMLExecutionProviderWithOptions:(ORTCoreMLExecutionProviderOptions*)options
error:(NSError**)error {
#if ORT_OBJC_API_COREML_EP_AVAILABLE
try {
const uint32_t flags =
(options.useCPUOnly ? COREML_FLAG_USE_CPU_ONLY : 0) |
(options.enableOnSubgraphs ? COREML_FLAG_ENABLE_ON_SUBGRAPH : 0) |
(options.onlyEnableForDevicesWithANE ? COREML_FLAG_ONLY_ENABLE_DEVICE_WITH_ANE : 0);
Ort::ThrowOnError(OrtSessionOptionsAppendExecutionProvider_CoreML(
[self CXXAPIOrtSessionOptions], flags));
return YES;
}
ORT_OBJC_API_IMPL_CATCH_RETURNING_BOOL(error);
#else // !ORT_OBJC_API_COREML_EP_AVAILABLE
static_cast<void>(options);
ORTSaveCodeAndDescriptionToError(ORT_FAIL, "CoreML execution provider is not enabled.", error);
return NO;
#endif
}
@end
NS_ASSUME_NONNULL_END

View file

@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#import "ort_session_internal.h"
#import "src/ort_session_internal.h"
#include <optional>
#include <vector>

View file

@ -3,6 +3,7 @@
#import <XCTest/XCTest.h>
#import "ort_coreml_execution_provider.h"
#import "ort_env.h"
#import "ort_session.h"
#import "ort_value.h"
@ -191,6 +192,29 @@ NS_ASSUME_NONNULL_BEGIN
ORTAssertBoolResultUnsuccessful(runResult, err);
}
- (void)testAppendCoreMLEP {
NSError* err = nil;
ORTSessionOptions* sessionOptions = [ORTSessionTest makeSessionOptions];
ORTCoreMLExecutionProviderOptions* coreMLOptions = [[ORTCoreMLExecutionProviderOptions alloc] init];
coreMLOptions.enableOnSubgraphs = YES; // set an arbitrary option
BOOL appendResult = [sessionOptions appendCoreMLExecutionProviderWithOptions:coreMLOptions
error:&err];
if (!ORTIsCoreMLExecutionProviderAvailable()) {
ORTAssertBoolResultUnsuccessful(appendResult, err);
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

Binary file not shown.

Binary file not shown.

View file

@ -15,5 +15,5 @@ graph = helper.make_graph(
helper.make_tensor_value_info('C', TensorProto.FLOAT, [1]),
])
model = helper.make_model(graph)
model = helper.make_model(graph, opset_imports=[helper.make_opsetid("", 12)])
onnx.save(model, r'single_add.onnx')