Taehee Jeong 86726adc39 Add subspecs to TFLite Objective-C API Cocoapod
Added Metal delegate and Core as subspecs of the source pod.

* Removed manually written module map. The module map and umbrella header `TFLTensorFlowLite-umbrella.h` will be automatically generated with all the delegate headers. `TFLTensorFlowLite.h` is left for legacy purpose.
* Modified macro to make tests work with bazel and Cocoapods.
Changed some umbrella header imports to module import,
`@import TFLTensorFlowLite`.

PiperOrigin-RevId: 333012903
Change-Id: Ib743d7a3250b884fc406505f457ed55cea1ad20d
2020-09-21 23:12:55 -07:00

122 lines
4.1 KiB
Objective-C

// Copyright 2020 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at:
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifdef COCOAPODS
@import TFLTensorFlowLite;
#else
#import "tensorflow/lite/experimental/objc/apis/TFLMetalDelegate.h"
#import "tensorflow/lite/experimental/objc/apis/TFLTensorFlowLite.h"
#endif
#import <Metal/MTLDevice.h>
#import <Metal/Metal.h>
#import <XCTest/XCTest.h>
NS_ASSUME_NONNULL_BEGIN
/**
* Float model resource name.
* The model has four inputs (a, b, c, d) and two outputs (x, y)
* x = a + (b + c)
* y = (b + c) + d
*/
static NSString* const kAddFloatModelResourceName = @"multi_add";
/** Model resource type. */
static NSString* const kAddModelResourceType = @"bin";
/** Size of input and output tensors */
static const int kTensorSize = 8 * 8 * 3;
/** Size of channel dimension of input and output tensors */
static const int kTensorChannels = 3;
/** Number of input tensors */
static const int kNumInputs = 4;
/** Number of output tensors */
static const int kNumOutputs = 2;
/** Accuracy used in comparing floating numbers. */
static const float kTestAccuracy = 1E-5F;
@interface TFLMetalDelegateTests : XCTestCase
@end
@implementation TFLMetalDelegateTests
- (void)testMetalDelegate {
NSBundle* bundle = [NSBundle bundleForClass:[self class]];
NSString* floatModelPath = [bundle pathForResource:kAddFloatModelResourceName
ofType:kAddModelResourceType];
TFLInterpreterOptions* options = [[TFLInterpreterOptions alloc] init];
TFLMetalDelegate* metalDelegate = [[TFLMetalDelegate alloc] init];
XCTAssertNotNil(metalDelegate);
id<MTLDevice> mtlDevice = MTLCreateSystemDefaultDevice();
if (mtlDevice == nil) return; // Stop testing if there's no GPU support
NSError* error;
TFLInterpreter* interpreter = [[TFLInterpreter alloc] initWithModelPath:floatModelPath
options:options
delegates:@[ metalDelegate ]
error:&error];
XCTAssertNil(error);
XCTAssertNotNil(interpreter);
XCTAssertTrue([interpreter allocateTensorsWithError:&error]);
XCTAssertNil(error);
// Copies the input data. For each input, input[i, j, k] == k
NSMutableData* inputData = [NSMutableData dataWithLength:sizeof(float) * kTensorSize];
for (int i = 0; i < kTensorSize / kTensorChannels; ++i) {
float* data = (float*)inputData.mutableBytes;
for (int j = 0; j < kTensorChannels; ++j) {
data[i * kTensorChannels + j] = j;
}
}
for (int input_idx = 0; input_idx < kNumInputs; ++input_idx) {
TFLTensor* inputTensor = [interpreter inputTensorAtIndex:input_idx error:&error];
XCTAssertNotNil(inputTensor);
XCTAssertTrue([inputTensor copyData:inputData error:&error]);
XCTAssertNil(error);
}
// Invokes the interpreter.
XCTAssertTrue([interpreter invokeWithError:&error]);
XCTAssertNil(error);
// Gets the output tensor data. For each output, output[i, j, k] == k * 3
for (int output_idx = 0; output_idx < kNumOutputs; ++output_idx) {
TFLTensor* outputTensor = [interpreter outputTensorAtIndex:output_idx error:&error];
NSData* outputData = [outputTensor dataWithError:&error];
XCTAssertNotNil(outputData);
XCTAssertNil(error);
float output[kTensorSize];
[outputData getBytes:output length:(sizeof(float) * kTensorSize)];
for (int i = 0; i < kTensorSize / kTensorChannels; ++i) {
for (int j = 0; j < kTensorChannels; ++j) {
XCTAssertEqualWithAccuracy(j * 3, output[i * kTensorChannels + j], kTestAccuracy);
}
}
}
}
@end
NS_ASSUME_NONNULL_END