From 19704aedbbd78f6ae53746c0968a7c22a839f5c3 Mon Sep 17 00:00:00 2001 From: Edward Chen <18449977+edgchen1@users.noreply.github.com> Date: Thu, 13 May 2021 18:47:22 -0700 Subject: [PATCH] Update Objective-C API (#7675) - Add session/run configuration - Add additional supported tensor data types - Clean up --- cmake/onnxruntime_objectivec.cmake | 3 +- .../core/session/onnxruntime_c_api.h | 6 +- objectivec/include/ort_enums.h | 15 ++ objectivec/include/ort_session.h | 147 ++++++++++++- objectivec/include/ort_value.h | 2 +- objectivec/src/error_utils.h | 22 +- objectivec/src/error_utils.mm | 6 +- objectivec/src/ort_enums.mm | 38 +++- objectivec/src/ort_enums_internal.h | 2 + objectivec/src/ort_env.mm | 19 +- objectivec/src/ort_session.mm | 199 ++++++++++++++++-- objectivec/src/ort_session_internal.h | 22 ++ objectivec/src/ort_value.mm | 51 ++--- objectivec/test/ort_session_test.mm | 25 ++- objectivec/test/ort_value_test.mm | 4 +- 15 files changed, 478 insertions(+), 83 deletions(-) create mode 100644 objectivec/src/ort_session_internal.h diff --git a/cmake/onnxruntime_objectivec.cmake b/cmake/onnxruntime_objectivec.cmake index 2e86cc9e8c..3524bcf9a3 100644 --- a/cmake/onnxruntime_objectivec.cmake +++ b/cmake/onnxruntime_objectivec.cmake @@ -40,7 +40,8 @@ set(onnxruntime_objc_headers "${OBJC_ROOT}/include/ort_enums.h" "${OBJC_ROOT}/include/ort_env.h" "${OBJC_ROOT}/include/ort_session.h" - "${OBJC_ROOT}/include/ort_value.h") + "${OBJC_ROOT}/include/ort_value.h" + ) file(GLOB onnxruntime_objc_srcs "${OBJC_ROOT}/src/*.h" diff --git a/include/onnxruntime/core/session/onnxruntime_c_api.h b/include/onnxruntime/core/session/onnxruntime_c_api.h index f6178f1788..78110d84ad 100644 --- a/include/onnxruntime/core/session/onnxruntime_c_api.h +++ b/include/onnxruntime/core/session/onnxruntime_c_api.h @@ -206,9 +206,9 @@ typedef void(ORT_API_CALL* OrtLoggingFunction)( void* param, OrtLoggingLevel severity, const char* category, const char* logid, const char* code_location, const char* message); -// Set Graph optimization level. -// Refer https://github.com/microsoft/onnxruntime/blob/master/docs/ONNX_Runtime_Graph_Optimizations.md -// for in-depth undersrtanding of Graph Optimizations in ORT +// Graph optimization level. +// Refer to https://www.onnxruntime.ai/docs/resources/graph-optimizations.html +// for an in-depth understanding of Graph Optimizations in ORT typedef enum GraphOptimizationLevel { ORT_DISABLE_ALL = 0, ORT_ENABLE_BASIC = 1, diff --git a/objectivec/include/ort_enums.h b/objectivec/include/ort_enums.h index 84fee5c4d1..040b50f2c3 100644 --- a/objectivec/include/ort_enums.h +++ b/objectivec/include/ort_enums.h @@ -32,7 +32,22 @@ typedef NS_ENUM(int32_t, ORTValueType) { typedef NS_ENUM(int32_t, ORTTensorElementDataType) { ORTTensorElementDataTypeUndefined, ORTTensorElementDataTypeFloat, + ORTTensorElementDataTypeInt8, + ORTTensorElementDataTypeUInt8, ORTTensorElementDataTypeInt32, + ORTTensorElementDataTypeUInt32, +}; + +/** + * The ORT graph optimization levels. + * See here for more details: + * https://www.onnxruntime.ai/docs/resources/graph-optimizations.html + */ +typedef NS_ENUM(int32_t, ORTGraphOptimizationLevel) { + ORTGraphOptimizationLevelNone, + ORTGraphOptimizationLevelBasic, + ORTGraphOptimizationLevelExtended, + ORTGraphOptimizationLevelAll, }; NS_ASSUME_NONNULL_END diff --git a/objectivec/include/ort_session.h b/objectivec/include/ort_session.h index 9d6f1fec97..08a24e5cc3 100644 --- a/objectivec/include/ort_session.h +++ b/objectivec/include/ort_session.h @@ -3,9 +3,13 @@ #import +#import "ort_enums.h" + NS_ASSUME_NONNULL_BEGIN @class ORTEnv; +@class ORTRunOptions; +@class ORTSessionOptions; @class ORTValue; /** @@ -16,15 +20,17 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)init NS_UNAVAILABLE; /** - * Creates an ORT Session. + * Creates a session. * * @param env The ORT Environment instance. * @param path The path to the ONNX model. + * @param sessionOptions Optional session configuration options. * @param[out] error Optional error information set if an error occurs. * @return The instance, or nil if an error occurs. */ - (nullable instancetype)initWithEnv:(ORTEnv*)env modelPath:(NSString*)path + sessionOptions:(nullable ORTSessionOptions*)sessionOptions error:(NSError**)error NS_DESIGNATED_INITIALIZER; /** @@ -33,11 +39,13 @@ NS_ASSUME_NONNULL_BEGIN * * @param inputs Dictionary of input names to input ORT values. * @param outputs Dictionary of output names to output ORT values. + * @param runOptions Optional run configuration options. * @param[out] error Optional error information set if an error occurs. * @return Whether the model was run successfully. */ - (BOOL)runWithInputs:(NSDictionary*)inputs outputs:(NSDictionary*)outputs + runOptions:(nullable ORTRunOptions*)runOptions error:(NSError**)error; /** @@ -46,14 +54,151 @@ NS_ASSUME_NONNULL_BEGIN * * @param inputs Dictionary of input names to input ORT values. * @param outputNames Set of output names. + * @param runOptions Optional run configuration options. * @param[out] error Optional error information set if an error occurs. * @return A dictionary of output names to output ORT values with the outputs * requested in `outputNames`, or nil if an error occurs. */ - (nullable NSDictionary*)runWithInputs:(NSDictionary*)inputs outputNames:(NSSet*)outputNames + runOptions:(nullable ORTRunOptions*)runOptions error:(NSError**)error; @end +/** + * Options for configuring a session. + */ +@interface ORTSessionOptions : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +/** + * Creates session configuration options. + * + * @param[out] error Optional error information set if an error occurs. + * @return The instance, or nil if an error occurs. + */ +- (nullable instancetype)initWithError:(NSError**)error NS_SWIFT_NAME(init()); + +/** + * Sets the number of threads used to parallelize the execution within nodes. + * A value of 0 means ORT will pick a default value. + * + * @param intraOpNumThreads The number of threads. + * @param[out] error Optional error information set if an error occurs. + * @return Whether the option was set successfully. + */ +- (BOOL)setIntraOpNumThreads:(int)intraOpNumThreads + error:(NSError**)error; + +/** + * Sets the graph optimization level. + * + * @param graphOptimizationLevel The graph optimization level. + * @param[out] error Optional error information set if an error occurs. + * @return Whether the option was set successfully. + */ +- (BOOL)setGraphOptimizationLevel:(ORTGraphOptimizationLevel)graphOptimizationLevel + error:(NSError**)error; + +/** + * Sets the path to which the optimized model file will be saved. + * + * @param optimizedModelFilePath The optimized model file path. + * @param[out] error Optional error information set if an error occurs. + * @return Whether the option was set successfully. + */ +- (BOOL)setOptimizedModelFilePath:(NSString*)optimizedModelFilePath + error:(NSError**)error; + +/** + * Sets the session log ID. + * + * @param logID The log ID. + * @param[out] error Optional error information set if an error occurs. + * @return Whether the option was set successfully. + */ +- (BOOL)setLogID:(NSString*)logID + error:(NSError**)error; + +/** + * Sets the session log severity level. + * + * @param loggingLevel The log severity level. + * @param[out] error Optional error information set if an error occurs. + * @return Whether the option was set successfully. + */ +- (BOOL)setLogSeverityLevel:(ORTLoggingLevel)loggingLevel + error:(NSError**)error; + +/** + * Sets a session configuration key-value pair. + * Any value for a previously set key will be overwritten. + * The session configuration keys and values are documented here: + * https://github.com/microsoft/onnxruntime/blob/master/include/onnxruntime/core/session/onnxruntime_session_options_config_keys.h + * + * @param key The key. + * @param value The value. + * @param[out] error Optional error information set if an error occurs. + * @return Whether the option was set successfully. + */ +- (BOOL)addConfigEntryWithKey:(NSString*)key + value:(NSString*)value + error:(NSError**)error; + +@end + +/** + * Options for configuring a run. + */ +@interface ORTRunOptions : NSObject + +- (instancetype)init NS_UNAVAILABLE; + +/** + * Creates run configuration options. + * + * @param[out] error Optional error information set if an error occurs. + * @return The instance, or nil if an error occurs. + */ +- (nullable instancetype)initWithError:(NSError**)error NS_SWIFT_NAME(init()); + +/** + * Sets the run log tag. + * + * @param logTag The log tag. + * @param[out] error Optional error information set if an error occurs. + * @return Whether the option was set successfully. + */ +- (BOOL)setLogTag:(NSString*)logTag + error:(NSError**)error; + +/** + * Sets the run log severity level. + * + * @param loggingLevel The log severity level. + * @param[out] error Optional error information set if an error occurs. + * @return Whether the option was set successfully. + */ +- (BOOL)setLogSeverityLevel:(ORTLoggingLevel)loggingLevel + error:(NSError**)error; + +/** + * Sets a run configuration key-value pair. + * Any value for a previously set key will be overwritten. + * The run configuration keys and values are documented here: + * https://github.com/microsoft/onnxruntime/blob/master/include/onnxruntime/core/session/onnxruntime_run_options_config_keys.h + * + * @param key The key. + * @param value The value. + * @param[out] error Optional error information set if an error occurs. + * @return Whether the option was set successfully. + */ +- (BOOL)addConfigEntryWithKey:(NSString*)key + value:(NSString*)value + error:(NSError**)error; + +@end + NS_ASSUME_NONNULL_END diff --git a/objectivec/include/ort_value.h b/objectivec/include/ort_value.h index cdcbe0a34f..cb211d203a 100644 --- a/objectivec/include/ort_value.h +++ b/objectivec/include/ort_value.h @@ -27,7 +27,7 @@ NS_ASSUME_NONNULL_BEGIN * @param[out] error Optional error information set if an error occurs. * @return The instance, or nil if an error occurs. */ -- (nullable instancetype)initTensorWithData:(NSMutableData*)tensorData +- (nullable instancetype)initWithTensorData:(NSMutableData*)tensorData elementType:(ORTTensorElementDataType)elementType shape:(NSArray*)shape error:(NSError**)error; diff --git a/objectivec/src/error_utils.h b/objectivec/src/error_utils.h index 4e39f71091..7b9fc8997c 100644 --- a/objectivec/src/error_utils.h +++ b/objectivec/src/error_utils.h @@ -3,11 +3,31 @@ #import +#include + #include "core/session/onnxruntime_cxx_api.h" NS_ASSUME_NONNULL_BEGIN void ORTSaveCodeAndDescriptionToError(int code, const char* description, NSError** error); -void ORTSaveExceptionToError(const Ort::Exception& e, NSError** error); +void ORTSaveOrtExceptionToError(const Ort::Exception& e, NSError** error); +void ORTSaveExceptionToError(const std::exception& e, NSError** error); + +// helper macros to catch and handle C++ exceptions +#define ORT_OBJC_API_IMPL_CATCH(error, failure_return_value) \ + catch (const Ort::Exception& e) { \ + ORTSaveOrtExceptionToError(e, (error)); \ + return (failure_return_value); \ + } \ + catch (const std::exception& e) { \ + ORTSaveExceptionToError(e, (error)); \ + return (failure_return_value); \ + } + +#define ORT_OBJC_API_IMPL_CATCH_RETURNING_BOOL(error) \ + ORT_OBJC_API_IMPL_CATCH(error, NO) + +#define ORT_OBJC_API_IMPL_CATCH_RETURNING_NULLABLE(error) \ + ORT_OBJC_API_IMPL_CATCH(error, nil) NS_ASSUME_NONNULL_END diff --git a/objectivec/src/error_utils.mm b/objectivec/src/error_utils.mm index ae1124528a..6ab7f0234e 100644 --- a/objectivec/src/error_utils.mm +++ b/objectivec/src/error_utils.mm @@ -18,8 +18,12 @@ void ORTSaveCodeAndDescriptionToError(int code, const char* descriptionCstr, NSE userInfo:@{NSLocalizedDescriptionKey : description}]; } -void ORTSaveExceptionToError(const Ort::Exception& e, NSError** error) { +void ORTSaveOrtExceptionToError(const Ort::Exception& e, NSError** error) { ORTSaveCodeAndDescriptionToError(e.GetOrtErrorCode(), e.what(), error); } +void ORTSaveExceptionToError(const std::exception& e, NSError** error) { + ORTSaveCodeAndDescriptionToError(ORT_RUNTIME_EXCEPTION, e.what(), error); +} + NS_ASSUME_NONNULL_END diff --git a/objectivec/src/ort_enums.mm b/objectivec/src/ort_enums.mm index 458c607659..6aea7d107a 100644 --- a/objectivec/src/ort_enums.mm +++ b/objectivec/src/ort_enums.mm @@ -43,12 +43,28 @@ struct TensorElementTypeInfo { }; // supported ORT tensor element data types -// define the mapping from ORTTensorElementDataType to C API -// ONNXTensorElementDataType here +// define the mapping from ORTTensorElementDataType to C API ONNXTensorElementDataType here constexpr TensorElementTypeInfo kElementTypeInfos[]{ {ORTTensorElementDataTypeUndefined, ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED, 0}, {ORTTensorElementDataTypeFloat, ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, sizeof(float)}, + {ORTTensorElementDataTypeInt8, ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8, sizeof(int8_t)}, + {ORTTensorElementDataTypeUInt8, ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8, sizeof(uint8_t)}, {ORTTensorElementDataTypeInt32, ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32, sizeof(int32_t)}, + {ORTTensorElementDataTypeUInt32, ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32, sizeof(uint32_t)}, +}; + +struct GraphOptimizationLevelInfo { + ORTGraphOptimizationLevel opt_level; + GraphOptimizationLevel capi_opt_level; +}; + +// ORT graph optimization levels +// define the mapping from ORTGraphOptimizationLevel to C API GraphOptimizationLevel here +constexpr GraphOptimizationLevelInfo kGraphOptimizationLevelInfos[]{ + {ORTGraphOptimizationLevelNone, ORT_DISABLE_ALL}, + {ORTGraphOptimizationLevelBasic, ORT_ENABLE_BASIC}, + {ORTGraphOptimizationLevelExtended, ORT_ENABLE_EXTENDED}, + {ORTGraphOptimizationLevelAll, ORT_ENABLE_ALL}, }; template @@ -59,7 +75,7 @@ auto SelectAndTransform( const auto it = std::find_if( std::begin(container), std::end(container), select_fn); if (it == std::end(container)) { - throw Ort::Exception{not_found_msg, ORT_NOT_IMPLEMENTED}; + ORT_CXX_API_THROW(not_found_msg, ORT_NOT_IMPLEMENTED); } return transform_fn(*it); } @@ -69,12 +85,8 @@ auto SelectAndTransform( OrtLoggingLevel PublicToCAPILoggingLevel(ORTLoggingLevel logging_level) { return SelectAndTransform( kLoggingLevelInfos, - [logging_level](const auto& logging_level_info) { - return logging_level_info.logging_level == logging_level; - }, - [](const auto& logging_level_info) { - return logging_level_info.capi_logging_level; - }, + [logging_level](const auto& logging_level_info) { return logging_level_info.logging_level == logging_level; }, + [](const auto& logging_level_info) { return logging_level_info.capi_logging_level; }, "unsupported logging level"); } @@ -109,3 +121,11 @@ size_t SizeOfCAPITensorElementType(ONNXTensorElementDataType capi_type) { [](const auto& type_info) { return type_info.element_size; }, "unsupported tensor element type"); } + +GraphOptimizationLevel PublicToCAPIGraphOptimizationLevel(ORTGraphOptimizationLevel opt_level) { + return SelectAndTransform( + kGraphOptimizationLevelInfos, + [opt_level](const auto& opt_level_info) { return opt_level_info.opt_level == opt_level; }, + [](const auto& opt_level_info) { return opt_level_info.capi_opt_level; }, + "unsupported graph optimization level"); +} diff --git a/objectivec/src/ort_enums_internal.h b/objectivec/src/ort_enums_internal.h index afb86817ca..07f85cc296 100644 --- a/objectivec/src/ort_enums_internal.h +++ b/objectivec/src/ort_enums_internal.h @@ -13,3 +13,5 @@ ONNXTensorElementDataType PublicToCAPITensorElementType(ORTTensorElementDataType ORTTensorElementDataType CAPIToPublicTensorElementType(ONNXTensorElementDataType capi_type); size_t SizeOfCAPITensorElementType(ONNXTensorElementDataType capi_type); + +GraphOptimizationLevel PublicToCAPIGraphOptimizationLevel(ORTGraphOptimizationLevel opt_level); diff --git a/objectivec/src/ort_env.mm b/objectivec/src/ort_env.mm index 6379a4e111..c218cca79f 100644 --- a/objectivec/src/ort_env.mm +++ b/objectivec/src/ort_env.mm @@ -18,17 +18,16 @@ NS_ASSUME_NONNULL_BEGIN - (nullable instancetype)initWithLoggingLevel:(ORTLoggingLevel)loggingLevel error:(NSError**)error { - self = [super init]; - if (self) { - try { - const auto CAPILoggingLevel = PublicToCAPILoggingLevel(loggingLevel); - _env = Ort::Env{CAPILoggingLevel}; - } catch (const Ort::Exception& e) { - ORTSaveExceptionToError(e, error); - self = nil; - } + if ((self = [super init]) == nil) { + return nil; } - return self; + + try { + const auto CAPILoggingLevel = PublicToCAPILoggingLevel(loggingLevel); + _env = Ort::Env{CAPILoggingLevel}; + return self; + } + ORT_OBJC_API_IMPL_CATCH_RETURNING_NULLABLE(error) } - (Ort::Env&)CXXAPIOrtEnv { diff --git a/objectivec/src/ort_session.mm b/objectivec/src/ort_session.mm index 27414934ed..b3be3bcf6a 100644 --- a/objectivec/src/ort_session.mm +++ b/objectivec/src/ort_session.mm @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -#import "ort_session.h" +#import "ort_session_internal.h" #include #include @@ -9,6 +9,7 @@ #include "core/session/onnxruntime_cxx_api.h" #import "src/error_utils.h" +#import "src/ort_enums_internal.h" #import "src/ort_env_internal.h" #import "src/ort_value_internal.h" @@ -20,26 +21,40 @@ NS_ASSUME_NONNULL_BEGIN - (nullable instancetype)initWithEnv:(ORTEnv*)env modelPath:(NSString*)path + sessionOptions:(nullable ORTSessionOptions*)sessionOptions error:(NSError**)error { - self = [super init]; - if (self) { - try { - Ort::SessionOptions sessionOptions{}; // TODO make configurable - _session = Ort::Session{[env CXXAPIOrtEnv], path.UTF8String, sessionOptions}; - } catch (const Ort::Exception& e) { - ORTSaveExceptionToError(e, error); - self = nil; - } + if ((self = [super init]) == nil) { + return nil; } - return self; + + try { + if (!sessionOptions) { + sessionOptions = [[ORTSessionOptions alloc] initWithError:error]; + if (!sessionOptions) { + return nil; + } + } + + _session = Ort::Session{[env CXXAPIOrtEnv], + path.UTF8String, + [sessionOptions CXXAPIOrtSessionOptions]}; + + return self; + } + ORT_OBJC_API_IMPL_CATCH_RETURNING_NULLABLE(error) } - (BOOL)runWithInputs:(NSDictionary*)inputs outputs:(NSDictionary*)outputs + runOptions:(nullable ORTRunOptions*)runOptions error:(NSError**)error { - BOOL status = NO; try { - Ort::RunOptions runOptions{}; // TODO make configurable + if (!runOptions) { + runOptions = [[ORTRunOptions alloc] initWithError:error]; + if (!runOptions) { + return NO; + } + } std::vector inputNames, outputNames; std::vector inputValues; @@ -55,24 +70,28 @@ NS_ASSUME_NONNULL_BEGIN outputValues.push_back(static_cast([outputs[outputName] CXXAPIOrtValue])); } - Ort::ThrowOnError(Ort::GetApi().Run(*_session, runOptions, + Ort::ThrowOnError(Ort::GetApi().Run(*_session, [runOptions CXXAPIOrtRunOptions], inputNames.data(), inputValues.data(), inputNames.size(), outputNames.data(), outputNames.size(), outputValues.data())); - status = YES; - } catch (const Ort::Exception& e) { - ORTSaveExceptionToError(e, error); + return YES; } - return status; + ORT_OBJC_API_IMPL_CATCH_RETURNING_BOOL(error) } - (nullable NSDictionary*)runWithInputs:(NSDictionary*)inputs outputNames:(NSSet*)outputNameSet + runOptions:(nullable ORTRunOptions*)runOptions error:(NSError**)error { try { - NSArray* outputNameArray = outputNameSet.allObjects; + if (!runOptions) { + runOptions = [[ORTRunOptions alloc] initWithError:error]; + if (!runOptions) { + return nil; + } + } - Ort::RunOptions runOptions{}; // TODO make configurable + NSArray* outputNameArray = outputNameSet.allObjects; std::vector inputNames, outputNames; std::vector inputValues; @@ -88,7 +107,7 @@ NS_ASSUME_NONNULL_BEGIN outputValues.push_back(nullptr); } - Ort::ThrowOnError(Ort::GetApi().Run(*_session, runOptions, + Ort::ThrowOnError(Ort::GetApi().Run(*_session, [runOptions CXXAPIOrtRunOptions], inputNames.data(), inputValues.data(), inputNames.size(), outputNames.data(), outputNames.size(), outputValues.data())); @@ -107,10 +126,144 @@ NS_ASSUME_NONNULL_BEGIN } return outputs; - } catch (const Ort::Exception& e) { - ORTSaveExceptionToError(e, error); + } + ORT_OBJC_API_IMPL_CATCH_RETURNING_NULLABLE(error) +} + +@end + +@implementation ORTSessionOptions { + std::optional _sessionOptions; +} + +#pragma mark - Public + +- (nullable instancetype)initWithError:(NSError**)error { + if ((self = [super init]) == nil) { return nil; } + + try { + _sessionOptions = Ort::SessionOptions{}; + return self; + } + ORT_OBJC_API_IMPL_CATCH_RETURNING_NULLABLE(error) +} + +- (BOOL)setIntraOpNumThreads:(int)intraOpNumThreads + error:(NSError**)error { + try { + _sessionOptions->SetIntraOpNumThreads(intraOpNumThreads); + return YES; + } + ORT_OBJC_API_IMPL_CATCH_RETURNING_BOOL(error) +} + +- (BOOL)setGraphOptimizationLevel:(ORTGraphOptimizationLevel)graphOptimizationLevel + error:(NSError**)error { + try { + _sessionOptions->SetGraphOptimizationLevel( + PublicToCAPIGraphOptimizationLevel(graphOptimizationLevel)); + return YES; + } + ORT_OBJC_API_IMPL_CATCH_RETURNING_BOOL(error) +} + +- (BOOL)setOptimizedModelFilePath:(NSString*)optimizedModelFilePath + error:(NSError**)error { + try { + _sessionOptions->SetOptimizedModelFilePath(optimizedModelFilePath.UTF8String); + return YES; + } + ORT_OBJC_API_IMPL_CATCH_RETURNING_BOOL(error) +} + +- (BOOL)setLogID:(NSString*)logID + error:(NSError**)error { + try { + _sessionOptions->SetLogId(logID.UTF8String); + return YES; + } + ORT_OBJC_API_IMPL_CATCH_RETURNING_BOOL(error) +} + +- (BOOL)setLogSeverityLevel:(ORTLoggingLevel)loggingLevel + error:(NSError**)error { + try { + _sessionOptions->SetLogSeverityLevel(PublicToCAPILoggingLevel(loggingLevel)); + return YES; + } + ORT_OBJC_API_IMPL_CATCH_RETURNING_BOOL(error) +} + +- (BOOL)addConfigEntryWithKey:(NSString*)key + value:(NSString*)value + error:(NSError**)error { + try { + _sessionOptions->AddConfigEntry(key.UTF8String, value.UTF8String); + return YES; + } + ORT_OBJC_API_IMPL_CATCH_RETURNING_BOOL(error) +} + +#pragma mark - Internal + +- (Ort::SessionOptions&)CXXAPIOrtSessionOptions { + return *_sessionOptions; +} + +@end + +@implementation ORTRunOptions { + std::optional _runOptions; +} + +#pragma mark - Public + +- (nullable instancetype)initWithError:(NSError**)error { + if ((self = [super init]) == nil) { + return nil; + } + + try { + _runOptions = Ort::RunOptions{}; + return self; + } + ORT_OBJC_API_IMPL_CATCH_RETURNING_NULLABLE(error) +} + +- (BOOL)setLogTag:(NSString*)logTag + error:(NSError**)error { + try { + _runOptions->SetRunTag(logTag.UTF8String); + return YES; + } + ORT_OBJC_API_IMPL_CATCH_RETURNING_BOOL(error) +} + +- (BOOL)setLogSeverityLevel:(ORTLoggingLevel)loggingLevel + error:(NSError**)error { + try { + _runOptions->SetRunLogSeverityLevel(PublicToCAPILoggingLevel(loggingLevel)); + return YES; + } + ORT_OBJC_API_IMPL_CATCH_RETURNING_BOOL(error) +} + +- (BOOL)addConfigEntryWithKey:(NSString*)key + value:(NSString*)value + error:(NSError**)error { + try { + _runOptions->AddConfigEntry(key.UTF8String, value.UTF8String); + return YES; + } + ORT_OBJC_API_IMPL_CATCH_RETURNING_BOOL(error) +} + +#pragma mark - Internal + +- (Ort::RunOptions&)CXXAPIOrtRunOptions { + return *_runOptions; } @end diff --git a/objectivec/src/ort_session_internal.h b/objectivec/src/ort_session_internal.h new file mode 100644 index 0000000000..a286e9f00a --- /dev/null +++ b/objectivec/src/ort_session_internal.h @@ -0,0 +1,22 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#import "ort_session.h" + +#include "core/session/onnxruntime_cxx_api.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface ORTSessionOptions () + +- (Ort::SessionOptions&)CXXAPIOrtSessionOptions; + +@end + +@interface ORTRunOptions () + +- (Ort::RunOptions&)CXXAPIOrtRunOptions; + +@end + +NS_ASSUME_NONNULL_END diff --git a/objectivec/src/ort_value.mm b/objectivec/src/ort_value.mm index bace8730c0..cc056c7548 100644 --- a/objectivec/src/ort_value.mm +++ b/objectivec/src/ort_value.mm @@ -61,9 +61,9 @@ ORTValueTypeInfo* CXXAPIToPublicValueTypeInfo( std::optional _typeInfo; } -#pragma mark Public +#pragma mark - Public -- (nullable instancetype)initTensorWithData:(NSMutableData*)tensorData +- (nullable instancetype)initWithTensorData:(NSMutableData*)tensorData elementType:(ORTTensorElementDataType)elementType shape:(NSArray*)shape error:(NSError**)error { @@ -82,34 +82,26 @@ ORTValueTypeInfo* CXXAPIToPublicValueTypeInfo( memoryInfo, tensorData.mutableBytes, tensorData.length, shapeVector.data(), shapeVector.size(), ONNXElementType); - self = [self initWithCAPIOrtValue:ortValue.release() + return [self initWithCAPIOrtValue:ortValue.release() externalTensorData:tensorData error:error]; - } catch (const Ort::Exception& e) { - ORTSaveExceptionToError(e, error); - self = nil; } - - return self; + ORT_OBJC_API_IMPL_CATCH_RETURNING_NULLABLE(error) } - (nullable ORTValueTypeInfo*)typeInfoWithError:(NSError**)error { try { return CXXAPIToPublicValueTypeInfo(*_typeInfo); - } catch (const Ort::Exception& e) { - ORTSaveExceptionToError(e, error); - return nil; } + ORT_OBJC_API_IMPL_CATCH_RETURNING_NULLABLE(error) } - (nullable ORTTensorTypeAndShapeInfo*)tensorTypeAndShapeInfoWithError:(NSError**)error { try { const auto tensorTypeAndShapeInfo = _typeInfo->GetTensorTypeAndShapeInfo(); return CXXAPIToPublicTensorTypeAndShapeInfo(tensorTypeAndShapeInfo); - } catch (const Ort::Exception& e) { - ORTSaveExceptionToError(e, error); - return nil; } + ORT_OBJC_API_IMPL_CATCH_RETURNING_NULLABLE(error) } - (nullable NSMutableData*)tensorDataWithError:(NSError**)error { @@ -119,36 +111,35 @@ ORTValueTypeInfo* CXXAPIToPublicValueTypeInfo( const size_t elementSize = SizeOfCAPITensorElementType(tensorTypeAndShapeInfo.GetElementType()); size_t rawDataLength; if (!SafeMultiply(elementCount, elementSize, rawDataLength)) { - throw Ort::Exception{"failed to compute tensor data length", ORT_RUNTIME_EXCEPTION}; + ORT_CXX_API_THROW("failed to compute tensor data length", ORT_RUNTIME_EXCEPTION); } + void* rawData; Ort::ThrowOnError(Ort::GetApi().GetTensorMutableData(*_value, &rawData)); + return [NSMutableData dataWithBytesNoCopy:rawData length:rawDataLength freeWhenDone:NO]; - } catch (const Ort::Exception& e) { - ORTSaveExceptionToError(e, error); - return nil; } + ORT_OBJC_API_IMPL_CATCH_RETURNING_NULLABLE(error) } -#pragma mark Internal +#pragma mark - Internal - (nullable instancetype)initWithCAPIOrtValue:(OrtValue*)CAPIOrtValue externalTensorData:(nullable NSMutableData*)externalTensorData error:(NSError**)error { - self = [super init]; - if (self) { - try { - _value = Ort::Value{CAPIOrtValue}; - _typeInfo = _value->GetTypeInfo(); - _externalTensorData = externalTensorData; - } catch (const Ort::Exception& e) { - ORTSaveExceptionToError(e, error); - self = nil; - } + if ((self = [super init]) == nil) { + return nil; } - return self; + + try { + _value = Ort::Value{CAPIOrtValue}; + _typeInfo = _value->GetTypeInfo(); + _externalTensorData = externalTensorData; + return self; + } + ORT_OBJC_API_IMPL_CATCH_RETURNING_NULLABLE(error); } - (Ort::Value&)CXXAPIOrtValue { diff --git a/objectivec/test/ort_session_test.mm b/objectivec/test/ort_session_test.mm index 8145add932..ef4c434a28 100644 --- a/objectivec/test/ort_session_test.mm +++ b/objectivec/test/ort_session_test.mm @@ -56,7 +56,7 @@ NS_ASSUME_NONNULL_BEGIN + (ORTValue*)ortValueWithScalarFloatData:(NSMutableData*)data { NSArray* shape = @[ @1 ]; NSError* err = nil; - ORTValue* ortValue = [[ORTValue alloc] initTensorWithData:data + ORTValue* ortValue = [[ORTValue alloc] initWithTensorData:data elementType:ORTTensorElementDataTypeFloat shape:shape error:&err]; @@ -65,6 +65,22 @@ NS_ASSUME_NONNULL_BEGIN return ortValue; } ++ (ORTSessionOptions*)makeSessionOptions { + NSError* err = nil; + ORTSessionOptions* sessionOptions = [[ORTSessionOptions alloc] initWithError:&err]; + XCTAssertNotNil(sessionOptions); + XCTAssertNil(err); + return sessionOptions; +} + ++ (ORTRunOptions*)makeRunOptions { + NSError* err = nil; + ORTRunOptions* runOptions = [[ORTRunOptions alloc] initWithError:&err]; + XCTAssertNotNil(runOptions); + XCTAssertNil(err); + return runOptions; +} + - (void)testInitAndRunWithPreallocatedOutputOk { NSMutableData* aData = [ORTSessionTest dataWithScalarFloat:1.0f]; NSMutableData* bData = [ORTSessionTest dataWithScalarFloat:2.0f]; @@ -77,12 +93,14 @@ NS_ASSUME_NONNULL_BEGIN NSError* err = nil; ORTSession* session = [[ORTSession alloc] initWithEnv:self.ortEnv modelPath:[ORTSessionTest getAddModelPath] + sessionOptions:[ORTSessionTest makeSessionOptions] error:&err]; XCTAssertNotNil(session); XCTAssertNil(err); BOOL runResult = [session runWithInputs:@{@"A" : a, @"B" : b} outputs:@{@"C" : c} + runOptions:[ORTSessionTest makeRunOptions] error:&err]; XCTAssertTrue(runResult); XCTAssertNil(err); @@ -103,6 +121,7 @@ NS_ASSUME_NONNULL_BEGIN NSError* err = nil; ORTSession* session = [[ORTSession alloc] initWithEnv:self.ortEnv modelPath:[ORTSessionTest getAddModelPath] + sessionOptions:[ORTSessionTest makeSessionOptions] error:&err]; XCTAssertNotNil(session); XCTAssertNil(err); @@ -110,6 +129,7 @@ NS_ASSUME_NONNULL_BEGIN NSDictionary* outputs = [session runWithInputs:@{@"A" : a, @"B" : b} outputNames:[NSSet setWithArray:@[ @"C" ]] + runOptions:[ORTSessionTest makeRunOptions] error:&err]; XCTAssertNotNil(outputs); XCTAssertNil(err); @@ -132,6 +152,7 @@ NS_ASSUME_NONNULL_BEGIN NSError* err = nil; ORTSession* session = [[ORTSession alloc] initWithEnv:self.ortEnv modelPath:invalidModelPath + sessionOptions:[ORTSessionTest makeSessionOptions] error:&err]; XCTAssertNil(session); XCTAssertNotNil(err); @@ -147,12 +168,14 @@ NS_ASSUME_NONNULL_BEGIN NSError* err = nil; ORTSession* session = [[ORTSession alloc] initWithEnv:self.ortEnv modelPath:[ORTSessionTest getAddModelPath] + sessionOptions:[ORTSessionTest makeSessionOptions] error:&err]; XCTAssertNotNil(session); XCTAssertNil(err); BOOL runResult = [session runWithInputs:@{@"D" : d} outputs:@{@"C" : c} + runOptions:[ORTSessionTest makeRunOptions] error:&err]; XCTAssertFalse(runResult); XCTAssertNotNil(err); diff --git a/objectivec/test/ort_value_test.mm b/objectivec/test/ort_value_test.mm index f9950a8cdc..09ecff7f64 100644 --- a/objectivec/test/ort_value_test.mm +++ b/objectivec/test/ort_value_test.mm @@ -29,7 +29,7 @@ NS_ASSUME_NONNULL_BEGIN const ORTTensorElementDataType elementType = ORTTensorElementDataTypeInt32; NSError* err = nil; - ORTValue* ortValue = [[ORTValue alloc] initTensorWithData:data + ORTValue* ortValue = [[ORTValue alloc] initWithTensorData:data elementType:elementType shape:shape error:&err]; @@ -69,7 +69,7 @@ NS_ASSUME_NONNULL_BEGIN NSArray* shape = @[ @2, @3 ]; // too large NSError* err = nil; - ORTValue* ortValue = [[ORTValue alloc] initTensorWithData:data + ORTValue* ortValue = [[ORTValue alloc] initWithTensorData:data elementType:ORTTensorElementDataTypeInt32 shape:shape error:&err];