- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
这里 Matrix multiplication using hdf5我使用 hdf5 (pytables) 进行大矩阵乘法,但我很惊讶,因为使用 hdf5 它比使用普通 numpy.dot 并在 RAM 中存储矩阵更快,这种行为的原因是什么?
也许python中有一些更快的矩阵乘法函数,因为我仍然使用numpy.dot进行小块矩阵乘法。
这里有一些代码:
假设矩阵可以放入 RAM:在矩阵 10*1000 x 1000 上进行测试。
使用默认的 numpy(我认为没有 BLAS 库)。普通的 numpy 数组在 RAM 中:时间 9.48
如果 A、B 在 RAM 中,C 在磁盘上:时间 1.48
如果 A、B、C 在磁盘上:时间 372.25
如果我使用带有 MKL 的 numpy,结果是:0.15,0.45,43.5。
结果看起来很合理,但我仍然不明白为什么在第一种情况下 block 乘法更快(当我们将 A、B 存储在 RAM 中时)。
n_row=1000
n_col=1000
n_batch=10
def test_plain_numpy():
A=np.random.rand(n_row,n_col)# float by default?
B=np.random.rand(n_col,n_row)
t0= time.time()
res= np.dot(A,B)
print (time.time()-t0)
#A,B in RAM, C on disk
def test_hdf5_ram():
rows = n_row
cols = n_col
batches = n_batch
#using numpy array
A=np.random.rand(n_row,n_col)
B=np.random.rand(n_col,n_row)
#settings for all hdf5 files
atom = tables.Float32Atom() #if store uint8 less memory?
filters = tables.Filters(complevel=9, complib='blosc') # tune parameters
Nchunk = 128 # ?
chunkshape = (Nchunk, Nchunk)
chunk_multiple = 1
block_size = chunk_multiple * Nchunk
#using hdf5
fileName_C = 'CArray_C.h5'
shape = (A.shape[0], B.shape[1])
h5f_C = tables.open_file(fileName_C, 'w')
C = h5f_C.create_carray(h5f_C.root, 'CArray', atom, shape, chunkshape=chunkshape, filters=filters)
sz= block_size
t0= time.time()
for i in range(0, A.shape[0], sz):
for j in range(0, B.shape[1], sz):
for k in range(0, A.shape[1], sz):
C[i:i+sz,j:j+sz] += np.dot(A[i:i+sz,k:k+sz],B[k:k+sz,j:j+sz])
print (time.time()-t0)
h5f_C.close()
def test_hdf5_disk():
rows = n_row
cols = n_col
batches = n_batch
#settings for all hdf5 files
atom = tables.Float32Atom() #if store uint8 less memory?
filters = tables.Filters(complevel=9, complib='blosc') # tune parameters
Nchunk = 128 # ?
chunkshape = (Nchunk, Nchunk)
chunk_multiple = 1
block_size = chunk_multiple * Nchunk
fileName_A = 'carray_A.h5'
shape_A = (n_row*n_batch, n_col) # predefined size
h5f_A = tables.open_file(fileName_A, 'w')
A = h5f_A.create_carray(h5f_A.root, 'CArray', atom, shape_A, chunkshape=chunkshape, filters=filters)
for i in range(batches):
data = np.random.rand(n_row, n_col)
A[i*n_row:(i+1)*n_row]= data[:]
rows = n_col
cols = n_row
batches = n_batch
fileName_B = 'carray_B.h5'
shape_B = (rows, cols*batches) # predefined size
h5f_B = tables.open_file(fileName_B, 'w')
B = h5f_B.create_carray(h5f_B.root, 'CArray', atom, shape_B, chunkshape=chunkshape, filters=filters)
sz= rows/batches
for i in range(batches):
data = np.random.rand(sz, cols*batches)
B[i*sz:(i+1)*sz]= data[:]
fileName_C = 'CArray_C.h5'
shape = (A.shape[0], B.shape[1])
h5f_C = tables.open_file(fileName_C, 'w')
C = h5f_C.create_carray(h5f_C.root, 'CArray', atom, shape, chunkshape=chunkshape, filters=filters)
sz= block_size
t0= time.time()
for i in range(0, A.shape[0], sz):
for j in range(0, B.shape[1], sz):
for k in range(0, A.shape[1], sz):
C[i:i+sz,j:j+sz] += np.dot(A[i:i+sz,k:k+sz],B[k:k+sz,j:j+sz])
print (time.time()-t0)
h5f_A.close()
h5f_B.close()
h5f_C.close()
最佳答案
np.dot
分派(dispatch)到 BLAS当
float32
、float64
、complex32
或 complex64
和否则,它默认使用自己的慢速矩阵乘法例程。
描述了检查您的 BLAS 链接 here .简而言之,检查您的 NumPy 安装中是否有文件 _dotblas.so
或类似文件。如果有,请检查它链接到哪个 BLAS 库;引用 BLAS 很慢,ATLAS 很快,OpenBLAS 和供应商特定版本(如英特尔 MKL)甚至更快。注意多线程 BLAS 实现,因为它们 don't play nicely使用 Python 的 multiprocessing
。
接下来,通过检查数组的 flags
检查数据对齐情况。在 1.7.2 之前的 NumPy 版本中,np.dot
的两个参数都应该是 C 顺序的。在 NumPy >= 1.7.2 中,这不再重要,因为已经引入了 Fortran 数组的特殊情况。
>>> X = np.random.randn(10, 4)
>>> Y = np.random.randn(7, 4).T
>>> X.flags
C_CONTIGUOUS : True
F_CONTIGUOUS : False
OWNDATA : True
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
>>> Y.flags
C_CONTIGUOUS : False
F_CONTIGUOUS : True
OWNDATA : False
WRITEABLE : True
ALIGNED : True
UPDATEIFCOPY : False
如果你的 NumPy 没有与 BLAS 链接,要么(简单)重新安装它,要么(硬)使用 SciPy 中的 BLAS gemm
(广义矩阵乘法)函数:
>>> from scipy.linalg import get_blas_funcs
>>> gemm = get_blas_funcs("gemm", [X, Y])
>>> np.all(gemm(1, X, Y) == np.dot(X, Y))
True
这看起来很简单,但它几乎没有任何错误检查,所以你必须真正知道你在做什么。
关于python - 如何获得比 numpy.dot 更快的代码用于矩阵乘法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19839539/
我正在为我的雇主编写脚本,以从他们自己的站点获取某些数据。出于一长串原因,我需要从网站上获取数据,如图所示。我发现,其中一些数据是通过 js 调用检索的... 回想起来,我应该选择 Mechanize
我正在使用 python 和 cryptography.io 来签署和验证消息。我可以通过以下方式获得签名的 DER 编码字节表示: cryptography_priv_key.sign(messag
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 6年前关闭。 Improve thi
是否可以区分 ECDF?以下面得到的为例。 set.seed(1) a <- sort(rnorm(100)) b <- ecdf(a) plot(b) 我想对 b 求导以获得它的概率密度函数 (PD
我找到了如何从 navigator.mimeTypes 获取 mimetypes: function GetMimeTypes() { var message = ""; var mi
我在表单中使用单选按钮来隐藏/显示联系人表单中的成员 ID 字段。问题是,当 javascript 更改 html 中包含的隐藏 id 字段(该字段设置为“无”值)时,该字段将不再通过 post 可用
我正在做单元测试。我必须测试所有可能的if..else情况。但是在此if语句中: int32_t i32Res = snprintf(buffer, len, "The%d_String_%d", 0
我有一个 Facebook 应用程序,我想从中获取“喜欢”的总数。我想知道这是否可能。 其中 ID 是应用程序的 ID,ACCESS_TOKEN 是我尝试过的应用程序的当前访问 token : gra
如果我有多个计算实例尝试同时获取同一个 blob 的租约,则似乎经常会成功。我的印象是,一旦租约发出(并因此被客户获得),就不可能同时发出另一个租约? 我希望情况确实如此,我一直在 Azure 中使用
这是我的索引 POST /blogs/1 { "name" : "learn java", "popularity" : 100 } POST /blogs/2 { "name" : "l
我正在将 Symfony2 与 FOSUserBundle 一起使用。我需要为用户获得最高角色。 role_hierarchy: ROLE_CONTRIBUTOR: ROLE_USER
我正在向服务器发送基于 REST 的请求。我希望尽快得到答复,并希望了解可以进行的各种优化。 一种方法当然是在线程中并行发送这些请求。还有哪些其他选项可用于优化此功能? 在服务器上,可以添加哪些配置?
这可能是某种重复的问题,但我似乎找不到合适的解决方案。我正在使用 git4idea.history.GitHistoryUtils.history() 获取提交列表。如果 checkout 其中一个较
我正在做一个程序,可以输入每周的工资和那一周的总工作时间。它应该以小时工资率显示答案。但是我无法显示正确的“centavos/2 decimal places”公式并且它不想使用 float % fl
已结束。此问题正在寻求书籍、工具、软件库等的推荐。它不满足Stack Overflow guidelines 。目前不接受答案。 我们不允许提出寻求书籍、工具、软件库等推荐的问题。您可以编辑问题,以便
我已经尝试了 mContext.getMainLooper() 和 Looper.getMainLooper()。两者都返回相同的结果,但我想知道哪种方法正确? 我还从 Android 开发人员链接中
我有一个“affiliates”表,其中包含“user”和“referredBy”列。 给定一个用户,我希望获得该用户推荐的所有“n 级”玩家。对于 n=1,我们只关心您直接推荐的玩家数量: SELE
我在 PostgreSQL 9.5 数据库中有两个表: project - id - name task - id - project_id - name - updated_
请帮助我怎样才能得到我预期的结果,在此先感谢并抱歉我的英语不好。 PHP: $dog = implode(',', $data['dogbreed']); $query .= "AND `do
我有 let impulse = CGVectorMake(CGFloat(Constants.impulse), 0) 如何在不创建另一个 CGVector 的情况下得到它的负值? 我正在考虑在 C
我是一名优秀的程序员,十分优秀!