为啥 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 进程的KindApple)。 Anaconda。然后通过Rosseta运行python。 (从活动监视器检查,python 进程的KindIntel)。

2。由

安装的 Numpy conda 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,首先需要安装cythonpybind11
$ 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 中。注意,mklblis 在 arm64 上不受支持。

D. np_openblas_source:首先通过brew install openblas 安装openblas。然后将 [openblas] 路径 /opt/homebrew/opt/openblas 添加到 site.cfg 并从源代码构建 Numpy。 M1i9–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_defaultnp_openblasnp_netlib。但是每个都产生非常相似的结果。并进一步查看numpy.show_config() 使用了哪个 BLAS 接口——每个都完全相同——只有libraries = ['cblas', 'blas', 'cblas', 'blas']blas_info 中,没有openblasnetlib——这意味着他们三个实际上安装了相同的numpy。你能解释一下原因吗? 我问了一个朋友,他用的是 M1,不是 M1 Pro 或 Max。他使用与我完全相同的程序来安装 python(通过 miniforge,然后是 conda install numpy)。但是他在他的 numpy 中得到了openblas,而我没有。 在使用conda安装相应的numpy之前,是否需要自己安装openblas和netlib? @graphitump BLAS 库将全部显示为与 numpy.show_config() 相同,因为它们(libblaslibcblasliblapack 等)使用相同的名称并具有相同的 API,但链接到不同的库(openblasmkl 等)。您必须检查conda listbuilds,其中包含openblasnetlib 等字符串。 @graphitump 库应该通过 Conda 安装,如答案中所示。

以上是关于为啥 M1 Max 上的原生 Python 比旧 Intel i5 上的 Python 慢得多?的主要内容,如果未能解决你的问题,请参考以下文章

PHP - 为啥新的 SQLSRV 驱动程序比旧的 mssql 驱动程序慢?

「地表最强」苹果M1 Max跌下神坛!

安装 mongodb 将 amazon EC2 m1.large 实例升级到 m3.large

为啥 Android 原生 HTML5 日期选择器上的 Chrome 变得非常慢?

Photoshop 2021 M1原生版没有扩展面板怎么办,ps 2021 m1版无法使用旧版插件

苹果最强芯片M1 Ultra亮相!两个M1 Max胶水拼接,性能爆表