M1 MacBook Pro vs. Intel i9 MacBook Pro,数据科学终极笔记本之战

2021-07-07 09:51:30 浏览数 (1)

预算没问题的情况下,数据科学应用最好选哪个笔记本?内核 M1 vs. i9–9880H, 我们全方位对比测试了复合benchmarks、 Python、 Numpy、 Pandas 和 Scikit Learn 性能来一探究竟。

M1 芯片是革命性的。谁能想到苹果的第一代芯片就将英特尔几十年的工程技术彻底摧毁了呢?未来的 M1X 和 M2 芯片令人遐想,但是现在的 M1 仍然有很多值得欣赏的地方。

今天,我们将在复合 benchmarks、 纯 Python、 Numpy、 Pandas 和 Scikit-Learn 中比较这两台机器的性能:

  • 2019年16寸 MacBook Pro — 英特尔 Core i9–9880H, 16GB RAM, 和 AMD Radeon Pro 5500M (在美国约3000美元)
  • 2020年13寸 M1 MacBook Pro — 苹果 M1 芯片, 8GB unified memory, 和 8个GPU 内核 (在美国约1300 美元)

请注意,这些只是简单的编程和数据科学 benchmarks,其实在每个测试领域都可以做更多的工作。敬请期待后续的文章。

今天的文章结构如下:

  • 复合 Benchmarks — Geekbench 和 Cinebench
  • 比较纯 Python 的性能
  • 比较 Numpy 的性能
  • 比较 Pandas 的性能
  • 比较 Scikit-Learn 的性能
  • 最后的想法

复合 Benchmarks — Geekbench 和 Cinebench

除了你马上就会看到的性能上的差异,还有一件重要的事情需要注意 — 16英寸基于英特尔的 MBP 运行起来会热,非常的热。以至于你不能把它放在自己的膝盖上(别人的膝盖不确定,你可以试下,被打不要找我),至少在夏天不能。M1 Mac 就没有这个问题。它的风扇在测试的最后几分钟才启动。

让我们从简单的 Geekbench 单核比较开始:

图1 ー Geekbench 单核得分比较

Wow.贵了三倍的机器性能居然不如便宜的。让我们看看多核测试是否同样如此。请记住,Intel i9-9880H 有8个内核:

图2 ー Geekbench 多核得分比较

太荒谬了,没什么好补充的了。

让我们看一下 Geekbench 的 GPU 测试。这种比较不是100% 公平的,因为 M1 Mac 没有专门的 GPU。以下是结果:

图3 ー 用 GPU 进行 Geekbench 比较

专用 GPU 的得分几乎是两倍,但这在意料之中。接下来,让我们来看一下 Cinebench 的单核和多核的对比。下面是单核的例子:

图4 ー Cinebench 单核得分比较

M1 芯片再次领先,让我们看看多核测试的结果:

图5 ー Cinebench 多核得分比较

这两台机器有点接近,但是基于英特尔的 Mac 这次赢了。总而言之,两者都是非常强的机器,但人们的预期是 i9 每次都会以明显的优势获胜,至少根据价格来说是这样的。

赢家 ー M1 MacBook Pro。 在大多数情况下,这是一台性能更好的机器,而且它不会融化掉你的裤子。

比较纯 Python 的性能

