Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions extension/apple/ExecuTorch/Exported/ExecuTorch+Module.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,36 @@ public extension MethodMetadata {
}
}

public extension Module {
/// Loads the module's program with per-delegate backend options.
///
/// - Parameters:
/// - backendOptions: A dictionary mapping backend identifiers (e.g. "CoreMLBackend")
/// to arrays of `BackendOption` objects configuring that backend.
/// - verification: The verification level to apply when loading the program.
/// - Throws: An error if loading fails.
func load(
backendOptions: [String: [BackendOption]],
verification: ModuleVerification = .minimal
) throws {
try __load(backendOptions: backendOptions, verification: verification)
}

/// Loads a specific method from the program with per-delegate backend options.
///
/// - Parameters:
/// - method: The name of the method to load.
/// - backendOptions: A dictionary mapping backend identifiers (e.g. "CoreMLBackend")
/// to arrays of `BackendOption` objects configuring that backend.
/// - Throws: An error if loading fails.
func load(
_ method: String,
backendOptions: [String: [BackendOption]]
) throws {
try __loadMethod(method, backendOptions: backendOptions)
}
}

public extension Module {
/// Executes a specific method with the provided input values.
/// The method is loaded on demand if not already loaded.
Expand Down
1 change: 1 addition & 0 deletions extension/apple/ExecuTorch/Exported/ExecuTorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* LICENSE file in the root directory of this source tree.
*/

#import "ExecuTorchBackendOption.h"
#import "ExecuTorchError.h"
#import "ExecuTorchLog.h"
#import "ExecuTorchModule.h"
Expand Down
89 changes: 89 additions & 0 deletions extension/apple/ExecuTorch/Exported/ExecuTorchBackendOption.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

/**
* Enum to define the type of a backend option value.
*/
typedef NS_ENUM(NSInteger, ExecuTorchBackendOptionType) {
ExecuTorchBackendOptionTypeBoolean,
ExecuTorchBackendOptionTypeInteger,
ExecuTorchBackendOptionTypeString,
} NS_SWIFT_NAME(BackendOptionType);

/**
* Represents a single key-value configuration option for a backend.
*
* Backend options are used to pass per-delegate configuration (e.g., compute
* unit, thread count, cache directory) when loading a module. Each option has
* a string key and a typed value (boolean, integer, or string).
*/
NS_SWIFT_NAME(BackendOption)
__attribute__((objc_subclassing_restricted))
@interface ExecuTorchBackendOption : NSObject

/** The option key name (e.g. "compute_unit", "num_threads"). */
@property (nonatomic, readonly) NSString *key;

/** The type of the option value. */
@property (nonatomic, readonly) ExecuTorchBackendOptionType type;

/** The boolean value. Only valid when type is Boolean. */
@property (nonatomic, readonly) BOOL boolValue;

/** The integer value. Only valid when type is Integer. */
@property (nonatomic, readonly) NSInteger intValue;

/** The string value. Only valid when type is String. */
@property (nullable, nonatomic, readonly) NSString *stringValue;

/**
* Creates a backend option with a boolean value.
*
* @param key The option key.
* @param value The boolean value.
* @return A new ExecuTorchBackendOption instance.
*/
+ (instancetype)optionWithKey:(NSString *)key
booleanValue:(BOOL)value
NS_SWIFT_NAME(init(_:_:))
NS_RETURNS_RETAINED;

/**
* Creates a backend option with an integer value.
*
* @param key The option key.
* @param value The integer value.
* @return A new ExecuTorchBackendOption instance.
*/
+ (instancetype)optionWithKey:(NSString *)key
integerValue:(NSInteger)value
NS_SWIFT_NAME(init(_:_:))
NS_RETURNS_RETAINED;

/**
* Creates a backend option with a string value.
*
* @param key The option key.
* @param value The string value.
* @return A new ExecuTorchBackendOption instance.
*/
+ (instancetype)optionWithKey:(NSString *)key
stringValue:(NSString *)value
NS_SWIFT_NAME(init(_:_:))
NS_RETURNS_RETAINED;

+ (instancetype)new NS_UNAVAILABLE;
- (instancetype)init NS_UNAVAILABLE;

@end

NS_ASSUME_NONNULL_END
67 changes: 67 additions & 0 deletions extension/apple/ExecuTorch/Exported/ExecuTorchBackendOption.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/

#import "ExecuTorchBackendOption.h"

@implementation ExecuTorchBackendOption {
NSString *_key;
ExecuTorchBackendOptionType _type;
BOOL _boolValue;
NSInteger _intValue;
NSString *_stringValue;
}

- (instancetype)initWithKey:(NSString *)key
booleanValue:(BOOL)value {
self = [super init];
if (self) {
_key = [key copy];
_type = ExecuTorchBackendOptionTypeBoolean;
_boolValue = value;
}
return self;
}

- (instancetype)initWithKey:(NSString *)key
integerValue:(NSInteger)value {
self = [super init];
if (self) {
_key = [key copy];
_type = ExecuTorchBackendOptionTypeInteger;
_intValue = value;
}
return self;
}

- (instancetype)initWithKey:(NSString *)key
stringValue:(NSString *)value {
self = [super init];
if (self) {
_key = [key copy];
_type = ExecuTorchBackendOptionTypeString;
_stringValue = [value copy];
}
return self;
}

+ (instancetype)optionWithKey:(NSString *)key
booleanValue:(BOOL)value {
return [[self alloc] initWithKey:key booleanValue:value];
}

+ (instancetype)optionWithKey:(NSString *)key
integerValue:(NSInteger)value {
return [[self alloc] initWithKey:key integerValue:value];
}

+ (instancetype)optionWithKey:(NSString *)key
stringValue:(NSString *)value {
return [[self alloc] initWithKey:key stringValue:value];
}

@end
38 changes: 38 additions & 0 deletions extension/apple/ExecuTorch/Exported/ExecuTorchModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* LICENSE file in the root directory of this source tree.
*/

#import "ExecuTorchBackendOption.h"
#import "ExecuTorchValue.h"

NS_ASSUME_NONNULL_BEGIN
Expand Down Expand Up @@ -186,6 +187,30 @@ NS_SWIFT_NAME(Module)
*/
- (BOOL)load:(NSError **)error;

/**
* Loads the module's program with per-delegate backend options.
*
* @param backendOptions A dictionary mapping backend identifiers (e.g. "CoreMLBackend")
* to arrays of ExecuTorchBackendOption objects configuring that backend.
* @param verification The verification level to apply when loading the program.
* @param error A pointer to an NSError pointer that will be set if an error occurs.
* @return YES if the program was successfully loaded; otherwise, NO.
*/
- (BOOL)loadWithBackendOptions:(NSDictionary<NSString *, NSArray<ExecuTorchBackendOption *> *> *)backendOptions
verification:(ExecuTorchVerification)verification
error:(NSError **)error NS_REFINED_FOR_SWIFT;

/**
* Loads the module's program with per-delegate backend options using minimal verification.
*
* @param backendOptions A dictionary mapping backend identifiers (e.g. "CoreMLBackend")
* to arrays of ExecuTorchBackendOption objects configuring that backend.
* @param error A pointer to an NSError pointer that will be set if an error occurs.
* @return YES if the program was successfully loaded; otherwise, NO.
*/
- (BOOL)loadWithBackendOptions:(NSDictionary<NSString *, NSArray<ExecuTorchBackendOption *> *> *)backendOptions
error:(NSError **)error NS_REFINED_FOR_SWIFT;

/**
* Checks if the module is loaded.
*
Expand All @@ -203,6 +228,19 @@ NS_SWIFT_NAME(Module)
- (BOOL)loadMethod:(NSString *)methodName
error:(NSError **)error NS_SWIFT_NAME(load(_:));

/**
* Loads a specific method from the program with per-delegate backend options.
*
* @param methodName A string representing the name of the method to load.
* @param backendOptions A dictionary mapping backend identifiers (e.g. "CoreMLBackend")
* to arrays of ExecuTorchBackendOption objects configuring that backend.
* @param error A pointer to an NSError pointer that is set if an error occurs.
* @return YES if the method was successfully loaded; otherwise, NO.
*/
- (BOOL)loadMethod:(NSString *)methodName
backendOptions:(NSDictionary<NSString *, NSArray<ExecuTorchBackendOption *> *> *)backendOptions
error:(NSError **)error NS_REFINED_FOR_SWIFT;

/**
* Checks if a specific method is loaded.
*
Expand Down
97 changes: 97 additions & 0 deletions extension/apple/ExecuTorch/Exported/ExecuTorchModule.mm
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@

#import "ExecuTorchModule.h"

#import "ExecuTorchBackendOption.h"
#import "ExecuTorchError.h"
#import "ExecuTorchUtils.h"

#import <executorch/extension/module/module.h>
#import <executorch/extension/tensor/tensor.h>
#import <executorch/runtime/backend/backend_options_map.h>
#import <executorch/runtime/backend/options.h>

using namespace executorch::extension;
using namespace executorch::runtime;
Expand Down Expand Up @@ -63,6 +66,49 @@ static inline EValue toEValue(ExecuTorchValue *value) {
return [ExecuTorchValue new];
}

static Error buildBackendOptionsMap(
NSDictionary<NSString *, NSArray<ExecuTorchBackendOption *> *> *backendOptions,
std::vector<std::vector<BackendOption>> &allOptions,
LoadBackendOptionsMap &map) {
allOptions.reserve(backendOptions.count);
for (NSString *backendId in backendOptions) {
NSArray<ExecuTorchBackendOption *> *options = backendOptions[backendId];
std::vector<BackendOption> opts;
opts.reserve(options.count);
for (ExecuTorchBackendOption *opt in options) {
BackendOption bo;
strncpy(bo.key, opt.key.UTF8String, kMaxOptionKeyLength - 1);
bo.key[kMaxOptionKeyLength - 1] = '\0';
switch (opt.type) {
case ExecuTorchBackendOptionTypeBoolean:
bo.value = (bool)opt.boolValue;
break;
case ExecuTorchBackendOptionTypeInteger:
if (opt.intValue < INT_MIN || opt.intValue > INT_MAX) {
return Error::InvalidArgument;
}
bo.value = (int)opt.intValue;
break;
case ExecuTorchBackendOptionTypeString: {
std::array<char, kMaxOptionValueLength> arr{};
strncpy(arr.data(), opt.stringValue.UTF8String, kMaxOptionValueLength - 1);
arr[kMaxOptionValueLength - 1] = '\0';
bo.value = arr;
break;
}
}
opts.push_back(bo);
}
allOptions.push_back(std::move(opts));
auto &backOpts = allOptions.back();
const auto err = map.set_options(backendId.UTF8String, Span<BackendOption>(backOpts.data(), backOpts.size()));
if (err != Error::Ok) {
return err;
}
}
return Error::Ok;
}

@interface ExecuTorchTensorMetadata ()

- (instancetype)initWithTensorMetadata:(const TensorInfo &)tensorInfo
Expand Down Expand Up @@ -324,6 +370,57 @@ - (BOOL)loadMethod:(NSString *)methodName
return YES;
}

- (BOOL)loadWithBackendOptions:(NSDictionary<NSString *, NSArray<ExecuTorchBackendOption *> *> *)backendOptions
verification:(ExecuTorchVerification)verification
error:(NSError **)error {
std::vector<std::vector<BackendOption>> allOptions;
LoadBackendOptionsMap map;
const auto buildError = buildBackendOptionsMap(backendOptions, allOptions, map);
if (buildError != Error::Ok) {
if (error) {
*error = ExecuTorchErrorWithCode((ExecuTorchErrorCode)buildError);
}
return NO;
}
const auto errorCode = _module->load(map, static_cast<Program::Verification>(verification));
if (errorCode != Error::Ok) {
if (error) {
*error = ExecuTorchErrorWithCode((ExecuTorchErrorCode)errorCode);
}
return NO;
}
return YES;
}

- (BOOL)loadWithBackendOptions:(NSDictionary<NSString *, NSArray<ExecuTorchBackendOption *> *> *)backendOptions
error:(NSError **)error {
return [self loadWithBackendOptions:backendOptions
verification:ExecuTorchVerificationMinimal
error:error];
}

- (BOOL)loadMethod:(NSString *)methodName
backendOptions:(NSDictionary<NSString *, NSArray<ExecuTorchBackendOption *> *> *)backendOptions
error:(NSError **)error {
std::vector<std::vector<BackendOption>> allOptions;
LoadBackendOptionsMap map;
const auto buildError = buildBackendOptionsMap(backendOptions, allOptions, map);
if (buildError != Error::Ok) {
if (error) {
*error = ExecuTorchErrorWithCode((ExecuTorchErrorCode)buildError);
}
return NO;
}
const auto errorCode = _module->load_method(methodName.UTF8String, nullptr, nullptr, &map);
if (errorCode != Error::Ok) {
if (error) {
*error = ExecuTorchErrorWithCode((ExecuTorchErrorCode)errorCode);
}
return NO;
}
return YES;
}

- (BOOL)isMethodLoaded:(NSString *)methodName {
return _module->is_method_loaded(methodName.UTF8String);
}
Expand Down
Loading
Loading