本系列的前两篇文章介绍了使用C++代码对python的数值计算进行加速的基本介绍,以及在第二篇中介绍了比较强大的intel编译器,可以使得计算速度有近百倍的提升。
本篇文章介绍可以使得速度再次提升的方法,而且仅需要在编译过程中添加几个参数就可以做到,在之后做一下vs编译器和intel编译器运行速度上的对比。
以下举的运算例子还是上一篇文章提到的,对因子值的z-score行业中性的计算过程。
在calc.cpp中包含两个函数一个是testfunc1,该函数就是之前一篇文章中写的行业中性化的代码,另一个函数是testfunc2,该函数和testfunc1的差别仅仅是在for循环外面加上了omp parallel for,也就是用了openmp的并行计算技术,其他代码和testfunc1完全一致。
Vs编译器的优化参数,在原来cl编译命令的基础上加上,/Ox、/Ot、/GL、/cgthreadh8、/Qpar这几个参数,可能实际起到代码优化作用的可能就只有/Ox或者/Ot,本人还是将其他的几个参数也加上编译,也不是太费力的事情。
编译的代码变成如下样子:
cl calc.cpp /Ox /Ot /GL /cgthreads8 /openmp /Qpar /I "路径1" /I "路径2" /LD /Fe:calc.pyd /link/LIBPATH:"路径3"
intel编译器的优化参数,在原来icl编译命令的基础上需要加上,/Ox 、/Ot、 /Qparallel,从而编译代码变成如下样子:
icl calc.cpp /Ox /Ot /Qipo16 /Qopenmp /Qparallel /I "路径1" /I "路径2" /LD /Fe:calc.pyd /link "路径3\python35.lib"
接下来针对之前的cpp文件使用vs编译器和intel编译器分别用三组参数进行编译,来感受下计算速度的差别。
以下为使用不同编译器以及不同的参数得到的不同的pyd文件。
接下来在python中感受下六个库文件对函数testfunc1和testfunc2的执行速度。对每个函数分别运行5次(主要有的函数太慢了,循环次数太多需要很多时间)。
得到如下的运行平均时间和运行时间标准差。
根据上述表格可以得到如下结论:
- 在vs编译器下,虽然代码中使用了openmp的代码,在编译的时候不加上openmp的参数,并不会起到并行的效果。
- 在vs编译器下,使用openmp的运行时长是不使用openmp的1/3。这个提速应该和电脑的cpu核的个数有关。
- 在vs编译器下,将所有编译优化参数加上之后,运行速度和intel编译器同一量级,同时代码使用openmp写法可以比不使用再快一倍。
- 在intel编译器下,仅使用openmp的参数就可以达到比较快的运行速度。
- 在intel编译器下,当编译的时候开了所有的优化参数,代码使用openmp写法之后,运行时长可以变成不使用openmp写法的1/3。
- 总体来看,运行速度以及运行的稳定性都是intel编译器更加优秀。
- 当vs编译器使用所有优化参数之后,运行速度还是可以和intel编译器一拼的。
对于使用了所有参数的vs编译器和intel编译器的运行30次的时间对比如下:
通过上图可以看到,使用了所有优化参数的时候,vs编译器和intel编译器性能几乎差不多。
所以,对于不想再安装多一个intel编译器的读者来说,使用vs编译器,并加上所有优化参数进行编译,速度也是可以提高到最快的程度。对于速度和稳定性有更高追求的读者,可以尝试使用intel编译器,并加上所有的优化参数。
当然,代码最好写成能用openmp进行并行计算的样子。
获得【源码】关注【量化杂货铺】,回复【加速三】即可获得。