Python 加速numpy.dot

Python 加速numpy.dot,python,performance,numpy,dot-product,Python,Performance,Numpy,Dot Product,我有一个numpy脚本,它将大约50%的运行时间花费在以下代码中: s=numpy.dot(v1,v1) 在哪里 v1=v[1:][/code> 而v是存储在连续内存中的float64的4000个元素1Dndarray(v.strips是(8,)) 有没有加快这一进程的建议 编辑这是在英特尔硬件上。这是我的numpy.show\u config()的输出: 我唯一能想到的加速这一进程的方法是确保您的NumPy安装是根据优化的BLAS库(如ATLAS)编译的numpy.dot() 正如斯文所说,d

我有一个
numpy
脚本,它将大约50%的运行时间花费在以下代码中:

s=numpy.dot(v1,v1)

在哪里

v1=v[1:][/code>

v
是存储在连续内存中的
float64
的4000个元素1D
ndarray
v.strips
(8,)

有没有加快这一进程的建议

编辑这是在英特尔硬件上。这是我的
numpy.show\u config()
的输出:


我唯一能想到的加速这一进程的方法是确保您的NumPy安装是根据优化的BLAS库(如ATLAS)编译的
numpy.dot()

正如斯文所说,dot产品依赖于BLAS操作。这些操作需要以连续的C顺序存储数组。若传递给dot的两个数组都是C_连续的,那个么您应该会看到更好的性能

当然,如果传递给dot的两个数组确实是1D(8),那么您应该看到C_continuous和F_continuous标志都设置为True;但是如果它们是(1,8),那么您可以看到混合顺序

>>> w = NP.random.randint(0, 10, 100).reshape(100, 1)
>>> w.flags
   C_CONTIGUOUS : True
   F_CONTIGUOUS : False
   OWNDATA : False
   WRITEABLE : True
   ALIGNED : True
   UPDATEIFCOPY : False

另一种选择是:使用BLAS的_GEMM,它通过模块scipy.linalg.fblas暴露出来。(两个数组A和B显然是按Fortran顺序排列的,因为使用了fblas。)


您的阵列不是很大,所以ATLAS可能做的不多。以下Fortran程序的计时是什么?假设ATLAS做的不多,这应该会让您了解如果没有任何python开销,dot()的速度有多快。使用gfortran-O3,我的速度为5+/-0.5 us

    program test

    real*8 :: x(4000), start, finish, s
    integer :: i, j
    integer,parameter :: jmax = 100000

    x(:) = 4.65
    s = 0.
    call cpu_time(start)
    do j=1,jmax
        s = s + dot_product(x, x)
    enddo
    call cpu_time(finish)
    print *, (finish-start)/jmax * 1.e6, s

    end program test

如果编译正确,numpy.dot将使用多线程。请确保它与顶部匹配。我知道有些情况下,人们在numpy w/atlas中没有使用多线程。此外,值得尝试使用针对英特尔mkl库编译的numpy版本。它们包括blas例程,在英特尔硬件上应该比atlas更快。您可以试试Enthough的python发行版。包含所有这些内容,对于拥有edu电子邮件帐户的人是免费的。

好建议(+1)。我已经用我的
numpy
config更新了这个问题。它似乎是根据ATLAS构建的。@aix:您的配置在我看来很好(尽管我不太确定如何解释它:),仔细想想,当您的代码花费大部分时间乘以中等大小的向量时,您可能在内存带宽的限制下运行,因此,任何优化都只会使处理器等待新数据的时间更长。要给出计时结果吗?FWIW,在我的普通机器中,具有形状随机向量(4000)的点(,)将花费大约6us。Thanks@eat:在我的机器上进行相同的操作需要5us以下的时间。虽然我做了很多这样的事情,但是它们加起来了。那么,单点似乎是合理有效的。但是,如果您想向我们展示更多的代码,可能会有人发现如何优化计算。Thanks@tillsten:是的,谢谢,速度慢了好几倍(可能是因为它使用了一个临时数组。)@OferHelman:这是很久以前的事了(3.5年),很抱歉,我不太记得了-(然而,我确实记得,我最终使用了英特尔MKL。我不确定它是否对这一特定问题起到了任何作用。只是要明确一点,输入数组是1D(输出是标量)。您能否提供一个链接,我们可以从中获得针对英特尔MKL库编译的numpy版本?anaconda通常会这样做
from scipy.linalg import fblas as FB
X = FB.dgemm(alpha=1., a=A, b=B, trans_b=True)
    program test

    real*8 :: x(4000), start, finish, s
    integer :: i, j
    integer,parameter :: jmax = 100000

    x(:) = 4.65
    s = 0.
    call cpu_time(start)
    do j=1,jmax
        s = s + dot_product(x, x)
    enddo
    call cpu_time(finish)
    print *, (finish-start)/jmax * 1.e6, s

    end program test