【发布时间】: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 工程团队之外的任何人都无法回答这个问题,因此我认为除了以基于意见的方式。
标签: python numpy matlab openmp