我一直在尝试优化我的代码一段时间,并且只是意识到每当我尝试将numpy.dot
与3维或更多维数组一起使用时,会有巨大的性能损失。
例如,这段代码:
def ti():
r = random.rand(8,256,32**2)
p = random.rand(32**2,256)
o = empty((8,256,256))
for k in xrange(100):
dot(r,p,o)
比以下转换慢50倍(在8核macbook pro上):
def ti2():
r = random.rand(8*256,32**2)
p = random.rand(32**2,256)
o = empty((8*256,256))
for k in xrange(100):
dot(r,p,o)
事实证明,第一个代码块没有使用多个内核,这让我想知道它是否正在使用MKL。
有没有办法强制第一个代码块是多线程的并使用MKL而不将其明确地转换为第二个代码块?实际上,我正在使用的数组是4d和5d,我想避免折叠所有的开始维度(我还在数组上执行其他操作,比如在原始4d数组的第二维上取总和如果我将整个数组只分成2个维度,这将变得更加复杂。或者,为了使代码的其余部分可读,通过将数组从4d重新塑造为2d,然后在该步骤之后返回到4d,我将遭受多大的性能损失?或者是否有更有效的方法在两个形状之间转换数据?
更新: 我还尝试使用简单的嵌套for循环迭代第一维,它似乎工作得相对较好,但我是cython的新手,但还没能将它转换为cython。专门的cython功能会增加很多性能吗?
答案 0 :(得分:1)
没有内置的方式。在numpy bug跟踪器上有一个open issue,在邮件列表上有一个discussion。这两个都是相当陈旧的,所以看起来这几年没有取得进展。
我确实发现this blog post链接到一个名为fastdot
的小型图书馆,声称可以更快地完成高维网格产品,但我还没有亲自使用它,所以我可以&#39 ; t确定它有多好(或者是否有效)。
答案 1 :(得分:0)
您可以尝试np.tensordot
,因为它会在引擎盖下进行重塑和2D点。
o = np.tensordot(r, p, [[-1], [-2]])
至于性能损失,似乎可以在不特定情况下进行重新整形(r
和p
都是C连续的)并且在这种情况下应该几乎没有影响在表现上。遗憾的是它不支持输出参数,但如果你真的需要它,你可以修改source code。