diff --git a/Package.swift b/Package.swift index 24034c3..791fa8e 100644 --- a/Package.swift +++ b/Package.swift @@ -96,21 +96,21 @@ if let pod_archive_path = ProcessInfo.processInfo.environment["ORT_IOS_POD_LOCAL package.targets.append(Target.binaryTarget(name: "onnxruntime", path: pod_archive_path)) } else { - // ORT 1.17.0 release + // ORT 1.18.0 release package.targets.append( Target.binaryTarget(name: "onnxruntime", - url: "https://onnxruntimepackages.z14.web.core.windows.net/pod-archive-onnxruntime-c-1.17.0.zip", - checksum: "1623e1150507d9e50554e3d3e5cf9abf75e1bfd8324b74a602acfe45343db871") + url: "https://download.onnxruntime.ai/pod-archive-onnxruntime-c-1.18.0.zip", + checksum: "9f196b7d09129177f529be63a91e18731ab1ccc830828e29edcbe95bd652fa5c") ) } if let ext_pod_archive_path = ProcessInfo.processInfo.environment["ORT_EXTENSIONS_IOS_POD_LOCAL_PATH"] { package.targets.append(Target.binaryTarget(name: "onnxruntime_extensions", path: ext_pod_archive_path)) } else { - // ORT Extensions 0.10.0 release + // ORT Extensions 0.11.0 release package.targets.append( Target.binaryTarget(name: "onnxruntime_extensions", - url: "https://onnxruntimepackages.z14.web.core.windows.net/pod-archive-onnxruntime-extensions-c-0.10.0.zip", - checksum: "c0fbe30bcf898b0f7428e913918803372ba986ed9c662c1b8300ceaff3f442e0") + url: "https://download.onnxruntime.ai/pod-archive-onnxruntime-extensions-c-0.11.0.zip", + checksum: "289e8b7847116744946003ed21e1ac9ee4897c3aca48e261238e329634c27c0a") ) } \ No newline at end of file diff --git a/objectivec/include/ort_coreml_execution_provider.h b/objectivec/include/ort_coreml_execution_provider.h index a015b6f..6ff1817 100644 --- a/objectivec/include/ort_coreml_execution_provider.h +++ b/objectivec/include/ort_coreml_execution_provider.h @@ -41,6 +41,17 @@ NS_ASSUME_NONNULL_BEGIN */ @property BOOL onlyEnableForDevicesWithANE; +/** + * Only allow CoreML EP to take nodes with inputs with static shapes. By default it will also allow inputs with + * dynamic shapes. However, the performance may be negatively impacted if inputs have dynamic shapes. + */ +@property BOOL onlyAllowStaticInputShapes; + +/** + * Create an MLProgram. By default it will create a NeuralNetwork model. Requires Core ML 5 or later. + */ +@property BOOL createMLProgram; + @end @interface ORTSessionOptions (ORTSessionOptionsCoreMLEP) diff --git a/objectivec/include/ort_env.h b/objectivec/include/ort_env.h index 8456b57..67db766 100644 --- a/objectivec/include/ort_env.h +++ b/objectivec/include/ort_env.h @@ -24,6 +24,9 @@ NSString* _Nullable ORTVersion(void); /** * The ORT environment. + * It maintains shared state including the default logger. + * + * @note One ORTEnv should be created before and destroyed after other ORT API usage. */ @interface ORTEnv : NSObject diff --git a/objectivec/include/ort_training_session.h b/objectivec/include/ort_training_session.h index 15c0137..2ad4fed 100644 --- a/objectivec/include/ort_training_session.h +++ b/objectivec/include/ort_training_session.h @@ -39,7 +39,7 @@ NS_ASSUME_NONNULL_BEGIN * session which will be moved to the device specified in the session option if needed. * * @param env The `ORTEnv` instance to use for the training session. - * @param sessionOptions The `ORTSessionOptions` to use for the training session. + * @param sessionOptions The optional `ORTSessionOptions` to use for the training session. * @param checkpoint Training states that are used as a starting point for training. * @param trainModelPath The path to the training onnx model. * @param evalModelPath The path to the evaluation onnx model. @@ -52,7 +52,7 @@ NS_ASSUME_NONNULL_BEGIN * keeps a strong (owning) pointer to the checkpoint state. */ - (nullable instancetype)initWithEnv:(ORTEnv*)env - sessionOptions:(ORTSessionOptions*)sessionOptions + sessionOptions:(nullable ORTSessionOptions*)sessionOptions checkpoint:(ORTCheckpoint*)checkpoint trainModelPath:(NSString*)trainModelPath evalModelPath:(nullable NSString*)evalModelPath diff --git a/objectivec/ort_checkpoint.mm b/objectivec/ort_checkpoint.mm index 1238645..2c7c9e4 100644 --- a/objectivec/ort_checkpoint.mm +++ b/objectivec/ort_checkpoint.mm @@ -8,6 +8,7 @@ #include #import "cxx_api.h" +#import "cxx_utils.h" #import "error_utils.h" NS_ASSUME_NONNULL_BEGIN @@ -73,7 +74,7 @@ NS_ASSUME_NONNULL_BEGIN try { Ort::Property value = [self CXXAPIOrtCheckpoint].GetProperty(name.UTF8String); if (std::string* str = std::get_if(&value)) { - return [NSString stringWithUTF8String:str->c_str()]; + return utils::toNSString(str->c_str()); } ORT_CXX_API_THROW("Property is not a string.", ORT_INVALID_ARGUMENT); } diff --git a/objectivec/ort_coreml_execution_provider.mm b/objectivec/ort_coreml_execution_provider.mm index 6340fde..58b47d6 100644 --- a/objectivec/ort_coreml_execution_provider.mm +++ b/objectivec/ort_coreml_execution_provider.mm @@ -26,7 +26,10 @@ BOOL ORTIsCoreMLExecutionProviderAvailable() { 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); + (options.onlyEnableForDevicesWithANE ? COREML_FLAG_ONLY_ENABLE_DEVICE_WITH_ANE : 0) | + (options.onlyAllowStaticInputShapes ? COREML_FLAG_ONLY_ALLOW_STATIC_INPUT_SHAPES : 0) | + (options.createMLProgram ? COREML_FLAG_CREATE_MLPROGRAM : 0); + Ort::ThrowOnError(OrtSessionOptionsAppendExecutionProvider_CoreML( [self CXXAPIOrtSessionOptions], flags)); return YES; diff --git a/objectivec/ort_session.mm b/objectivec/ort_session.mm index d27c3e2..3dcc88f 100644 --- a/objectivec/ort_session.mm +++ b/objectivec/ort_session.mm @@ -7,6 +7,7 @@ #include #import "cxx_api.h" +#import "cxx_utils.h" #import "error_utils.h" #import "ort_enums_internal.h" #import "ort_env_internal.h" @@ -23,6 +24,7 @@ enum class NamedValueType { NS_ASSUME_NONNULL_BEGIN @implementation ORTSession { + ORTEnv* _env; // keep a strong reference so the ORTEnv doesn't get destroyed before this does std::optional _session; } @@ -44,6 +46,7 @@ NS_ASSUME_NONNULL_BEGIN } } + _env = env; _session = Ort::Session{[env CXXAPIOrtEnv], path.UTF8String, [sessionOptions CXXAPIOrtSessionOptions]}; @@ -196,8 +199,7 @@ NS_ASSUME_NONNULL_BEGIN for (size_t i = 0; i < nameCount; ++i) { auto name = getName(i, allocator); - NSString* nameNsstr = [NSString stringWithUTF8String:name.get()]; - NSAssert(nameNsstr != nil, @"nameNsstr must not be nil"); + NSString* nameNsstr = utils::toNSString(name.get()); [result addObject:nameNsstr]; } diff --git a/objectivec/ort_training_session.mm b/objectivec/ort_training_session.mm index 285151b..5387bfd 100644 --- a/objectivec/ort_training_session.mm +++ b/objectivec/ort_training_session.mm @@ -19,8 +19,9 @@ NS_ASSUME_NONNULL_BEGIN @implementation ORTTrainingSession { - std::optional _session; + ORTEnv* _env; // keep a strong reference so the ORTEnv doesn't get destroyed before this does ORTCheckpoint* _checkpoint; + std::optional _session; } - (Ort::TrainingSession&)CXXAPIOrtTrainingSession { @@ -28,7 +29,7 @@ NS_ASSUME_NONNULL_BEGIN } - (nullable instancetype)initWithEnv:(ORTEnv*)env - sessionOptions:(ORTSessionOptions*)sessionOptions + sessionOptions:(nullable ORTSessionOptions*)sessionOptions checkpoint:(ORTCheckpoint*)checkpoint trainModelPath:(NSString*)trainModelPath evalModelPath:(nullable NSString*)evalModelPath @@ -39,9 +40,17 @@ NS_ASSUME_NONNULL_BEGIN } try { + if (!sessionOptions) { + sessionOptions = [[ORTSessionOptions alloc] initWithError:error]; + if (!sessionOptions) { + return nil; + } + } + std::optional evalPath = utils::toStdOptionalString(evalModelPath); std::optional optimizerPath = utils::toStdOptionalString(optimizerModelPath); + _env = env; _checkpoint = checkpoint; _session = Ort::TrainingSession{ [env CXXAPIOrtEnv], @@ -50,6 +59,7 @@ NS_ASSUME_NONNULL_BEGIN trainModelPath.UTF8String, evalPath, optimizerPath}; + return self; } ORT_OBJC_API_IMPL_CATCH_RETURNING_NULLABLE(error) diff --git a/objectivec/ort_value.mm b/objectivec/ort_value.mm index b9dc1a9..c61a7ea 100644 --- a/objectivec/ort_value.mm +++ b/objectivec/ort_value.mm @@ -148,6 +148,9 @@ bool SafeMultiply(size_t a, size_t b, size_t& out) { - (nullable ORTTensorTypeAndShapeInfo*)tensorTypeAndShapeInfoWithError:(NSError**)error { try { const auto tensorTypeAndShapeInfo = _typeInfo->GetTensorTypeAndShapeInfo(); + if (!tensorTypeAndShapeInfo) { + ORT_CXX_API_THROW("ORTValue is not a tensor.", ORT_RUNTIME_EXCEPTION); + } return CXXAPIToPublicTensorTypeAndShapeInfo(tensorTypeAndShapeInfo); } ORT_OBJC_API_IMPL_CATCH_RETURNING_NULLABLE(error) @@ -156,6 +159,9 @@ bool SafeMultiply(size_t a, size_t b, size_t& out) { - (nullable NSMutableData*)tensorDataWithError:(NSError**)error { try { const auto tensorTypeAndShapeInfo = _typeInfo->GetTensorTypeAndShapeInfo(); + if (!tensorTypeAndShapeInfo) { + ORT_CXX_API_THROW("ORTValue is not a tensor.", ORT_RUNTIME_EXCEPTION); + } if (tensorTypeAndShapeInfo.GetElementType() == ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING) { ORT_CXX_API_THROW( "This ORTValue holds string data. Please call tensorStringDataWithError: " @@ -182,6 +188,9 @@ bool SafeMultiply(size_t a, size_t b, size_t& out) { - (nullable NSArray*)tensorStringDataWithError:(NSError**)error { try { const auto tensorTypeAndShapeInfo = _typeInfo->GetTensorTypeAndShapeInfo(); + if (!tensorTypeAndShapeInfo) { + ORT_CXX_API_THROW("ORTValue is not a tensor.", ORT_RUNTIME_EXCEPTION); + } const size_t elementCount = tensorTypeAndShapeInfo.GetElementCount(); const size_t tensorStringDataLength = _value->GetStringTensorDataLength(); std::vector tensorStringData(tensorStringDataLength, '\0');