2021-05-11 17:34:40 +00:00
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
|
// Licensed under the MIT License.
|
|
|
|
|
|
|
|
|
|
#import "OnnxruntimeModule.h"
|
2023-06-16 09:37:02 +00:00
|
|
|
#import "FakeRCTBlobManager.h"
|
2021-05-11 17:34:40 +00:00
|
|
|
#import "TensorHelper.h"
|
2021-06-15 20:36:05 +00:00
|
|
|
|
2021-05-11 17:34:40 +00:00
|
|
|
#import <XCTest/XCTest.h>
|
2021-06-15 20:36:05 +00:00
|
|
|
#import <onnxruntime/onnxruntime_cxx_api.h>
|
2021-05-11 17:34:40 +00:00
|
|
|
|
|
|
|
|
@interface OnnxruntimeModuleTest : XCTestCase
|
|
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@implementation OnnxruntimeModuleTest
|
|
|
|
|
|
2023-06-16 09:37:02 +00:00
|
|
|
FakeRCTBlobManager *fakeBlobManager = nil;
|
|
|
|
|
|
|
|
|
|
+ (void)initialize {
|
|
|
|
|
if (self == [OnnxruntimeModuleTest class]) {
|
|
|
|
|
fakeBlobManager = [FakeRCTBlobManager new];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-11 17:34:40 +00:00
|
|
|
- (void)testOnnxruntimeModule {
|
|
|
|
|
NSBundle *bundle = [NSBundle bundleForClass:[OnnxruntimeModuleTest class]];
|
2021-06-15 20:36:05 +00:00
|
|
|
NSString *dataPath = [bundle pathForResource:@"test_types_float" ofType:@"ort"];
|
2023-04-29 00:34:26 +00:00
|
|
|
NSString *sessionKey = @"";
|
|
|
|
|
NSString *sessionKey2 = @"";
|
2021-05-11 17:34:40 +00:00
|
|
|
|
|
|
|
|
OnnxruntimeModule *onnxruntimeModule = [OnnxruntimeModule new];
|
2023-06-16 09:37:02 +00:00
|
|
|
[onnxruntimeModule setBlobManager:fakeBlobManager];
|
2021-05-11 17:34:40 +00:00
|
|
|
|
|
|
|
|
{
|
2023-04-29 00:34:26 +00:00
|
|
|
// test loadModelFromBuffer()
|
2021-05-11 17:34:40 +00:00
|
|
|
NSMutableDictionary *options = [NSMutableDictionary dictionary];
|
2023-04-29 00:34:26 +00:00
|
|
|
NSData *fileData = [NSData dataWithContentsOfFile:dataPath];
|
2021-05-11 17:34:40 +00:00
|
|
|
|
2023-04-29 00:34:26 +00:00
|
|
|
NSDictionary *resultMap = [onnxruntimeModule loadModelFromBuffer:fileData options:options];
|
|
|
|
|
sessionKey = resultMap[@"key"];
|
2021-05-11 17:34:40 +00:00
|
|
|
NSArray *inputNames = resultMap[@"inputNames"];
|
|
|
|
|
XCTAssertEqual([inputNames count], 1);
|
|
|
|
|
XCTAssertEqualObjects(inputNames[0], @"input");
|
|
|
|
|
NSArray *outputNames = resultMap[@"outputNames"];
|
|
|
|
|
XCTAssertEqual([outputNames count], 1);
|
|
|
|
|
XCTAssertEqualObjects(outputNames[0], @"output");
|
2023-04-29 00:34:26 +00:00
|
|
|
|
|
|
|
|
// test loadModel()
|
|
|
|
|
NSDictionary *resultMap2 = [onnxruntimeModule loadModel:dataPath options:options];
|
|
|
|
|
sessionKey2 = resultMap2[@"key"];
|
|
|
|
|
NSArray *inputNames2 = resultMap2[@"inputNames"];
|
|
|
|
|
XCTAssertEqual([inputNames2 count], 1);
|
|
|
|
|
XCTAssertEqualObjects(inputNames2[0], @"input");
|
|
|
|
|
NSArray *outputNames2 = resultMap2[@"outputNames"];
|
|
|
|
|
XCTAssertEqual([outputNames2 count], 1);
|
|
|
|
|
XCTAssertEqualObjects(outputNames2[0], @"output");
|
2021-05-11 17:34:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// test run()
|
|
|
|
|
{
|
|
|
|
|
NSMutableDictionary *inputTensorMap = [NSMutableDictionary dictionary];
|
|
|
|
|
|
|
|
|
|
// dims
|
|
|
|
|
NSArray *dims = @[ [NSNumber numberWithLong:1], [NSNumber numberWithLong:5] ];
|
|
|
|
|
inputTensorMap[@"dims"] = dims;
|
|
|
|
|
|
|
|
|
|
// type
|
|
|
|
|
inputTensorMap[@"type"] = JsTensorTypeFloat;
|
|
|
|
|
|
|
|
|
|
// data
|
Replace float_t with float (#16484)
A couple of places in onnxruntime used `float_t` data type alias as an
alternative to `float`. However, this is not entirely correct, since
`float_t` is an implementation-defined type alias, which may be `float`,
`double`, `long double` or some other implementation-defined data type,
depending on the state of the internal `FLT_EVAL_METHOD` macro:
https://en.cppreference.com/w/c/numeric/math/float_t
On most major platforms and compilers (clang, GCC, MSVC) this is only a
cosmetic change and will not lead to any changes. However, icpx compiler
(and legacy icc) tends to substitute `float_t` with `long double`,
resulting in a linker error (unresolved reference) to the base onnx
library, that only contains the `ParseData` function for `float` and
`double` as in
[here](https://github.com/onnx/onnx/blob/9264e093676f40a48aee819b8013ef285e3d4fc5/onnx/defs/tensor_proto_util.cc#L133-L134).
Overall, this PR cleans up the implementation-defined behaviour and
enables building onnxruntime with icpx.
2023-06-27 16:28:38 +00:00
|
|
|
std::array<float, 5> outValues{std::numeric_limits<float>::min(), 1.0f, -2.0f, 3.0f,
|
|
|
|
|
std::numeric_limits<float>::max()};
|
2021-05-11 17:34:40 +00:00
|
|
|
|
Replace float_t with float (#16484)
A couple of places in onnxruntime used `float_t` data type alias as an
alternative to `float`. However, this is not entirely correct, since
`float_t` is an implementation-defined type alias, which may be `float`,
`double`, `long double` or some other implementation-defined data type,
depending on the state of the internal `FLT_EVAL_METHOD` macro:
https://en.cppreference.com/w/c/numeric/math/float_t
On most major platforms and compilers (clang, GCC, MSVC) this is only a
cosmetic change and will not lead to any changes. However, icpx compiler
(and legacy icc) tends to substitute `float_t` with `long double`,
resulting in a linker error (unresolved reference) to the base onnx
library, that only contains the `ParseData` function for `float` and
`double` as in
[here](https://github.com/onnx/onnx/blob/9264e093676f40a48aee819b8013ef285e3d4fc5/onnx/defs/tensor_proto_util.cc#L133-L134).
Overall, this PR cleans up the implementation-defined behaviour and
enables building onnxruntime with icpx.
2023-06-27 16:28:38 +00:00
|
|
|
const NSInteger byteBufferSize = outValues.size() * sizeof(float);
|
2021-05-11 17:34:40 +00:00
|
|
|
unsigned char *byteBuffer = static_cast<unsigned char *>(malloc(byteBufferSize));
|
|
|
|
|
NSData *byteBufferRef = [NSData dataWithBytesNoCopy:byteBuffer length:byteBufferSize];
|
|
|
|
|
float *floatPtr = (float *)[byteBufferRef bytes];
|
|
|
|
|
for (NSUInteger i = 0; i < outValues.size(); ++i) {
|
|
|
|
|
*floatPtr++ = outValues[i];
|
|
|
|
|
}
|
|
|
|
|
floatPtr = (float *)[byteBufferRef bytes];
|
|
|
|
|
|
2023-06-16 09:37:02 +00:00
|
|
|
XCTAssertNotNil(fakeBlobManager);
|
|
|
|
|
inputTensorMap[@"data"] = [fakeBlobManager testCreateData:byteBufferRef];
|
2021-05-11 17:34:40 +00:00
|
|
|
|
|
|
|
|
NSMutableDictionary *inputDataMap = [NSMutableDictionary dictionary];
|
|
|
|
|
inputDataMap[@"input"] = inputTensorMap;
|
|
|
|
|
|
|
|
|
|
NSMutableDictionary *options = [NSMutableDictionary dictionary];
|
|
|
|
|
|
|
|
|
|
NSMutableArray *output = [NSMutableArray array];
|
|
|
|
|
[output addObject:@"output"];
|
|
|
|
|
|
2023-04-29 00:34:26 +00:00
|
|
|
NSDictionary *resultMap = [onnxruntimeModule run:sessionKey input:inputDataMap output:output options:options];
|
|
|
|
|
NSDictionary *resultMap2 = [onnxruntimeModule run:sessionKey2 input:inputDataMap output:output options:options];
|
2021-05-11 17:34:40 +00:00
|
|
|
|
2023-06-16 09:37:02 +00:00
|
|
|
// Compare output & input, but data.blobId is different
|
|
|
|
|
// dims
|
|
|
|
|
XCTAssertTrue([[resultMap objectForKey:@"output"][@"dims"] isEqualToArray:inputTensorMap[@"dims"]]);
|
|
|
|
|
XCTAssertTrue([[resultMap2 objectForKey:@"output"][@"dims"] isEqualToArray:inputTensorMap[@"dims"]]);
|
|
|
|
|
|
|
|
|
|
// type
|
|
|
|
|
XCTAssertEqual([resultMap objectForKey:@"output"][@"type"], JsTensorTypeFloat);
|
|
|
|
|
XCTAssertEqual([resultMap2 objectForKey:@"output"][@"type"], JsTensorTypeFloat);
|
|
|
|
|
|
|
|
|
|
// data ({ blobId, offset, size })
|
|
|
|
|
XCTAssertEqual([[resultMap objectForKey:@"output"][@"data"][@"offset"] longValue], 0);
|
|
|
|
|
XCTAssertEqual([[resultMap2 objectForKey:@"output"][@"data"][@"size"] longValue], byteBufferSize);
|
2021-05-11 17:34:40 +00:00
|
|
|
}
|
2023-06-08 23:17:33 +00:00
|
|
|
|
|
|
|
|
// test dispose
|
|
|
|
|
{
|
|
|
|
|
[onnxruntimeModule dispose:sessionKey];
|
|
|
|
|
[onnxruntimeModule dispose:sessionKey2];
|
|
|
|
|
}
|
2021-05-11 17:34:40 +00:00
|
|
|
}
|
|
|
|
|
|
2023-07-12 21:55:47 +00:00
|
|
|
- (void)testOnnxruntimeModule_AppendCoreml {
|
|
|
|
|
NSBundle *bundle = [NSBundle bundleForClass:[OnnxruntimeModuleTest class]];
|
|
|
|
|
NSString *dataPath = [bundle pathForResource:@"test_types_float" ofType:@"ort"];
|
|
|
|
|
NSString *sessionKey = @"";
|
|
|
|
|
|
|
|
|
|
OnnxruntimeModule *onnxruntimeModule = [OnnxruntimeModule new];
|
|
|
|
|
[onnxruntimeModule setBlobManager:fakeBlobManager];
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
// test loadModel() with coreml options
|
|
|
|
|
NSMutableDictionary *options = [NSMutableDictionary dictionary];
|
|
|
|
|
|
|
|
|
|
// register coreml ep options
|
|
|
|
|
NSMutableArray *epList = [NSMutableArray array];
|
|
|
|
|
[epList addObject:@"coreml"];
|
|
|
|
|
NSArray *immutableEpList = [NSArray arrayWithArray:epList];
|
|
|
|
|
[options setObject:immutableEpList forKey:@"executionProviders"];
|
|
|
|
|
|
|
|
|
|
NSDictionary *resultMap = [onnxruntimeModule loadModel:dataPath options:options];
|
|
|
|
|
|
|
|
|
|
sessionKey = resultMap[@"key"];
|
|
|
|
|
NSArray *inputNames = resultMap[@"inputNames"];
|
|
|
|
|
XCTAssertEqual([inputNames count], 1);
|
|
|
|
|
XCTAssertEqualObjects(inputNames[0], @"input");
|
|
|
|
|
NSArray *outputNames = resultMap[@"outputNames"];
|
|
|
|
|
XCTAssertEqual([outputNames count], 1);
|
|
|
|
|
XCTAssertEqualObjects(outputNames[0], @"output");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
{ [onnxruntimeModule dispose:sessionKey]; }
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-11 17:34:40 +00:00
|
|
|
@end
|