-
Notifications
You must be signed in to change notification settings - Fork 762
Expand file tree
/
Copy pathCoreMLPython.h
More file actions
281 lines (222 loc) · 9.43 KB
/
CoreMLPython.h
File metadata and controls
281 lines (222 loc) · 9.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
// Copyright (c) 2021, Apple Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-3-clause license that can be
// found in the LICENSE.txt file or at https://opensource.org/licenses/BSD-3-Clause
// Disable a few warnings and include pybind first, then re-enable warnings
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wexit-time-destructors"
#pragma clang diagnostic ignored "-Wdocumentation"
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#pragma clang diagnostic pop
#import <CoreML/CoreML.h>
#import <Availability.h>
#import <vector>
#import <optional>
#ifndef BUILT_WITH_MACOS15_SDK
#if TARGET_OS_OSX && defined(__MAC_15_0) && __MAC_OS_X_VERSION_MAX_ALLOWED >= __MAC_15_0
#define BUILT_WITH_MACOS15_SDK 1
#else
#define BUILT_WITH_MACOS15_SDK 0
#endif
#endif
// Print BUILT_WITH_MACOS15_SDK value
#if BUILT_WITH_MACOS15_SDK
#pragma message ("Building with macOS 15+ SDK")
#else
#pragma message ("Building without macOS 15 SDK")
#endif
#if !defined(ML_COMPUTE_PLAN_IS_AVAILABLE) && __has_include(<CoreML/MLComputePlan.h>)
#define ML_COMPUTE_PLAN_IS_AVAILABLE 1
#endif
#if !defined(ML_MODEL_STRUCTURE_IS_AVAILABLE) && __has_include(<CoreML/MLModelStructure.h>)
#define ML_MODEL_STRUCTURE_IS_AVAILABLE 1
#endif
#if !defined(ML_COMPUTE_DEVICE_IS_AVAILABLE) && __has_include(<CoreML/MLComputeDeviceProtocol.h>)
#define ML_COMPUTE_DEVICE_IS_AVAILABLE 1
#endif
#if !defined(ML_MODEL_ASSET_IS_AVAILABLE) && __has_include(<CoreML/MLModelAsset.h>)
#define ML_MODEL_ASSET_IS_AVAILABLE 1
#endif
#if !defined(ML_STATE_IS_AVAILABLE) && __has_include(<CoreML/MLState.h>)
#define ML_STATE_IS_AVAILABLE 1
#endif
namespace py = pybind11;
namespace CoreML {
namespace Python {
struct State {
// MLState must be wrapped in a C++ class for PyBind.
inline State(id impl):
m_impl(impl) {}
#if ML_STATE_IS_AVAILABLE
API_AVAILABLE(macos(15.0))
inline MLState *getImpl() const {
return (MLState *)m_impl;
}
#endif
// Retrieves the value of the specified state variable from the model.
py::object readState(const std::string& stateName) const;
// Sets the value of the specified state variable in the model.
void writeState(const std::string& stateName, py::object value);
private:
// Type erase `m_impl` otherwise it will result in a compiler warning.
id m_impl = nil;
};
struct CPUComputeDevice {
inline CPUComputeDevice():
m_impl(nil) {}
// MLCPUComputeDevice must be wrapped in a C++ class for PyBind.
inline CPUComputeDevice(id impl):
m_impl(impl) {}
#if ML_COMPUTE_DEVICE_IS_AVAILABLE
API_AVAILABLE(macos(14.0))
inline MLCPUComputeDevice *getImpl() const {
return (MLCPUComputeDevice *)m_impl;
}
#endif
private:
// Type erase `m_impl` otherwise it will result in a compiler warning.
id m_impl = nil;
};
struct GPUComputeDevice {
inline GPUComputeDevice():
m_impl(nil) {}
// MLGPUComputeDevice must be wrapped in a C++ class for PyBind.
inline GPUComputeDevice(id impl):
m_impl(impl) {}
#if ML_COMPUTE_DEVICE_IS_AVAILABLE
API_AVAILABLE(macos(14.0))
inline MLGPUComputeDevice *getImpl() const {
return (MLGPUComputeDevice *)m_impl;
}
#endif
private:
// Type erase `m_impl` otherwise it will result in a compiler warning.
id m_impl = nil;
};
struct NeuralEngineComputeDevice {
inline NeuralEngineComputeDevice():
m_impl(nil) {}
// MLNeuralEngineComputeDevice must be wrapped in a C++ class for PyBind.
inline NeuralEngineComputeDevice(id impl):
m_impl(impl) {}
#if ML_COMPUTE_DEVICE_IS_AVAILABLE
API_AVAILABLE(macos(14.0))
inline MLNeuralEngineComputeDevice *getImpl() const {
return (MLNeuralEngineComputeDevice *)m_impl;
}
#endif
int getTotalCoreCount() const;
private:
// Type erase `m_impl` otherwise it will result in a compiler warning.
id m_impl = nil;
};
struct ModelStructureProgramOperation {
// MLModelStructureProgramOperation must be wrapped in a C++ class for PyBind.
inline ModelStructureProgramOperation(id impl):
m_impl(impl) {}
#if ML_MODEL_STRUCTURE_IS_AVAILABLE
API_AVAILABLE(macos(14.4))
inline MLModelStructureProgramOperation *getImpl() const {
return (MLModelStructureProgramOperation *)m_impl;
}
#endif
private:
// Type erase `m_impl` otherwise it will result in a compiler warning.
__weak id m_impl = nil;
};
struct ModelStructureNeuralNetworkLayer {
// ModelStructureNeuralNetworkLayer must be wrapped in a C++ class for PyBind.
inline ModelStructureNeuralNetworkLayer(id impl):
m_impl(impl) {}
#if ML_MODEL_STRUCTURE_IS_AVAILABLE
API_AVAILABLE(macos(14.4))
inline MLModelStructureNeuralNetworkLayer *getImpl() const {
return (MLModelStructureNeuralNetworkLayer *)m_impl;
}
#endif
private:
// Type erase `m_impl` otherwise it will result in a compiler warning.
__weak id m_impl = nil;
};
struct ComputePlan {
inline ComputePlan():
m_impl(nil), m_modelStructure(py::none()) {}
// MLComputePlan must be wrapped in a C++ class for PyBind.
inline ComputePlan(id impl, py::object modelStructure):
m_impl(impl),
m_modelStructure(modelStructure) {}
inline py::object getModelStructure() const {
return m_modelStructure;
}
#if ML_COMPUTE_PLAN_IS_AVAILABLE
API_AVAILABLE(macos(14.4))
inline MLComputePlan *getImpl() const {
return (MLComputePlan *)m_impl;
}
py::object getComputeDeviceUsageForMLProgramOperation(py::object operation);
py::object getComputeDeviceUsageForNeuralNetworkLayer(py::object layer);
py::object getEstimatedCostForMLProgramOperation(py::object operation);
#endif
private:
id m_impl = nil;
py::object m_modelStructure;
};
struct ModelAsset {
// MLModelAsset must be wrapped in a C++ class for PyBind.
inline ModelAsset(id impl, std::vector<py::bytes> datas):
m_impl(impl),
m_datas(std::move(datas)) {}
#if ML_MODEL_ASSET_IS_AVAILABLE
API_AVAILABLE(macos(13.0))
inline MLModelAsset *getImpl() const {
return (MLModelAsset *)m_impl;
}
#endif
id m_impl = nil;
std::vector<py::bytes> m_datas;
};
class Model {
private:
MLModel *m_model = nil;
NSURL *compiledUrl = nil;
bool m_deleteCompiledModelOnExit = false;
std::optional<uint64_t> m_loadDurationInNanoSeconds;
std::optional<uint64_t> m_lastPredictDurationInNanoSeconds;
public:
static py::bytes autoSetSpecificationVersion(const py::bytes& modelBytes);
static py::str compileModel(const std::string& urlStr);
static int32_t maximumSupportedSpecificationVersion();
static void setComputeUnit(MLModelConfiguration *configuration, const std::string& computeUnits);
Model(const Model&) = delete;
Model& operator=(const Model&) = delete;
~Model();
explicit Model(const std::string& urlStr,
const std::string& computeUnits,
const std::string& functionName,
const py::dict& optimizationHints,
const py::object& asset);
explicit Model(const std::string& urlStr,
const std::string& computeUnits,
const std::string& functionName,
const py::dict& optimizationHints);
explicit Model(MLModel* m_model, NSURL* compiledUrl, bool deleteCompiledModelOnExit);
py::list batchPredict(const py::list& batch);
py::str getCompiledModelPath() const;
py::dict predict(const py::dict& input, State* state=NULL);
py::object getLoadDurationInNanoSeconds() const;
py::object getLastPredictDurationInNanoSeconds() const;
#if BUILT_WITH_MACOS15_SDK
static void setOptimizationHints(MLModelConfiguration *configuration, const py::dict& optimizationHints);
State newState() const;
#endif
static py::object createModelAssetFromPath(const std::string& path);
static py::object createModelAssetFromMemory(const py::bytes& specData, const py::dict& blobMapping);
static py::object getModelStructure(const std::string& modelPath);
static py::list getAvailableComputeDevices();
static py::list getAllComputeDevices();
static py::object getComputePlan(const std::string& modelPath, const std::string& computeUnits);
};
}
}