开篇提醒:本文系无机云评测。

前情提要

今天在知乎上看到了 Apple Silicon M1 机器学习性能简单测试,突然沸腾了(沸腾体警告⚠️)。文章中用一段cnn训练mnist的代码在几台机器上分别运行,以每batch运行时间为评测标准,横向对比。正好我也把手头的几个电脑加入这个对比中。

运行结果

把文章中的结果和我跑出来的结果以及github上看到的结果总结之后放在一起,我最感兴趣的数据就是我的mbp的GPU对比m1,即使他是一个不十分准确的对比也让我对m1有了个粗略的认识。

  CPU GPU
Macbook Air 2020 M1   24s
Macbook Pro 2020 M1   23s
MacMini 2020 M1 16s 22s
Macbook Pro 13 2015(i5 5257u ?) 310s ?  
🧑‍💻 xfangfang’s MacBook Air 13 2015(i5 5250u) 85s  
🧑‍💻 xfangfang’s Macbook Pro 15 2018(i7 8750h; RadeonPro555x) 45s 27s
🧑‍💻 xfangfang’s PC(Ryzen5 3600; 2070super) 22s 2s

说的有些迟到,但是好像ARM的时代真的来了。手上这台18款mbp的CPU发热巨大,日常使用60度,动不动就跑到100度,CPU跑这个卷积更是风扇满转,不过切到GPU去运行倒是完全不热。日常的高温让我爱不起来,看了数据甚至有点想入手下一代ARM处理器的Macbook。

数据粗粗浏览下载,有的机型前后差距很大,应该是tensorflow正在对M1不断优化,ARM真的是未来可期了啊。

附:评测脚本

github评测结果: https://github.com/apple/tensorflow_macos/issues/25

为了可以用mbp18的GPU,稍微修改了一些,应该和github中的脚本跑起来差不多。

1
2
3
4
5
6
7
8
# 运行在macbook上 使用plaidml keras开启AMD GPU支持
# pip install plaidml-keras
# terminal 运行 plaidml-setup 选择对应的显卡
import plaidml.keras
plaidml.keras.install_backend()
import os
os.environ["KERAS_BACKEND"] = "plaidml.keras.backend"
import keras
1
2
3
4
5
# 通用脚本 CPU
import os
os.environ['CUDA_VISIBLE_DEVICES'] = '-1'
import tensorflow
keras = tensorflow.keras
1
2
3
4
# 通用脚本 GPU
gpus = tf.config.experimental.list_physical_devices('GPU')
assert len(gpus) > 0, "Not enough GPU hardware devices available"
tf.config.experimental.set_memory_growth(gpus[0], True)

上面三段代码片段,分别和下面的脚本组合,用来在不同设备上运行

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
import time
import numpy as np
from datetime import timedelta

mnist = keras.datasets.mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
train_images = np.expand_dims(train_images, axis=3) / 255.0
test_images = np.expand_dims(test_images, axis=3) / 255.0

model = keras.models.Sequential([
    keras.layers.Conv2D(32, kernel_size=(3, 3), activation='relu',input_shape=(28,28,1)),
    keras.layers.Conv2D(64, kernel_size=(3, 3), activation='relu'),
    keras.layers.MaxPooling2D(pool_size=(2, 2)),
    keras.layers.Flatten(),
    keras.layers.Dense(128, activation='relu'),
    keras.layers.Dense(10, activation='softmax')
])
model.compile(
    loss='sparse_categorical_crossentropy',
    optimizer=keras.optimizers.Adam(0.001),
    metrics=['accuracy'],
)
start = time.time()
model.fit(
    train_images,
    train_labels,
    epochs=10,
    batch_size=128
)
delta = (time.time() - start)
elapsed = str(timedelta(seconds=delta))
print('Elapsed Time: {}'.format(elapsed))