第一次为数据科学配置 M1 芯片可能是一种痛苦。如果你想原生运行所有的东西,这个过程和英特尔的芯片不一样。幸运的是,网上有不少可行的教程(如:https://towardsdatascience.com/how-to-easily-set-up-m1-macbooks-for-data-science-and-machine-learning-cd4f8a6b706d)。

我们将在纯 Python 测试中完成几个相对简单的任务:

  • 创建一个包含100,000,000个100到999之间的随机整数的列表 l
  • 把每项都平方
  • 取 l 中每项的平方根
  • 将相应的平方和平方根相乘
  • 将相应的平方和平方根相除
  • 对相应的平方和平方根执行整除

因为这是一个纯 Python 测试,所以不允许使用第三方库。这是代码段:

代码语言:javascript复制
import random

time_start = datetime.now()

l = [random.randrange(100, 999) for i in range(100000000)]

squared = [x**2 for x in l]
sqrt = [x**0.5 for x in l]
mul = [x * y for x, y in zip(squared, sqrt)]
div = [x / y for x, y in zip(squared, sqrt)]
int_div = [x // y for x, y in zip(squared, sqrt)]

time_end = datetime.now()
print(f'TOTAL TIME = {(time_end - time_start).seconds} seconds')

以下是结果:

图6 ー 纯 Python 性能比较

虽然差别不大,但对于 M1 芯片来说仍然是一个明显的胜利。

赢家: M1 MacBook Pro。 以三分之一的价格获得第一名。

比较 Numpy 的性能

下面是在这个 benchmark 中执行的任务列表:

  • 矩阵乘法(Matrix multiplication)
  • 矢量乘法(Vector multiplication)
  • 奇异值分解(Singular Value Decomposition)
  • 乔列斯基分解(Cholesky Decomposition)
  • 特征分解(Eigendecomposition)

最初的 benchmark 脚本是从 Github 上的 Markus Beuckelmann 那里(https://gist.github.com/markus-beuckelmann/8bc25531b11158431a5b09a45abd6276) 获取的,并经过了一些修改,因此可以获取开始和结束时间。下面是这个脚本:

代码语言:javascript复制
# SOURCE: https://gist.github.com/markus-beuckelmann/8bc25531b11158431a5b09a45abd6276

import numpy as np
from time import time
from datetime import datetime

start_time = datetime.now()

# Let's take the randomness out of random numbers (for reproducibility)
np.random.seed(0)

size = 4096
A, B = np.random.random((size, size)), np.random.random((size, size))
C, D = np.random.random((size * 128,)), np.random.random((size * 128,))
E = np.random.random((int(size / 2), int(size / 4)))
F = np.random.random((int(size / 2), int(size / 2)))
F = np.dot(F, F.T)
G = np.random.random((int(size / 2), int(size / 2)))

# Matrix multiplication
N = 20
t = time()
for i in range(N):
    np.dot(A, B)
delta = time() - t
print('Dotted two %dx%d matrices in %0.2f s.' % (size, size, delta / N))
del A, B

# Vector multiplication
N = 5000
t = time()
for i in range(N):
    np.dot(C, D)
delta = time() - t
print('Dotted two vectors of length %d in %0.2f ms.' % (size * 128, 1e3 * delta / N))
del C, D

# Singular Value Decomposition (SVD)
N = 3
t = time()
for i in range(N):
    np.linalg.svd(E, full_matrices = False)
delta = time() - t
print("SVD of a %dx%d matrix in %0.2f s." % (size / 2, size / 4, delta / N))
del E

# Cholesky Decomposition
N = 3
t = time()
for i in range(N):
    np.linalg.cholesky(F)
delta = time() - t
print("Cholesky decomposition of a %dx%d matrix in %0.2f s." % (size / 2, size / 2, delta / N))

# Eigendecomposition
t = time()
for i in range(N):
    np.linalg.eig(G)
delta = time() - t
print("Eigendecomposition of a %dx%d matrix in %0.2f s." % (size / 2, size / 2, delta / N))

print('')
end_time = datetime.now()
print(f'TOTAL TIME = {(end_time - start_time).seconds} seconds')

以下是结果:

图7 ー Numpy 性能比较

Numpy 则是另一回事。测试在英特尔芯片上完成得更快,最有可能的原因是 M1 芯片上没有英特尔数学内核库(Maths Kernel Libraries/MKL)。

赢家 ー 英特尔 i9 MacBook Pro。 目前 Numpy 运行速度更快。

比较 Pandas 的性能

这个 benchmark 与使用纯 Python 完成的 benchmark 非常相似。同样的操作被执行,但是结果被合并到一个 Pandas DataFrame:

  • 创建一个空的 data frame
  • 给它分配一个100,000,000个100到999之间的随机整数的列(X)
  • X 中每一项平方
  • 取 X 中每个项的平方根
  • 将相应的平方和平方根相乘
  • 将相应的平方和平方根相除
  • 对相应的平方和平方根执行整除

下面是代码段:

代码语言:javascript复制
import numpy as np
import pandas as pd
from datetime import datetime

time_start = datetime.now()

df = pd.DataFrame()
df['X'] = np.random.randint(low=100, high=999, size=100000000)
df['X_squared'] = df['X'].apply(lambda x: x**2)
df['X_sqrt'] = df['X'].apply(lambda x: x**0.5)
df['Mul'] = df['X_squared'] * df['X_sqrt']
df['Div'] = df['X_squared'] / df['X_sqrt']
df['Int_div'] = df['X_squared'] // df['X_sqrt']

time_end = datetime.now()
print(f'Total time = {(time_end - time_start).seconds} seconds')

以下是结果:

图8 ー Pandas的性能比较

英特尔 i9-9880H 是一个非常强大的处理器,但在这项任务上它看起来不如 M1芯片。

赢家 - M1 MacBook Pro。 速度更快,更安静。

Scikit-Learn 性能比较

让我们从基本的开始,做以下任务:

  • 从网上获取数据集
  • 执行训练/测试划分
  • 声明一个决策树模型并找到最佳的超参数(2400个组合 5-fold 的交叉验证)
  • 用最优参数拟合模型
  • 这或多或少是一个标准的模型训练过程,不管是哪种算法的测试、数据准备和特征工程。

下面是测试的代码段:

代码语言:javascript复制
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.metrics import accuracy_score, confusion_matrix

time_start = datetime.now()

# Dataset
iris = pd.read_csv('https://gist.githubusercontent.com/curran/a08a1080b88344b0c8a7/raw/0e7a9b0a5d22642a06d3d5b9bcbad9890c8ee534/iris.csv')
time_load = datetime.now()
print(f'Dataset loaded, runtime = {(time_load - time_start).seconds} seconds')

# Train/Test split
X = iris.drop('species', axis=1)
y = iris['species']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25)
time_split = datetime.now()
print(f'Train/test split, runtime = {(time_split - time_start).seconds} seconds')

# Hyperparameter tuning
model = DecisionTreeClassifier()
params = {
    'criterion': ['gini', 'entropy'],
    'splitter': ['best', 'random'],
    'max_depth': [1, 5, 10, 50, 100, 250, 500, 1000],
    'min_samples_split': [2, 5, 10, 15, 20],
    'min_samples_leaf': [1, 2, 3, 4, 5],
    'max_features': ['auto', 'sqrt', 'log2']
}
clf = GridSearchCV(
    estimator=model, 
    param_grid=params, 
    cv=5
)
clf.fit(X_train, y_train)
time_optim = datetime.now()
print(f'Hyperparameter optimization, runtime = {(time_optim - time_start).seconds} seconds')

best_model = DecisionTreeClassifier(**clf.best_params_)
best_model.fit(X_train, y_train)

time_end = datetime.now()
print()
print(f'TOTAL RUNTIME = {(time_end - time_start).seconds} seconds')

以下是结果:

图9 ー Scikit-Learn 性能比较

结果不言自明,我没有什么要补充的了。

赢家: M1 MacBook Pro。 速度快了一倍,价格只有三分之一。

最后的想法

M1 芯片无疑是革命性的。我已经完成了你在文章中看到的所有 benchmarks,并编写和编辑了整篇文章,还在 Netflix 上观看了40分钟的视频,但电池竟然还剩 83% !

M1 Macs 没有专用的 GPU,但这不是问题。大概率你不会使用任何笔记本电脑来完成非常耗资源和时间的任务,特别是深度学习。在云端做这种事更有效率。

因此,对于日常的数据科学和分析工作来说,M1似乎是不二之选 - 性能出众又酷,而且续航时间长达两个工作日。如果你想买一台新的 Mac,并且你需要的所有东西都与 M1芯片兼容,我认为没有理由再花2-4倍的钱买英特尔。

原文: https://towardsdatascience.com/m1-macbook-pro-vs-intel-i9-macbook-pro-ultimate-data-science-comparison-dde8fc32b5df

0 人点赞