производительность NumPy с различными реализациями BLAS

Я запускаю алгоритм, реализованный на Python и использующий NumPy. Самая затратная с вычислительной точки зрения часть алгоритма включает решение набора линейных систем (т. е. вызов numpy.linalg.solve(). Я придумал этот небольшой тест:

import numpy as np
import time

# Create two large random matrices
a = np.random.randn(5000, 5000)
b = np.random.randn(5000, 5000)

t1 = time.time()
# That's the expensive call:
np.linalg.solve(a, b)
print time.time() - t1

Я запускал это на:

  1. Мой ноутбук, 15-дюймовый MacBook Pro конца 2013 года с 4 ядрами на частоте 2 ГГц (sysctl -n machdep.cpu.brand_string дает мне процессор Intel(R) Core(TM) i7-4750HQ с частотой 2,00 ГГц)
  2. Экземпляр Amazon EC2 c3.xlarge с 4 виртуальными ЦП. Amazon рекламирует их как «высокочастотные процессоры Intel Xeon E5-2680 v2 (Ivy Bridge)».

Нижняя линия:

  • На Mac это выполняется за ~4,5 секунды.
  • В экземпляре EC2 он выполняется за ~19,5 секунд.

Я также пробовал это на других установках на основе OpenBLAS / Intel MKL, и время выполнения всегда сравнимо с тем, что я получаю на экземпляре EC2 (по модулю конфигурации оборудования).

Кто-нибудь может объяснить, почему производительность на Mac (с Accelerate Framework) > в 4 раза выше? Более подробная информация о настройке NumPy/BLAS в каждом из них приведена ниже.

Настройка ноутбука

numpy.show_config() дает мне:

atlas_threads_info:
  NOT AVAILABLE
blas_opt_info:
    extra_link_args = ['-Wl,-framework', '-Wl,Accelerate']
    extra_compile_args = ['-msse3', '-I/System/Library/Frameworks/vecLib.framework/Headers']
    define_macros = [('NO_ATLAS_INFO', 3)]
atlas_blas_threads_info:
  NOT AVAILABLE
openblas_info:
  NOT AVAILABLE
lapack_opt_info:
    extra_link_args = ['-Wl,-framework', '-Wl,Accelerate']
    extra_compile_args = ['-msse3']
    define_macros = [('NO_ATLAS_INFO', 3)]
atlas_info:
  NOT AVAILABLE
lapack_mkl_info:
  NOT AVAILABLE
blas_mkl_info:
  NOT AVAILABLE
atlas_blas_info:
  NOT AVAILABLE
mkl_info:
  NOT AVAILABLE

Настройка экземпляра EC2:

В Ubuntu 14.04 я установил OpenBLAS с

sudo apt-get install libopenblas-base libopenblas-dev

При установке NumPy я создал site.cfg со следующим содержимым:

[default]
library_dirs= /usr/lib/openblas-base

[atlas]
atlas_libs = openblas

numpy.show_config() дает мне:

atlas_threads_info:
    libraries = ['lapack', 'openblas']
    library_dirs = ['/usr/lib']
    define_macros = [('ATLAS_INFO', '"\\"None\\""')]
    language = f77
    include_dirs = ['/usr/include/atlas']
blas_opt_info:
    libraries = ['openblas']
    library_dirs = ['/usr/lib']
    language = f77
openblas_info:
    libraries = ['openblas']
    library_dirs = ['/usr/lib']
    language = f77
lapack_opt_info:
    libraries = ['lapack', 'openblas']
    library_dirs = ['/usr/lib']
    define_macros = [('ATLAS_INFO', '"\\"None\\""')]
    language = f77
    include_dirs = ['/usr/include/atlas']
openblas_lapack_info:
  NOT AVAILABLE
lapack_mkl_info:
  NOT AVAILABLE
blas_mkl_info:
  NOT AVAILABLE
mkl_info:
  NOT AVAILABLE

person lum    schedule 22.10.2014    source источник
comment
У Haswell в два раза больше необработанных вычислений, чем у Ivybridge, за такт на ядро ​​(благодаря включению FMA). Интересно, ваш openblas был собран без поддержки AVX? Это дало бы еще 2x.   -  person Stephen Canon    schedule 23.10.2014
comment
Похоже, это может быть связано с этим. Можете ли вы проверить, выполняет ли ваш инстанс EC2 многопоточные операции BLAS?   -  person ali_m    schedule 19.12.2014


Ответы (1)


Причиной такого поведения может быть то, что Accelerate использует многопоточность, а другие нет.

Большинство реализаций BLAS используют переменную среды OMP_NUM_THREADS, чтобы определить, сколько потоков использовать. Я считаю, что они используют только 1 поток, если явно не указано иное. справочная страница Accelerate, однако похоже, что многопоточность включена по умолчанию; его можно отключить, установив переменную окружения VECLIB_MAXIMUM_THREADS.

Чтобы определить, действительно ли это происходит, попробуйте

export VECLIB_MAXIMUM_THREADS=1

перед вызовом версии Accelerate и

export OMP_NUM_THREADS=4

для других версий.

Независимо от того, является ли это действительно причиной, рекомендуется всегда устанавливать эти переменные при использовании BLAS, чтобы быть уверенным, что вы контролируете происходящее.

person Elmar Peise    schedule 07.01.2015
comment
Связанный с Accelerate, VECLIB_MAXIMUM_THREADS влияет на производительность numpy.linalg.norm. scipy.linalg.norm, с другой стороны, постоянно медленнее и не зависит от переменной, что наводит меня на мысль, что он не связан с Accelerate, а вместо этого использует ссылку LAPACK. - person Elmar Peise; 03.01.2017
comment
Спасибо Эльмар. Между прочим, scipy.linalg.norm делает if ord in (None, 2) and (a.ndim == 1): nrm2 = get_blas_funcs('nrm2'); norm в numpy.linalg.linalg говорит # Немедленно обрабатывать некоторые стандартные, простые, быстрые и распространенные случаи. В общем, слишком сложно. - person denis; 08.01.2017