为什么 M1 Max 上的 Python native 比旧的 Intel i5 上的 Python 慢得多?
Why Python native on M1 Max is greatly slower than Python on old Intel i5?
我刚拿到带有 M1 Max 芯片的新 MacBook Pro,正在设置 Python。我已经尝试了几种组合设置来测试速度 - 现在我很困惑。先把我的问题放在这里:
- 为什么 python 运行 在 M1 Max 上比在我的旧 MacBook Pro 2016 with Intel i5 上慢很多 (~100%)?
- 在 M1 Max 上,为什么原生 运行(通过 miniforge)和通过 Rosetta(通过 anaconda)的 运行 之间没有明显的速度差异 - 应该慢 ~20% ?
- 在 M1 Max 和本机 运行 上,为什么 conda 安装的 Numpy 和 TensorFlow 安装的 Numpy 之间没有明显的速度差异 - 哪个应该更快?
- 在 M1 Max 上,为什么 运行 in PyCharm IDE 总是比终端的 运行 慢 ~20%,这在我的旧 Intel 上不会发生Mac.
支持我的问题的证据如下:
以下是我试过的设置:
1. Python 由
安装
- Miniforge-arm64,因此 python 在 M1 Max 芯片上是原生的 运行。 (从 Activity 监视器检查,python 进程的
Kind
是 Apple
)。
- Anaconda。然后 python 通过 Rosseta 是 运行。 (从 Activity 监视器检查,python 进程的
Kind
是 Intel
)。
2。
安装的 Numpy
conda install numpy
: 来自原始 conda-forge 频道的 numpy,或预装了 anaconda。
- Apple-TensorFlow:用miniforge安装的python,我直接安装tensorflow,numpy也会安装。据说,这样安装的numpy针对Apple 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):.5f}s')
结果如下:
+-----------------------------------+-----------------------+--------------------+
| 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芯片的问题?由于我的工作严重依赖本地 运行s,因此本地速度对我来说非常重要。对可能的解决方案或您自己设备上的任何数据点的任何建议将不胜感激:)
可能的原因:不同的 BLAS 库
由于基准是 运行 线性代数例程,这里可能测试的是 BLAS 实现。 osx-64 平台的默认 Anaconda 发行版将随英特尔的 MKL 实现一起提供; osx-arm64 平台只有通用的 Netlib BLAS 和 OpenBLAS 实现选项。
对于我(配备 Intel i9 的 MacOS),我得到以下基准测试结果:
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.
2022 年 3 月 28 日更新:请参阅下面@AndrejHribernik 的评论。
如何在M1 Max上安装numpy,加速性能最强(苹果的vecLib)?这是截至 2021 年 12 月 6 日的答案。
步骤
我。安装 miniforge
所以你的 Python 是 运行 原生的 arm64,不是通过 Rosseta 翻译的。
- 下载Miniforge3-MacOSX-arm64.sh,然后
- 运行脚本,然后再打开一个shell
$ bash Miniforge3-MacOSX-arm64.sh
- 创建环境(这里我用name
np_veclib
)
$ conda create -n np_veclib python=3.9
$ conda activate np_veclib
二.使用指定为 vecLib
的 BLAS 接口安装 Numpy
- 要编译
numpy
,首先需要安装cython
和pybind11
:
$ conda install cython pybind11
- 通过(感谢@Marijn 的 answer)编译
numpy
- 不要使用 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。竞争对手:
除了上面那个最优的,我也尝试了其他几种安装方式
- 一个。
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 上不支持。
- D.
np_openblas_source
:首先通过brew install openblas
安装openblas。然后将 [openblas]
路径 /opt/homebrew/opt/openblas
添加到 site.cfg
并从源代码构建 Numpy。
M1
和 i9–9880H
在这个 post.
- 我的旧
i5-6360U
2 核 MacBook Pro 2016 13 英寸
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):.5f}s')
dario.py
:Dario Radečić 在上面 post 的基准测试脚本。
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 |
+-------+-----------+------------+-------------+-----------+--------------------+----+----------+----------+
我刚拿到带有 M1 Max 芯片的新 MacBook Pro,正在设置 Python。我已经尝试了几种组合设置来测试速度 - 现在我很困惑。先把我的问题放在这里:
- 为什么 python 运行 在 M1 Max 上比在我的旧 MacBook Pro 2016 with Intel i5 上慢很多 (~100%)?
- 在 M1 Max 上,为什么原生 运行(通过 miniforge)和通过 Rosetta(通过 anaconda)的 运行 之间没有明显的速度差异 - 应该慢 ~20% ?
- 在 M1 Max 和本机 运行 上,为什么 conda 安装的 Numpy 和 TensorFlow 安装的 Numpy 之间没有明显的速度差异 - 哪个应该更快?
- 在 M1 Max 上,为什么 运行 in PyCharm IDE 总是比终端的 运行 慢 ~20%,这在我的旧 Intel 上不会发生Mac.
支持我的问题的证据如下:
以下是我试过的设置:
1. Python 由
安装- Miniforge-arm64,因此 python 在 M1 Max 芯片上是原生的 运行。 (从 Activity 监视器检查,python 进程的
Kind
是Apple
)。 - Anaconda。然后 python 通过 Rosseta 是 运行。 (从 Activity 监视器检查,python 进程的
Kind
是Intel
)。
2。
安装的 Numpyconda install numpy
: 来自原始 conda-forge 频道的 numpy,或预装了 anaconda。- Apple-TensorFlow:用miniforge安装的python,我直接安装tensorflow,numpy也会安装。据说,这样安装的numpy针对Apple 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):.5f}s')
结果如下:
+-----------------------------------+-----------------------+--------------------+
| 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芯片的问题?由于我的工作严重依赖本地 运行s,因此本地速度对我来说非常重要。对可能的解决方案或您自己设备上的任何数据点的任何建议将不胜感激:)
可能的原因:不同的 BLAS 库
由于基准是 运行 线性代数例程,这里可能测试的是 BLAS 实现。 osx-64 平台的默认 Anaconda 发行版将随英特尔的 MKL 实现一起提供; osx-arm64 平台只有通用的 Netlib BLAS 和 OpenBLAS 实现选项。
对于我(配备 Intel i9 的 MacOS),我得到以下基准测试结果:
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.
2022 年 3 月 28 日更新:请参阅下面@AndrejHribernik 的评论。
如何在M1 Max上安装numpy,加速性能最强(苹果的vecLib)?这是截至 2021 年 12 月 6 日的答案。
步骤
我。安装 miniforge
所以你的 Python 是 运行 原生的 arm64,不是通过 Rosseta 翻译的。
- 下载Miniforge3-MacOSX-arm64.sh,然后
- 运行脚本,然后再打开一个shell
$ bash Miniforge3-MacOSX-arm64.sh
- 创建环境(这里我用name
np_veclib
)
$ conda create -n np_veclib python=3.9
$ conda activate np_veclib
二.使用指定为 vecLib
的 BLAS 接口安装 Numpy- 要编译
numpy
,首先需要安装cython
和pybind11
:
$ conda install cython pybind11
- 通过(感谢@Marijn 的 answer)编译
numpy
- 不要使用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。竞争对手:
除了上面那个最优的,我也尝试了其他几种安装方式
- 一个。
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 上不支持。
- D.
np_openblas_source
:首先通过brew install openblas
安装openblas。然后将[openblas]
路径/opt/homebrew/opt/openblas
添加到site.cfg
并从源代码构建 Numpy。 M1
和i9–9880H
在这个 post.- 我的旧
i5-6360U
2 核 MacBook Pro 2016 13 英寸
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):.5f}s')
dario.py
:Dario Radečić 在上面 post 的基准测试脚本。
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 |
+-------+-----------+------------+-------------+-----------+--------------------+----+----------+----------+