- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在尝试评估与 C++ 相比,Python 的性能有多好。
这是我的 Python 代码:
a=np.random.rand(1000,1000) #type is automaically float64
b=np.random.rand(1000,1000)
c=np.empty((1000,1000),dtype='float64')
%timeit a.dot(b,out=c)
#15.5 ms ± 560 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
这是我在发布机制中使用 Xcode 编译的 C++ 代码:
#include <iostream>
#include <Dense>
#include <time.h>
using namespace Eigen;
using namespace std;
int main(int argc, const char * argv[]) {
//RNG generator
unsigned int seed = clock();
srand(seed);
int Msize=1000, Nloops=10;
MatrixXd m1=MatrixXd::Random(Msize,Msize);
MatrixXd m2=MatrixXd::Random(Msize,Msize);
MatrixXd m3=MatrixXd::Random(Msize,Msize);
cout << "Starting matrix multiplication test with " << Msize <<
"matrices" << endl;
clock_t start=clock();
for (int i=0; i<Nloops; i++)
m3=m1*m2;
start = clock() - start;
cout << "time elapsed for 1 multiplication: " << start / ((double)
CLOCKS_PER_SEC * (double) Nloops) << " seconds" <<endl;
return 0;
结果是:
Starting matrix multiplication test with 1000matrices
time elapsed for 1 multiplication: 0.148856 seconds
Program ended with exit code: 0
这意味着 C++ 程序要慢 10 倍。
或者,我尝试在 MAC 终端中编译 cpp 代码:
g++ -std=c++11 -I/usr/local/Cellar/eigen/3.3.5/include/eigen3/eigen main.cpp -o my_exec -O3
./my_exec
Starting matrix multiplication test with 1000matrices
time elapsed for 1 multiplication: 0.150432 seconds
我知道非常相似question ,但是,问题似乎出在矩阵定义中。在我的示例中,我使用默认特征函数从均匀分布创建矩阵。
谢谢,米哈伊尔
编辑:我发现,虽然 numpy 使用多线程,但 Eigen 默认不使用多线程(通过 Eigen::nbThreads()
函数检查)。正如建议的那样,我使用了 -march=native
选项,该选项将计算时间减少了 3 倍。考虑到我的 MAC 上有 8 个可用线程,我相信多线程 numpy 的运行速度快了 3 倍。
最佳答案
经过漫长而痛苦的安装和编译,我已经在 Matlab、C++ 和 Python 中执行了基准测试。
我的电脑:MAC OS High Sierra 10.13.6,Intel(R) Core(TM) i7-7920HQ CPU @ 3.10GHz(4 核,8 线程)。我有 Radeon Pro 560 4096 MB,因此这些测试中没有涉及 GPU(而且我从未配置过 openCL,也没有在 np.show_config()
中看到它)。
软件:Matlab 2018a、Python 3.6、C++ 编译器:Apple LLVM 版本 9.1.0 (clang-902.0.39.2)、g++-8 (Homebrew GCC 8.2.0) 8.2.0
1) Matlab 性能:时间 = (14.3 +- 0.7 ) ms,执行 10 次运行
a=rand(1000,1000);
b=rand(1000,1000);
c=rand(1000,1000);
tic
for i=1:100
c=a*b;
end
toc/100
2) Python 性能(%timeit a.dot(b,out=c)
):15.5 +- 0.8
我还为 python 安装了 mkl 库。将 numpy 链接到 mkl: 14.4+-0.7 - 它有帮助,但非常小。
3) C++ 性能。应用了对原始(参见问题)代码的以下更改:
noalias
函数可避免创建不必要的时间矩阵。
时间是用 c++11 chorno
库测量的
这里我使用了一堆不同的选项和两个不同的编译器:
3.1 clang++ -std=c++11 -I/usr/local/Cellar/eigen/3.3.5/include/eigen3/eigen main.cpp -O3
执行时间 ~ 146 毫秒
3.2 Added -march=native option:
执行时间~ 46 +-2 毫秒
3.3 Changed compiler to GNU g++ (in my mac it is called gpp by custom-defined alias):
gpp -std=c++11 -I/usr/local/Cellar/eigen/3.3.5/include/eigen3/eigen main.cpp -O3
执行时间 222 毫秒
3.4 Added - march=native option:
执行时间 ~ 45.5 +- 1 毫秒
到这里我才明白Eigen并没有使用多线程。我安装了 openmp 并添加了 -fopenmp 标志。请注意,在最新的 clang 版本上,openmp 不起作用,因此我必须从现在开始使用 g++。我还通过监视 Eigen::nbthreads()
的值和使用 MAC OS 事件监视器来确保我实际上使用了所有可用线程。
3.5 gpp -std=c++11 -I/usr/local/Cellar/eigen/3.3.5/include/eigen3/eigen main.cpp -O3 -march=native -fopenmp
执行时间:16.5 +- 0.7 毫秒
3.6 最后,我安装了 Intel mkl 库。在代码中使用它们非常容易:我刚刚添加了 #define EIGEN_USE_MKL_ALL
宏,仅此而已。虽然很难链接所有库:
gpp -std=c++11 -DMKL_LP64 -m64 -I${MKLROOT}/include -I/usr/local/Cellar/eigen/3.3.5/include/eigen3/eigen -L${MKLROOT}/lib -Wl,-rpath,${MKLROOT}/lib -lmkl_intel_ilp64 -lmkl_intel_thread -lmkl_core -liomp5 -lpthread -lm -ldl main.cpp -o my_exec_intel -O3 -fopenmp -march=native
执行时间:14.33 +-0.26 毫秒。 (编者注:这个答案最初声称使用了 -DMKL_ILP64
也就是 not supported 。也许它曾经是,或者碰巧有效。)
结论:
Python/Matlab 中的矩阵乘法得到了高度优化。不可能(或者至少很难)(在 CPU 上)做得更好。
CPP 代码(至少在 MAC 平台上)只有在完全优化的情况下才能达到类似的性能,其中包括全套优化选项和英特尔 mkl 库。我本可以安装支持 openmp 的旧 clang 编译器,但由于单线程性能相似(~46 毫秒),看来这无济于事。
最好用原生 Intel 编译器 icc
试试看。不幸的是,这是专有软件,与英特尔 mkl 库不同。
感谢有益的讨论,
米哈伊尔
编辑:为了进行比较,我还使用 cublasDgemm 函数对我的 GTX 980 GPU 进行了基准测试。计算时间 = 12.6 毫秒,与其他 results. 兼容CUDA 几乎与 CPU 一样好的原因如下:我的 GPU 没有针对 double 优化。使用 float ,GPU 时间 =0.43 毫秒,而 Matlab 的是 7.2 毫秒
编辑 2:为了获得显着的 GPU 加速,我需要对尺寸更大的矩阵进行基准测试,例如10k x 10k
编辑 3:将接口(interface)从 MKL_ILP64 更改为 MKL_LP64,因为 ILP64 是 not supported.
关于python - 基准矩阵乘法性能 : C++ (eigen) is much slower than Python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51656818/
我正在处理一组标记为 160 个组的 173k 点。我想通过合并最接近的(到 9 或 10 个组)来减少组/集群的数量。我搜索过 sklearn 或类似的库,但没有成功。 我猜它只是通过 knn 聚类
我有一个扁平数字列表,这些数字逻辑上以 3 为一组,其中每个三元组是 (number, __ignored, flag[0 or 1]),例如: [7,56,1, 8,0,0, 2,0,0, 6,1,
我正在使用 pipenv 来管理我的包。我想编写一个 python 脚本来调用另一个使用不同虚拟环境(VE)的 python 脚本。 如何运行使用 VE1 的 python 脚本 1 并调用另一个 p
假设我有一个文件 script.py 位于 path = "foo/bar/script.py"。我正在寻找一种在 Python 中通过函数 execute_script() 从我的主要 Python
这听起来像是谜语或笑话,但实际上我还没有找到这个问题的答案。 问题到底是什么? 我想运行 2 个脚本。在第一个脚本中,我调用另一个脚本,但我希望它们继续并行,而不是在两个单独的线程中。主要是我不希望第
我有一个带有 python 2.5.5 的软件。我想发送一个命令,该命令将在 python 2.7.5 中启动一个脚本,然后继续执行该脚本。 我试过用 #!python2.7.5 和http://re
我在 python 命令行(使用 python 2.7)中,并尝试运行 Python 脚本。我的操作系统是 Windows 7。我已将我的目录设置为包含我所有脚本的文件夹,使用: os.chdir("
剧透:部分解决(见最后)。 以下是使用 Python 嵌入的代码示例: #include int main(int argc, char** argv) { Py_SetPythonHome
假设我有以下列表,对应于及时的股票价格: prices = [1, 3, 7, 10, 9, 8, 5, 3, 6, 8, 12, 9, 6, 10, 13, 8, 4, 11] 我想确定以下总体上最
所以我试图在选择某个单选按钮时更改此框架的背景。 我的框架位于一个类中,并且单选按钮的功能位于该类之外。 (这样我就可以在所有其他框架上调用它们。) 问题是每当我选择单选按钮时都会出现以下错误: co
我正在尝试将字符串与 python 中的正则表达式进行比较,如下所示, #!/usr/bin/env python3 import re str1 = "Expecting property name
考虑以下原型(prototype) Boost.Python 模块,该模块从单独的 C++ 头文件中引入类“D”。 /* file: a/b.cpp */ BOOST_PYTHON_MODULE(c)
如何编写一个程序来“识别函数调用的行号?” python 检查模块提供了定位行号的选项,但是, def di(): return inspect.currentframe().f_back.f_l
我已经使用 macports 安装了 Python 2.7,并且由于我的 $PATH 变量,这就是我输入 $ python 时得到的变量。然而,virtualenv 默认使用 Python 2.6,除
我只想问如何加快 python 上的 re.search 速度。 我有一个很长的字符串行,长度为 176861(即带有一些符号的字母数字字符),我使用此函数测试了该行以进行研究: def getExe
list1= [u'%app%%General%%Council%', u'%people%', u'%people%%Regional%%Council%%Mandate%', u'%ppp%%Ge
这个问题在这里已经有了答案: Is it Pythonic to use list comprehensions for just side effects? (7 个答案) 关闭 4 个月前。 告
我想用 Python 将两个列表组合成一个列表,方法如下: a = [1,1,1,2,2,2,3,3,3,3] b= ["Sun", "is", "bright", "June","and" ,"Ju
我正在运行带有最新 Boost 发行版 (1.55.0) 的 Mac OS X 10.8.4 (Darwin 12.4.0)。我正在按照说明 here构建包含在我的发行版中的教程 Boost-Pyth
学习 Python,我正在尝试制作一个没有任何第 3 方库的网络抓取工具,这样过程对我来说并没有简化,而且我知道我在做什么。我浏览了一些在线资源,但所有这些都让我对某些事情感到困惑。 html 看起来
我是一名优秀的程序员,十分优秀!