Skip to content

Commit 80276dc

Browse files
committed
[Core ML] Implement intermediate tensor logging
1 parent 227b49d commit 80276dc

23 files changed

+865
-108
lines changed

backends/apple/coreml/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,11 @@ if(NOT EXECUTORCH_ROOT)
1313
set(EXECUTORCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
1414
endif()
1515

16+
if(EXECUTORCH_BUILD_SDK)
17+
# protobuf requires frtti
18+
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -frtti" )
19+
endif()
20+
1621
option(COREML_BUILD_EXECUTOR_RUNNER "Build CoreML executor runner." OFF)
1722

1823
# inmemoryfs sources
@@ -141,6 +146,8 @@ if(EXECUTORCH_BUILD_SDK)
141146
add_subdirectory(
142147
${CMAKE_CURRENT_SOURCE_DIR}/third-party/coremltools/deps/protobuf/cmake
143148
)
149+
150+
target_link_options_shared_lib(libprotobuf-lite)
144151
target_link_libraries(coremldelegate PRIVATE libprotobuf-lite)
145152
endif()
146153

backends/apple/coreml/runtime/delegate/coreml_backend_delegate.mm

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,8 @@ ModelLoggingOptions get_logging_options(BackendExecutionContext& context) {
124124
auto event_tracer = context.event_tracer();
125125
if (event_tracer) {
126126
options.log_profiling_info = true;
127-
options.log_intermediate_tensors = event_tracer->intermediate_outputs_logging_status();
127+
auto debug_level = event_tracer->event_tracer_debug_level();
128+
options.log_intermediate_tensors = (debug_level >= EventTracerDebugLogLevel::kIntermediateOutputs);
128129
}
129130

130131
return options;

backends/apple/coreml/runtime/sdk/ETCoreMLModelAnalyzer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
#import <CoreML/CoreML.h>
99

10-
#import <ETCoreMLModelExecutor.h>
10+
#import "ETCoreMLModelExecutor.h"
1111

1212
namespace executorchcoreml {
1313
struct ModelMetadata;

backends/apple/coreml/runtime/sdk/ETCoreMLModelAnalyzer.mm

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,22 +5,23 @@
55
//
66
// Please refer to the license found in the LICENSE file in the root directory of the source tree.
77

8-
#import <ETCoreMLAsset.h>
9-
#import <ETCoreMLAssetManager.h>
10-
#import <ETCoreMLDefaultModelExecutor.h>
11-
#import <ETCoreMLLogging.h>
12-
#import <ETCoreMLModel.h>
13-
#import <ETCoreMLModelAnalyzer.h>
14-
#import <ETCoreMLModelLoader.h>
15-
#import <ETCoreMLModelStructurePath.h>
16-
#import <ETCoreMLModelDebugger.h>
17-
#import <ETCoreMLModelProfiler.h>
18-
#import <ETCoreMLStrings.h>
19-
#import <model_logging_options.h>
20-
#import <model_event_logger.h>
21-
#import <model_metadata.h>
22-
#import <model_package_info.h>
23-
#import <objc_safe_cast.h>
8+
#import "ETCoreMLModelAnalyzer.h"
9+
10+
#import "ETCoreMLAsset.h"
11+
#import "ETCoreMLAssetManager.h"
12+
#import "ETCoreMLDefaultModelExecutor.h"
13+
#import "ETCoreMLLogging.h"
14+
#import "ETCoreMLModel.h"
15+
#import "ETCoreMLModelLoader.h"
16+
#import "ETCoreMLModelStructurePath.h"
17+
#import "ETCoreMLModelDebugger.h"
18+
#import "ETCoreMLModelProfiler.h"
19+
#import "ETCoreMLStrings.h"
20+
#import "model_logging_options.h"
21+
#import "model_event_logger.h"
22+
#import "model_metadata.h"
23+
#import "model_package_info.h"
24+
#import "objc_safe_cast.h"
2425

2526
namespace {
2627
using namespace executorchcoreml;

backends/apple/coreml/runtime/sdk/ETCoreMLModelDebugger.mm

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,22 @@
55
//
66
// Please refer to the license found in the LICENSE file in the root directory of the source tree.
77

8+
#import "ETCoreMLModelDebugger.h"
9+
810
#import <CoreML/CoreML.h>
9-
#import <ETCoreMLAsset.h>
10-
#import <ETCoreMLAssetManager.h>
11-
#import <ETCoreMLLogging.h>
12-
#import <ETCoreMLModelCompiler.h>
13-
#import <ETCoreMLModelStructurePath.h>
14-
#import <ETCoreMLPair.h>
15-
#import <ETCoreMLModelDebugger.h>
16-
#import <ETCoreMLStrings.h>
11+
#import "ETCoreMLAsset.h"
12+
#import "ETCoreMLAssetManager.h"
13+
#import "ETCoreMLLogging.h"
14+
#import "ETCoreMLModelCompiler.h"
15+
#import "ETCoreMLModelStructurePath.h"
16+
#import "ETCoreMLPair.h"
17+
#import "ETCoreMLStrings.h"
1718
#import <format/MIL.pb.h>
1819
#import <format/Model.pb.h>
1920
#import <fstream>
2021
#import <iostream>
21-
#import <model_package_info.h>
22-
#import <objc_json_serde.h>
22+
#import "model_package_info.h"
23+
#import "objc_json_serde.h"
2324
#import <string>
2425
#import <unordered_map>
2526

@@ -68,10 +69,6 @@ BOOL is_const_operation(const MILSpec::Operation& operation) {
6869
return operation.type() == "const";
6970
}
7071

71-
BOOL is_cast_operation(const MILSpec::Operation& operation) {
72-
return operation.type() == "cast";
73-
}
74-
7572
BOOL is_datatype_supported_as_model_output(MILSpec::DataType datatype) {
7673
switch (datatype) {
7774
case MILSpec::DataType::INT32:
@@ -95,11 +92,7 @@ BOOL is_operation_output_supported_as_model_output(const MILSpec::Operation& ope
9592
if (is_const_operation(operation)) {
9693
return NO;
9794
}
98-
99-
if (is_cast_operation(operation)) {
100-
return NO;
101-
}
102-
95+
10396
return YES;
10497
}
10598

@@ -316,7 +309,6 @@ void update_model_spec_version_to_include_fp16_output(Model& model_spec) {
316309
return nil;
317310
}
318311

319-
// Compile the model.
320312
return [ETCoreMLModelCompiler compileModelAtURL:model_url
321313
maxWaitTimeInSeconds:(5 * 60)
322314
error:error];

backends/apple/coreml/runtime/sdk/ETCoreMLModelProfiler.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,11 @@
55
//
66
// Please refer to the license found in the LICENSE file in the root directory of the source tree.
77

8+
#import "ETCoreMLPair.h"
89
#import <CoreML/CoreML.h>
9-
#import <ETCoreMLPair.h>
1010
#import <TargetConditionals.h>
1111

12+
@class ETCoreMLAsset;
1213
@class ETCoreMLModel;
1314
@class ETCoreMLModelStructurePath;
1415
@class ETCoreMLOperationProfilingInfo;

backends/apple/coreml/runtime/sdk/ETCoreMLModelProfiler.mm

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,17 @@
55
//
66
// Please refer to the license found in the LICENSE file in the root directory of the source tree.
77

8-
#import <ETCoreMLAsset.h>
9-
#import <ETCoreMLLogging.h>
10-
#import <ETCoreMLModelStructurePath.h>
11-
#import <ETCoreMLOperationProfilingInfo.h>
12-
#import <ETCoreMLPair.h>
13-
#import <ETCoreMLModelProfiler.h>
14-
#import <ETCoreMLStrings.h>
8+
#import "ETCoreMLModelProfiler.h"
9+
10+
#import "ETCoreMLAsset.h"
11+
#import "ETCoreMLLogging.h"
12+
#import "ETCoreMLModelStructurePath.h"
13+
#import "ETCoreMLOperationProfilingInfo.h"
14+
#import "ETCoreMLPair.h"
15+
#import "ETCoreMLStrings.h"
1516
#import <mach/mach_time.h>
1617
#import <math.h>
17-
#import <program_path.h>
18+
#import "program_path.h"
1819

1920
namespace {
2021
using namespace executorchcoreml::modelstructure;

backends/apple/coreml/runtime/sdk/ETCoreMLModelStructurePath.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
#import "ETCoreMLModelStructurePath.h"
99

10-
#import <objc_safe_cast.h>
10+
#import "objc_safe_cast.h"
1111

1212
namespace {
1313
using namespace executorchcoreml::modelstructure;

backends/apple/coreml/runtime/sdk/ETCoreMLOperationProfilingInfo.mm

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
//
66
// Please refer to the license found in the LICENSE file in the root directory of the source tree.
77

8-
#import <ETCoreMLOperationProfilingInfo.h>
9-
#import <hash_util.h>
10-
#import <model_event_logger_impl.h>
8+
#import "ETCoreMLOperationProfilingInfo.h"
9+
10+
#import "hash_util.h"
11+
#import "model_event_logger_impl.h"
1112

1213
namespace {
1314
NSString *const kPreferredComputeUnitKey = @"preferredComputeUnit";

backends/apple/coreml/runtime/sdk/ETCoreMLPair.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
//
66
// Please refer to the license found in the LICENSE file in the root directory of the source tree.
77

8-
#import <ETCoreMLPair.h>
8+
#import "ETCoreMLPair.h"
99

1010
@implementation ETCoreMLPair
1111

backends/apple/coreml/runtime/sdk/model_event_logger_impl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77

88
#pragma once
99

10+
#import "model_event_logger.h"
1011
#import <CoreML/CoreML.h>
11-
#import <model_event_logger.h>
1212

1313
namespace torch::executor {
1414
class EventTracer;

backends/apple/coreml/runtime/sdk/model_event_logger_impl.mm

Lines changed: 108 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,20 @@
55
//
66
// Please refer to the license found in the LICENSE file in the root directory of the source tree.
77

8-
#import <ETCoreMLModelStructurePath.h>
9-
#import <ETCoreMLOperationProfilingInfo.h>
8+
#import "model_event_logger_impl.h"
9+
10+
#import "ETCoreMLModelStructurePath.h"
11+
#import "ETCoreMLOperationProfilingInfo.h"
1012
#import <executorch/runtime/core/event_tracer.h>
13+
#import "objc_array_util.h"
1114
#import <mach/mach_time.h>
12-
#import <model_event_logger_impl.h>
15+
#import <numeric>
16+
#import "MLMultiArray_Copy.h"
1317

1418
namespace {
19+
20+
using namespace torch::executor;
21+
1522
uint64_t time_units_to_nano_seconds(uint64_t time_units) {
1623
static mach_timebase_info_data_t info;
1724
static dispatch_once_t onceToken;
@@ -22,6 +29,51 @@ uint64_t time_units_to_nano_seconds(uint64_t time_units) {
2229
return time_units * info.numer / info.denom;
2330
}
2431

32+
std::optional<ScalarType> to_scalar_type(MLMultiArrayDataType data_type) {
33+
switch (data_type) {
34+
case MLMultiArrayDataTypeFloat16: {
35+
return ScalarType::Half;
36+
}
37+
case MLMultiArrayDataTypeFloat32: {
38+
return ScalarType::Float;
39+
}
40+
case MLMultiArrayDataTypeDouble: {
41+
return ScalarType::Double;
42+
}
43+
case MLMultiArrayDataTypeInt32: {
44+
return ScalarType::Int;
45+
}
46+
default: {
47+
return std::nullopt;
48+
}
49+
}
50+
}
51+
52+
MLMultiArrayDataType get_supported_data_type(MLMultiArrayDataType data_type) {
53+
switch (data_type) {
54+
case MLMultiArrayDataTypeFloat16: {
55+
return MLMultiArrayDataTypeFloat32;
56+
}
57+
default: {
58+
return data_type;
59+
}
60+
}
61+
}
62+
63+
bool is_packed(NSArray<NSNumber *> *shape, NSArray<NSNumber *> *strides) {
64+
if (shape.count == 0) {
65+
return true;
66+
}
67+
size_t product = 1;
68+
for (size_t i = shape.count; i > 0; i--) {
69+
if (![strides[i - 1] isEqual:@(product)]) {
70+
return false;
71+
}
72+
product *= shape[i - 1].unsignedLongValue;
73+
}
74+
75+
return true;
76+
}
2577
}
2678

2779
namespace executorchcoreml {
@@ -54,6 +106,58 @@ uint64_t time_units_to_nano_seconds(uint64_t time_units) {
54106

55107
void ModelEventLoggerImpl::log_intermediate_tensors(NSDictionary<ETCoreMLModelStructurePath *, MLMultiArray *> *op_path_to_value_map,
56108
NSDictionary<ETCoreMLModelStructurePath *, NSString *> *op_path_to_debug_symbol_name_map) const noexcept {
57-
//TODO: Implement logging for intermediate tensors once ExecuTorch has support.
109+
[op_path_to_value_map enumerateKeysAndObjectsUsingBlock:^(ETCoreMLModelStructurePath *path,
110+
MLMultiArray *intermediate_value,
111+
BOOL * _Nonnull __unused stop) {
112+
using namespace torch::executor;
113+
114+
@autoreleasepool {
115+
NSString *symbol_name = op_path_to_debug_symbol_name_map[path];
116+
if (symbol_name == nil) {
117+
return;
118+
}
119+
120+
MLMultiArray *value = op_path_to_value_map[path];
121+
if (value == nil || value.count == 0) {
122+
return;
123+
}
124+
125+
MLMultiArray *supported_value = value;
126+
NSArray<NSNumber *> *shape = supported_value.shape;
127+
NSError *local_error = nil;
128+
MLMultiArrayDataType data_type = get_supported_data_type(value.dataType);
129+
130+
if (!is_packed(shape, value.strides) || (supported_value.dataType != data_type)) {
131+
supported_value = [[MLMultiArray alloc] initWithShape:shape
132+
dataType:data_type
133+
error:&local_error];
134+
NSCAssert(supported_value != nil,
135+
@"ModelEventLoggerImpl: Failed to create packed multiarray with shape=%@, dataType=%ld, error=%@.",
136+
shape,
137+
static_cast<long>(value.dataType),
138+
local_error);
139+
[value copyInto:supported_value];
140+
}
141+
142+
[supported_value getBytesWithHandler:^(const void * _Nonnull bytes, NSInteger size) {
143+
auto sizes = to_vector<TensorImpl::SizesType>(shape);
144+
auto strides = to_vector<TensorImpl::StridesType>(supported_value.strides);
145+
auto scalar_type = to_scalar_type(data_type);
146+
auto dim_order = std::vector<TensorImpl::DimOrderType>(shape.count);
147+
std::iota(std::begin(dim_order), std::end(dim_order), 0);
148+
149+
NSCAssert(scalar_type.has_value(), @"ModelEventLoggerImpl: MultiArray dataType=%ld is not supported.", static_cast<long>(data_type));
150+
auto tensor_impl = TensorImpl(
151+
scalar_type.value(),
152+
static_cast<ssize_t>(sizes.size()),
153+
sizes.data(),
154+
const_cast<void *>(bytes),
155+
dim_order.data(),
156+
strides.data());
157+
auto tensor = Tensor(&tensor_impl);
158+
tracer_->log_intermediate_output_delegate(symbol_name.UTF8String, -1, tensor);
159+
}];
160+
}
161+
}];
58162
}
59163
} // namespace executorchcoreml

backends/apple/coreml/runtime/sdk/model_package_info.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
#import <Foundation/Foundation.h>
1111

12-
#import <serde_json.h>
12+
#import "serde_json.h"
1313
#import <string>
1414
#import <unordered_map>
1515

backends/apple/coreml/runtime/sdk/model_package_info.mm

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77

88
#import "model_package_info.h"
99

10-
#import <ETCoreMLLogging.h>
11-
#import <objc_json_serde.h>
12-
#import <serde_json.h>
10+
#import "ETCoreMLLogging.h"
11+
#import "objc_json_serde.h"
12+
#import "serde_json.h"
1313

1414
namespace {
1515
struct ModelPackageInfoKeys {

0 commit comments

Comments
 (0)