架构如何影响numpy阵列的运行性能?

时间:2015-07-02 14:36:08

标签: python arrays numpy intel-mkl numpy-einsum

我的Ubuntu 14.04带有安装了英特尔数学内核库(MKL)的“Anaconda”Python发行版。我的处理器是Intel Xeon,具有8个内核,没有超线程(因此只有8个线程)。

对于我来说,numpy tensordot的大型数组始终优于einsum。但是,其他人在{2}之间找到Universal Dependencies site,甚至very little difference

对于使用快速库构建numpy发行版的人,我想知道为什么会发生这种情况。 MKL在非英特尔处理器上的运行速度是否较慢?或者einsum在具有更好线程功能的更现代的英特尔处理器上运行得更快?

以下是比较我的机器性能的快速示例代码:

In  [27]: a = rand(100,1000,2000)

In  [28]: b = rand(50,1000,2000)

In  [29]: time cten = tensordot(a, b, axes=[(1,2),(1,2)])
CPU times: user 7.85 s, sys: 29.4 ms, total: 7.88 s
Wall time: 1.08 s

In  [30]: "FLOPS TENSORDOT: {}.".format(cten.size * 1000 * 2000 / 1.08)
Out [30]: 'FLOPS TENSORDOT: 9259259259.26.'

In  [31]: time cein = einsum('ijk,ljk->il', a, b)
CPU times: user 42.3 s, sys: 7.58 ms, total: 42.3 s
Wall time: 42.4 s

In  [32]: "FLOPS EINSUM: {}.".format(cein.size * 1000 * 2000 / 42.4)
Out [32]: 'FLOPS EINSUM: 235849056.604.'

使用tensordot的张量运算始终在5-20 GFLOP范围内运行。我只用einsum得到0.2 GFLOPS。

1 个答案:

答案 0 :(得分:2)

基本上你要比较两个非常不同的东西:

  • np.einsum使用C中的for循环计算张量积。它有一些SIMD优化,但不是多线程的,不使用MLK。

  • np.tensordot,包括重塑/广播输入数组,然后调用BLAS(MKL,OpenBLAS等)进行矩阵乘法。重塑/广播阶段会产生一些额外的开销,但matrix multiplication is extremely well optimized有SIMD,有些汇编和多线程。

因此,tensordot will be generally faster than einsum在单核执行中,除非使用小数组大小(然后重塑/广播开销变得不可忽略)。这更为真实,因为前一种方法是多线程的,而后一种方法则不是。

总之,你得到的结果是完全正常的,可能一般都是正确的(英特尔/非英特尔CPU,现代与否,多核与否,使用MKL或OpenBLAS等)。