我们知道,一般机器学习都会考虑使用GPU进行加速。从iOS 12开始,Core ML不仅支持了GPU加速,还支持了Apple Neural Engine加速。Apple Neural Engine大家可以看苹果的官方介绍。
要使用GPU和Apple Neural Engine,我们需要在初始化模型类对象的时候,传入配置。我们在初始化模型(MLModel类头文件)的时候,可以看到如下两个方法(注意第二个方法需要iOS 12):
/// Construct a model with a default MLModelConfiguration object
+ (nullable instancetype)modelWithContentsOfURL:(NSURL *)url
error:(NSError **)error;
/// Construct a model given the location of its on-disk representation. Returns nil on error.
+ (nullable instancetype)modelWithContentsOfURL:(NSURL *)url
configuration:(MLModelConfiguration *)configuration
error:(NSError * _Nullable __autoreleasing *)error API_AVAILABLE(macos(10.14), ios(12.0), watchos(5.0), tvos(12.0));
前者是从文件路径加载mlmodelc的方法,而后者多了一个configuration。让我们看到这个MLModelConfiguration类:
@interface MLModelConfiguration : NSObject <NSCopying>
@property (readwrite) MLComputeUnits computeUnits;
@end
可以看到目前只有一个计算单元的配置属性,该属性是一个枚举:
typedef NS_ENUM(NSInteger, MLComputeUnits) {
MLComputeUnitsCPUOnly = 0,
MLComputeUnitsCPUAndGPU = 1
,
MLComputeUnitsAll = 2
} API_AVAILABLE(macos(10.14), ios(12.0), watchos(5.0), tvos(12.0));
MLComputeUnits官方文档对这三个配置的解释如下:
Processing Unit Configurations:
- MLComputeAll:
The model is allowed to use all compute units available, including the neural engine.- MLComputeCPUOnly:
The model is only allowed to use the CPU.- MLComputeCPUAndGPU:
The model is allowed to use both the CPU and GPU, but not the neural engine.
翻译一下:
- MLComputeCPUOnly:
只用CPU - MLComputeCPUAndGPU:
用CPU和GPU,不包括Apple Neural Engine - MLComputeAll:
所有能用的计算单元,包括Apple Neural Engine
我们回顾一下以往的发布会,可以发现,iPhone 8及以上版本的设备,才搭载了集成有Apple Neural Engine的芯片。
性能测试
我iPhone X和iPhone 7上进行一些性能测试,我们的测试内容为:
对同一张图片,用同一个模型(这里用的是MobileNet.mlmodel),使用上述三种不同的计算单元,分别进行1000次预测计算,统计总用时。
以下是我的测试结果:
结论:
- 似乎iPhone X搭载A11芯片在Core ML上并没有起到很好的作用。不知道最新的A12是否有所改观。
- 但是GPU加速后的运算性能则明显比只用CPU要好很多了。
多线程
既然代码写到这里,我又测试了一下MLModel的线程安全问题:
创建一个Model类对象,然后创建1000个预测任务,全部放到子线程队列中并发计算。
测试结果发现,在各个环境和配置下,并没有出现什么问题。我们可以猜测MLModel是线程安全的。
去官方文档上找,并没有找到多线程相关的说明,因此实际上Core ML到底是否线程安全,还需要等官方文档说明。