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 排序慢得多的主要内容,如果未能解决你的问题,请参考以下文章

pandas 比 numpy 慢得多?

为啥在迭代 NumPy 数组时 Cython 比 Numba 慢得多?

为啥 TensorFlow matmul() 比 NumPy multiply() 慢得多?

为啥 MEX 代码比 matlab 代码慢得多?

numpy.array和python自带的list比排序,哪个快?

arrayfun 可能比 matlab 中的显式循环慢得多。为啥?