为啥 M1 Max 上的原生 Python 比旧 Intel i5 上的 Python 慢得多?
Posted
技术标签:
【中文标题】为啥 M1 Max 上的原生 Python 比旧 Intel i5 上的 Python 慢得多?【英文标题】:Why Python native on M1 Max is greatly slower than Python on old Intel i5?为什么 M1 Max 上的原生 Python 比旧 Intel i5 上的 Python 慢得多? 【发布时间】:2022-01-11 08:49:48 【问题描述】:我刚拿到带有 M1 Max 芯片的新 MacBook Pro,并且正在设置 Python。我已经尝试了几种组合设置来测试速度 - 现在我很困惑。先把我的问题放在这里:
为什么在 M1 Max 上原生运行 python 比在我的配备 Intel i5 的旧 MacBook Pro 2016 上慢很多(~100%)? 在 M1 Max 上,为什么原生运行(通过 miniforge)和通过 Rosetta 运行(通过 anaconda)之间没有显着的速度差异 - 应该慢约 20%? 在 M1 Max 和原生运行中,为什么 conda 安装的 Numpy 和 TensorFlow 安装的 Numpy 之间没有显着的速度差异 - 应该更快? 在 M1 Max 上,为什么在 PyCharm IDE 中运行总是比从终端运行慢约 20%,这在我的旧 Intel Mac 上不会发生。支持我的问题的证据如下:
这是我尝试过的设置:
1.由
安装的Python Miniforge-arm64,因此 python 在 M1 Max 芯片上原生运行。 (从活动监视器检查,python 进程的Kind
是Apple
)。
Anaconda。然后通过Rosseta运行python。 (从活动监视器检查,python 进程的Kind
是Intel
)。
2。由
安装的 Numpyconda install numpy
: numpy 来自原 conda-forge 频道,或预装了 anaconda。
Apple-TensorFlow:用miniforge安装的python,我直接安装tensorflow,numpy也会安装。据说这样安装的numpy是针对苹果M1优化的,速度会更快。以下是安装命令:
conda install -c apple tensorflow-deps
python -m pip install tensorflow-macos
python -m pip install tensorflow-metal
3.从
运行 终端。 PyCharm (Apple Silicon version)。这里是测试代码:
import time
import numpy as np
np.random.seed(42)
a = np.random.uniform(size=(300, 300))
runtimes = 10
timecosts = []
for _ in range(runtimes):
s_time = time.time()
for i in range(100):
a += 1
np.linalg.svd(a)
timecosts.append(time.time() - s_time)
print(f'mean of runtimes runs: np.mean(timecosts):.5fs')
结果如下:
+-----------------------------------+-----------------------+--------------------+
| Python installed by (run on)→ | Miniforge (native M1) | Anaconda (Rosseta) |
+----------------------+------------+------------+----------+----------+---------+
| Numpy installed by ↓ | Run from → | Terminal | PyCharm | Terminal | PyCharm |
+----------------------+------------+------------+----------+----------+---------+
| Apple Tensorflow | 4.19151 | 4.86248 | / | / |
+-----------------------------------+------------+----------+----------+---------+
| conda install numpy | 4.29386 | 4.98370 | 4.10029 | 4.99271 |
+-----------------------------------+------------+----------+----------+---------+
这很慢。为了比较,
在我的带有 i5 芯片的旧 MacBook Pro 2016 上运行相同的代码 - 花费2.39917s
。
另一个 post (but not in English) 报告使用 M1 芯片(不是 Pro 或 Max)运行,miniforge+conda_installed_numpy 是 2.53214s
,miniforge+apple_tensorflow_numpy 是 1.00613s
.
您也可以自己试一试。
这里是CPU信息详情:
我的旧 i5:$ sysctl -a | grep -e brand_string -e cpu.core_count
machdep.cpu.brand_string: Intel(R) Core(TM) i5-6360U CPU @ 2.00GHz
machdep.cpu.core_count: 2
我的新 M1 Max:
% sysctl -a | grep -e brand_string -e cpu.core_count
machdep.cpu.brand_string: Apple M1 Max
machdep.cpu.core_count: 10
我严格按照教程中的说明进行操作 - 但为什么会发生所有这些情况?是因为我的安装缺陷,还是因为M1 Max芯片?由于我的工作严重依赖本地跑步,本地速度对我来说非常重要。对可能的解决方案的任何建议,或您自己设备上的任何数据点将不胜感激:)
【问题讨论】:
我还没有 M1。最简单的测试方法是比较正确设置的人员的设置。以下是指向a set of benchmarks 和the installation procedure they used 的链接,包括活动监视器中的性能应该如何显示。如果你能复制他们的结果,那么 M1 就无法处理你的代码,否则就是安装。 【参考方案1】:如何在 M1 Max 上安装 numpy,加速性能最高(苹果的 vecLib)?这是截至 2021 年 12 月 6 日的答案。
步骤
我。安装 miniforge
这样您的 Python 就可以在 arm64 上本地运行,而不是通过 Rosseta 进行翻译。
-
下载Miniforge3-MacOSX-arm64.sh,然后
运行脚本,然后打开另一个 shell
$ bash Miniforge3-MacOSX-arm64.sh
-
创建环境(这里我使用名称
np_veclib
)
$ conda create -n np_veclib python=3.9
$ conda activate np_veclib
二。使用指定为 vecLib 的 BLAS 接口安装 Numpy
-
要编译
numpy
,首先需要安装cython
和pybind11
:
$ conda install cython pybind11
-
编译
numpy
(感谢@Marijn 的answer) - 不要使用conda install
!
$ pip install --no-binary :all: --no-use-pep517 numpy
-
2. 的替代方法是从源代码构建
$ git clone https://github.com/numpy/numpy
$ cd numpy
$ cp site.cfg.example site.cfg
$ nano site.cfg
编辑复制的site.cfg
:添加以下行:
[accelerate]
libraries = Accelerate, vecLib
然后构建并安装:
$ NPY_LAPACK_ORDER=accelerate python setup.py build
$ python setup.py install
-
在 2 或 3 之后,现在测试 numpy 是否在使用 vecLib:
>>> import numpy
>>> numpy.show_config()
然后,应该打印像/System/Library/Frameworks/vecLib.framework/Headers
这样的信息。
三。使用 conda 进一步安装其他软件包
让 conda 识别 pip 安装的包
conda config --set pip_interop_enabled true
必须这样做,否则如果例如conda install pandas
,然后numpy
将在The following packages will be installed
列表中并再次安装。但是新装的是conda-forge
频道,速度慢。
与其他安装的比较:
1。竞争对手:
除了上面那个最优的,我还尝试了其他几种安装方式
A.np_default
: conda create -n np_default python=3.9 numpy
乙。 np_openblas
: conda create -n np_openblas python=3.9 numpy blas=*=*openblas*
C. np_netlib
: conda create -n np_netlib python=3.9 numpy blas=*=*netlib*
以上 ABC 选项直接从 conda-forge 频道安装。 numpy.show_config()
将显示相同的结果。要查看差异,请通过conda list
检查 - 例如openblas
包安装在 B 中。注意,mkl
或 blis
在 arm64 上不受支持。
np_openblas_source
:首先通过brew install openblas
安装openblas。然后将 [openblas]
路径 /opt/homebrew/opt/openblas
添加到 site.cfg
并从源代码构建 Numpy。
M1
和 i9–9880H
在这个 post 中。
我在 MacBook Pro 2016 13 英寸上的旧 i5-6360U
2cores。
2。基准:
这里我使用了两个基准:
mysvd.py
: 我的 SVD 分解
import time
import numpy as np
np.random.seed(42)
a = np.random.uniform(size=(300, 300))
runtimes = 10
timecosts = []
for _ in range(runtimes):
s_time = time.time()
for i in range(100):
a += 1
np.linalg.svd(a)
timecosts.append(time.time() - s_time)
print(f'mean of runtimes runs: np.mean(timecosts):.5fs')
dario.py
:Dario Radečić 在上面的帖子中的基准脚本。
3。结果:
+-------+-----------+------------+-------------+-----------+--------------------+----+----------+----------+
| sec | np_veclib | np_default | np_openblas | np_netlib | np_openblas_source | M1 | i9–9880H | i5-6360U |
+-------+-----------+------------+-------------+-----------+--------------------+----+----------+----------+
| mysvd | 1.02300 | 4.29386 | 4.13854 | 4.75812 | 12.57879 | / | / | 2.39917 |
+-------+-----------+------------+-------------+-----------+--------------------+----+----------+----------+
| dario | 21 | 41 | 39 | 323 | 40 | 33 | 23 | 78 |
+-------+-----------+------------+-------------+-----------+--------------------+----+----------+----------+
【讨论】:
在pip install
命令中添加--no-use-pep517
的目的是什么?
--no-binary :all:
忽略所有现有的***并从头开始构建***。那么没有--no-use-pep517
会导致could not build wheels for ...
错误。【参考方案2】:
可能原因:不同的 BLAS 库
由于基准测试运行的是线性代数例程,因此这里可能测试的是 BLAS 实现。 osx-64 平台的默认 Anaconda 发行版将与 Intel 的 MKL 实现一起提供; osx-arm64 平台只有通用的 Netlib BLAS 和 OpenBLAS 实现选项。
对于我(MacOS w/ Intel i9),我得到以下基准测试结果:
BLAS Implmentation | Mean Timing (s) |
---|---|
mkl |
0.95932 |
blis |
1.72059 |
openblas |
2.17023 |
netlib |
5.72782 |
所以,我怀疑旧的 MBP 安装了 MKL,而 M1 系统正在安装 Netlib 或 OpenBLAS。也许尝试弄清楚 Netlib 或 OpenBLAS 在 M1 上是否更快,并保留更快的那个。
指定 BLAS 实现
以下是我测试的不同环境:
# MKL
conda create -n np_mkl python=3.9 numpy blas=*=*mkl*
# BLIS
conda create -n np_blis python=3.9 numpy blas=*=*blis*
# OpenBLAS
conda create -n np_openblas python=3.9 numpy blas=*=*openblas*
# Netlib
conda create -n np_netlib python=3.9 numpy blas=*=*netlib*
并使用
运行基准脚本 (so-np-bench.py
)
conda run -n np_mkl python so-np-bench.py
# etc.
【讨论】:
谢谢@merv。我想这是正确的方法。我创建了 3 个环境:np_default
、np_openblas
和 np_netlib
。但是每个都产生非常相似的结果。并进一步查看numpy.show_config()
使用了哪个 BLAS 接口——每个都完全相同——只有libraries = ['cblas', 'blas', 'cblas', 'blas']
在blas_info
中,没有openblas
或netlib
——这意味着他们三个实际上安装了相同的numpy。你能解释一下原因吗?
我问了一个朋友,他用的是 M1,不是 M1 Pro 或 Max。他使用与我完全相同的程序来安装 python(通过 miniforge,然后是 conda install numpy
)。但是他在他的 numpy 中得到了openblas
,而我没有。
在使用conda安装相应的numpy之前,是否需要自己安装openblas和netlib?
@graphitump BLAS 库将全部显示为与 numpy.show_config()
相同,因为它们(libblas
、libcblas
、liblapack
等)使用相同的名称并具有相同的 API,但链接到不同的库(openblas
、mkl
等)。您必须检查conda list
包builds,其中包含openblas
、netlib
等字符串。
@graphitump 库应该通过 Conda 安装,如答案中所示。以上是关于为啥 M1 Max 上的原生 Python 比旧 Intel i5 上的 Python 慢得多?的主要内容,如果未能解决你的问题,请参考以下文章
PHP - 为啥新的 SQLSRV 驱动程序比旧的 mssql 驱动程序慢?
安装 mongodb 将 amazon EC2 m1.large 实例升级到 m3.large
为啥 Android 原生 HTML5 日期选择器上的 Chrome 变得非常慢?