Numpy 排序比 Matlab 排序慢得多
Posted
技术标签:
【中文标题】Numpy 排序比 Matlab 排序慢得多【英文标题】:Numpy sort much slower than Matlab sort 【发布时间】:2022-01-16 19:39:03 【问题描述】:我正在将一些代码从 Matlab 转换为 Python。有时我对性能损失感到非常惊讶。这是一个排序数组的例子,让我抓狂。
Matlab:
a=rand(50000,1000);tic;b=sort(a,1);toc
经过的时间是 0.624460 秒。
Python:
import numpy as np
import time
a=np.random.rand(50000,1000);
t0=time.time();b=np.sort(a,axis=0);print(time.time()-t0)
4.192200422286987
有人能解释一下为什么这种基本操作的性能有 7 倍吗?我看到这种排序在 Python 上不是多线程的,这应该是我的 20 核机器上的主要原因。
现在我尝试了(跟随this link):
sudo apt update
sudo apt install intel-mkl-full
conda install -c intel numpy
但这并没有改变行为。在终端中我也输入了
export MKL_NUM_THREADS=20
export NUMEXPR_NUM_THREADS=20
export OMP_NUM_THREADS=20
在 Python 中,以下命令
np.show_config()
返回
blas_mkl_info:
libraries = ['mkl_rt', 'pthread']
library_dirs = ['/home/pierre/anaconda3/lib']
define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
include_dirs = ['/home/pierre/anaconda3/include']
blas_opt_info:
libraries = ['mkl_rt', 'pthread']
library_dirs = ['/home/pierre/anaconda3/lib']
define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
include_dirs = ['/home/pierre/anaconda3/include']
lapack_mkl_info:
libraries = ['mkl_rt', 'pthread']
library_dirs = ['/home/pierre/anaconda3/lib']
define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
include_dirs = ['/home/pierre/anaconda3/include']
lapack_opt_info:
libraries = ['mkl_rt', 'pthread']
library_dirs = ['/home/pierre/anaconda3/lib']
define_macros = [('SCIPY_MKL_H', None), ('HAVE_CBLAS', None)]
include_dirs = ['/home/pierre/anaconda3/include']
这似乎表明我真的在使用 MKL。有没有办法让 np.sort 为数组并行工作?
【问题讨论】:
这里需要注意一件重要的事情:numpy 使用 row-major 顺序,而 matlab 使用 column-major 顺序将数据存储在内存中 (@987654322 @)。您正在对垂直轴进行排序,这自然有利于 matlab,因为所有数字都是连续存储的。我执行了两次python代码,一次是axis=0,耗时4.24s,一次是axis=1,耗时2.33s。 非常感谢您的评论。这是一个重要的评论,但这似乎并不能解释这种行为。我尝试使用方形数组并沿两个轴排序,但差异仍然大致相同。并行化是通过监控核心活动来实现的。 对每个使用完全相同的数据集也会更公平,您似乎正在生成在每种情况下都不同的随机数据集。 @Wolfie Fair 点,但由于 P. Weiss 基本上将 50k 均匀随机数排序一千次,我认为这应该“平均掉”任何不利的随机效应。 鉴于 Matlab 的sort
是一个已编译并因此被混淆的函数,MathWorks 工程团队之外的任何人都无法回答这个问题,因此我认为除了以基于意见的方式。
【参考方案1】:
花了几个小时并与同事核对后,现在解决方案很明确:
np.sort 不是多线程的,没有办法加速它。
只需查看来源即可:
https://github.com/numpy/numpy/tree/main/numpy/core/src/npysort
对于如此重要的功能,我感到很惊讶。像 99.9% 的使用 np 排序的代码可以加速。我想我会用 Cython 实现自己的排序功能。
最好的,
皮埃尔
【讨论】:
您可能想查看parallel_sort
python 包:pypi.org/project/parallel-sort
再次感谢您指出这个好信息!我已经尝试过了,但这仅适用于一维数组。我在 numpy github github.com/numpy/numpy/issues/20575 中打开了一个问题,看看是否有人有动力改进它:)。
请允许我补充一句:并行化代码时,您可以区分任务并行和数据并行。任务并行性是将矩阵的单个列(或行)分配给一个工作人员,每个工作人员都会对其进行排序。数据并行意味着您将单行(或列)分配给许多工作人员,他们将使用分而治之的方法对其进行排序。任务并行性适用于parallel_sort
。性能显然取决于您的用例。
感谢您提供此信息。 Matlab 似乎在两个方向上并行化。在其一侧 np.sort 没有方向并行化。我可能可以联合使用 numba 和 parallel_sort ,但这有点难看。现在,我正在使用 cupy.sort,它工作得非常好。唯一的问题是,对于我的问题,我需要在每次迭代时从 CPU 切换到 GPU,从而在数据传输上浪费大量时间。以上是关于Numpy 排序比 Matlab 排序慢得多的主要内容,如果未能解决你的问题,请参考以下文章
为啥在迭代 NumPy 数组时 Cython 比 Numba 慢得多?
为啥 TensorFlow matmul() 比 NumPy multiply() 慢得多?