Ускорение numpy.dot - PullRequest
       16

Ускорение numpy.dot

10 голосов
/ 13 мая 2011

У меня есть скрипт numpy, который тратит около 50% времени выполнения в следующем коде:

s = numpy.dot(v1, v1)

где

v1 = v[1:]

и v - это 4000-элементный 1D ndarray из float64, хранящийся в непрерывной памяти (v.strides - (8,)).

Есть предложения по ускорению этого процесса?

edit Это на аппаратном обеспечении Intel. Вот вывод моей numpy.show_config():

atlas_threads_info:
    libraries = ['lapack', 'ptf77blas', 'ptcblas', 'atlas']
    library_dirs = ['/usr/local/atlas-3.9.16/lib']
    language = f77
    include_dirs = ['/usr/local/atlas-3.9.16/include']

blas_opt_info:
    libraries = ['ptf77blas', 'ptcblas', 'atlas']
    library_dirs = ['/usr/local/atlas-3.9.16/lib']
    define_macros = [('ATLAS_INFO', '"\\"3.9.16\\""')]
    language = c
    include_dirs = ['/usr/local/atlas-3.9.16/include']

atlas_blas_threads_info:
    libraries = ['ptf77blas', 'ptcblas', 'atlas']
    library_dirs = ['/usr/local/atlas-3.9.16/lib']
    language = c
    include_dirs = ['/usr/local/atlas-3.9.16/include']

lapack_opt_info:
    libraries = ['lapack', 'ptf77blas', 'ptcblas', 'atlas']
    library_dirs = ['/usr/local/atlas-3.9.16/lib']
    define_macros = [('ATLAS_INFO', '"\\"3.9.16\\""')]
    language = f77
    include_dirs = ['/usr/local/atlas-3.9.16/include']

lapack_mkl_info:
  NOT AVAILABLE

blas_mkl_info:
  NOT AVAILABLE

mkl_info:
  NOT AVAILABLE

Ответы [ 4 ]

5 голосов
/ 13 мая 2011

Возможно, виновником является копирование массивов, переданных в точка .

Как сказал Свен, продукт dot основан на операциях BLAS. Эти операции требуют массивов, хранящихся в непрерывном порядке C. Если оба массива, переданные точка , находятся в C_CONTIGUOUS, вы должны увидеть лучшую производительность.

Конечно, если ваши два массива, переданные в точку, действительно являются 1D (8,), тогда вы должны увидеть и , что флаги C_CONTIGUOUS AND F_CONTIGUOUS установлены в 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


Альтернатива: используйте _GEMM от BLAS, который открывается через модуль, scipy.linalg.fblas . (Два массива, A и B, очевидно, в порядке Фортрана, потому что используется fblas .)

from scipy.linalg import fblas as FB
X = FB.dgemm(alpha=1., a=A, b=B, trans_b=True)
5 голосов
/ 13 мая 2011

Ваши массивы не очень большие, поэтому ATLAS, вероятно, мало что делает. Каковы ваши сроки для следующей программы Fortran? Предполагая, что ATLAS мало что делает, это должно дать вам представление о том, насколько быстрой могла бы быть точка (), если бы не было никаких накладных расходов Python. С gfortran -O3 я получаю скорость 5 +/- 0,5 мкс.

    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
4 голосов
/ 13 мая 2011

Единственное, что я могу придумать, чтобы ускорить это, это убедиться, что ваша установка NumPy скомпилирована с оптимизированной библиотекой BLAS (например, ATLAS). numpy.dot() - это одна из немногих функций NumPy, использующих BLAS.

2 голосов
/ 14 мая 2011

numpy.dot будет использовать многопоточность, если скомпилировано правильно.Удостоверьтесь, что это делает с вершиной.Я знаю случаи, когда многопоточность в numpy w / atlas не работала.Кроме того, стоит попытаться использовать неповоротливую версию, скомпилированную с библиотеками intel mkl.Они включают подпрограммы blas, которые должны быть быстрее, чем атлас на оборудовании Intel.Вы могли бы попробовать Python дистрибутив enthought.Содержит все это и бесплатно для людей с учетной записью электронной почты edu.

...