UPDATE
不幸的是,由于我的疏忽,我有一个旧版本的MKL(11.1)链接到numpy.较新版本的MKL(11.3.1)在C中和从python调用时具有相同的性能.
什么是模糊的东西,即使将编译的共享库与新的MKL明确地链接,并将LD_*变量指向它们,然后在python中执行import numpy,以某种方式使python调用旧的MKL库.只有在python lib文件夹中替换所有libmkl _*.所以使用更新的MKL我能够匹配python和C调用中的性能.
背景/图书馆信息.
矩阵乘法是通过numpy.dot函数通过sgemm(单精度)和dgemm(双精度)Intel的MKL库调用完成的.可以使用例如oprof来验证库函数的实际调用.
在这里使用2x18核心CPU E5-2699 v3,因此共有36个物理核心.KMP_AFFINITY =散射.在linux上运行.
TL; DR
1)为什么numpy.dot,即使它调用相同的MKL库函数,与C编译代码相比,最好慢两倍?
2)为什么通过numpy.dot随着内核数量的增加而性能下降,而在C代码中没有观察到相同的效果(调用相同的库函数).
问题
我观察到在numpy.dot中进行单/双精度浮点矩阵乘法,以及直接从编译的C 共享库调用cblas_sgemm/dgemm,与从纯C内部调用相同的MKL cblas_sgemm/dgemm函数相比,性能明显更差码.
import numpy as np
import mkl
n = 10000
A = np.random.randn(n,n).astype('float32')
B = np.random.randn(n,n).astype('float32')
C = np.zeros((n,n)).astype('float32')
mkl.set_num_threads(3); %time np.dot(A, B, out=C)
11.5 seconds
mkl.set_num_threads(6); %time np.dot(A, B, out=C)
6 seconds
mkl.set_num_threads(12); %time np.dot(A, B, out=C)
3 seconds
mkl.set_num_threads(18); %time np.dot(A, B, out=C)
2.4 seconds
mkl.set_num_threads(24); %time np.dot(A, B, out=C)
3.6 seconds
mkl.set_num_threads(30); %time np.dot(A, B, out=C)
5 …Run Code Online (Sandbox Code Playgroud) 所有代码都在linux上的同一台机器上运行.
在python中:
import numpy as np
drr = abs(np.random.randn(100000,50))
%timeit np.log2(drr)
Run Code Online (Sandbox Code Playgroud)
10个循环,最佳3:每循环77.9 ms
在C++中(使用g ++ -o log ./log.cpp -std = c ++ 11 -O3编译):
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>
#include <ctime>
int main()
{
std::mt19937 e2(0);
std::normal_distribution<> dist(0, 1);
const int n_seq = 100000;
const int l_seq = 50;
static double x[n_seq][l_seq];
for (int n = 0;n < n_seq; ++n) {
for (int k = 0; k < l_seq; ++k) {
x[n][k] = abs(dist(e2));
if(x[n][k] …Run Code Online (Sandbox Code Playgroud) 我想从MySQL表中读取一些数字(double,即float64)数据.数据大小约为200k行.
MATLAB参考:
tic;
feature accel off;
conn = database(...);
c=fetch(exec(conn,'select x,y from TABLENAME'));
cell2mat(c.data);
toc
Run Code Online (Sandbox Code Playgroud)
经过的时间约为1秒.
在python中做同样的事情,使用这里找到的几个例子(我已经尝试了所有这些,即使用pandas read_frame,frame_query和__processCursor函数): 如何将SQL查询结果转换为PANDAS数据结构?
参考python代码:
import pyodbc
import pandas.io.sql as psql
import pandas
connection_info = "DRIVER={MySQL ODBC 3.51 \
Driver};SERVER=;DATABASE=;USER=;PASSWORD=;OPTION=3;"
cnxn = pyodbc.connect(connection_info)
cursor = cnxn.cursor()
sql = "select x,y from TABLENAME"
#cursor.execute(sql)
#dataframe = __processCursor(cursor, dataframe=True)
#df = psql.frame_query(sql, cnxn, coerce_float=False)
df = psql.read_frame(sql, cnxn)
cnxn.close()
Run Code Online (Sandbox Code Playgroud)
大约需要6秒钟.Profiler说所有花费的时间都在read_frame中.我想知道是否有人能给我一些提示如何加速至少匹配MATLAB代码.如果在python中完全可以的话.
编辑:
瓶颈似乎在pyodbc库中的cursor.execute(在pymysql库中)或cursor.fetchall()内.最慢的部分是按元素(逐行,逐列)读取返回的MySQL数据元素,并将其转换为先前由同一个库推断的数据类型.
到目前为止,我通过这个非常脏的解决方案设法加快了接近MATLAB的速度:
import pymysql
import numpy
conn = pymysql.connect(host='', port=, user='', passwd='', db='')
cursor = conn.cursor() …Run Code Online (Sandbox Code Playgroud)