многопоточный блас в Python / Numpy - PullRequest
44 голосов
/ 10 марта 2011

Я пытаюсь реализовать большое количество матрично-матричных умножений в Python. Первоначально я предполагал, что NumPy будет автоматически использовать мои библиотеки BLAS с резьбой, так как я построил его для этих библиотек. Однако, когда я смотрю на top или что-то еще, мне кажется, что код вообще не использует многопоточность.

Есть идеи, что не так или что я могу сделать, чтобы легко использовать производительность BLAS?

Ответы [ 4 ]

103 голосов
/ 04 октября 2011

Я уже разместил это в другой ветке, но думаю, что он подходит лучше:

ОБНОВЛЕНИЕ (30.07.2014):

Я перезапускаюэталон на нашем новом HPC.И аппаратное обеспечение, и программный стек изменились по сравнению с настройкой в ​​исходном ответе.

Я поместил результаты в электронную таблицу Google (также содержит результаты из исходного ответа).

Аппаратное обеспечение

Наш HPC имеет два разных узла, один с процессорами Intel Sandy Bridge и один с более новыми процессорами Ivy Bridge:

Sandy (MKL, OpenBLAS, ATLAS):

  • CPU : 2 x 16 Intel (R) Xeon (R) E2560 Sandy Bridge @ 2,00 ГГц (16 ядер)
  • RAM : 64 ГБ

Плющ (MKL, OpenBLAS, ATLAS):

  • CPU : 2x 20 Intel (R) Xeon (R) E2680 V2 Ivy Bridge @ 2,80 ГГц (20 ядер, с HT = 40 ядер)
  • RAM : 256 ГБ

Программное обеспечение

Программный стек предназначен для обоих узлов.Вместо GotoBLAS2 используется OpenBLAS , а также имеется многопоточный ATLAS BLAS , который настроен на 8 потоков (жестко закодированный).

  • ОС : Suse
  • Компилятор Intel : ictce-5.3.0
  • Numpy: 1.8.0
  • OpenBLAS: 0.2.6
  • ATLAS: : 3.8.4

Точка-Производственный эталон

Контрольный код тот же, что и ниже.Однако для новых машин я также провел эталонный тест для размеров матрицы 5000 и 8000 .
В приведенной ниже таблице приведены результаты эталонных тестов из исходного ответа (переименованный: MKL ->Nehalem MKL, Netlib Blas -> Nehalem Netlib BLAS и т. Д.)

Matrix multiplication (sizes=[1000,2000,3000,5000,8000])

Однопоточная производительность: single threaded performance

Многопоточная производительность (8 потоков): multi-threaded (8 threads) performance

Потоки против размера матрицы (Ivy Bridge MKL) : Matrix-size vs threads

Benchmark Suite

benchmark suite

Однопоточная производительность: enter image description here

Многопоточная (8 нитей) производительность: enter image description here

Заключение

Результаты нового теста аналогичны исходным ответам. OpenBLAS и MKL работают на одном уровне, за исключением теста Eigenvalue .Тест Eigenvalue достаточно хорошо работает на OpenBLAS в однопоточном режиме .В многопоточном режиме производительность хуже.

Диаграмма "Размер матрицы в сравнении с потоками" также показывает, что, хотя MKL и OpenBLAS в целом хорошо масштабируются с количеством ядер / потоков, это зависит от размера матрицы.Для небольших матриц добавление большего количества ядер не сильно улучшит производительность.

Также примерно на 30% увеличена производительность с Sandy Bridge до Ivy Bridge , что может быть связано с более высокой тактовой частотой (+ 0,8 ГГц) и / или лучшеархитектура.


Оригинальный ответ (04.10.2011):

Некоторое время назад мне пришлось оптимизировать некоторые вычисления / алгоритмы линейной алгебры, которые были написаны на python, используя numpy и BLAS, поэтому я провел сравнительный анализ / тестировалразличные конфигурации NUMPY / BLAS.

В частности, я тестировал:

  • Numpy с ATLAS
  • Numpy с GotoBlas2 (1.13)
  • Numpy с MKL (11,1 / 073)
  • Numpy с Accelerate Framework (Mac OS X)

Я выполнил два разных теста:

  1. простой точечный продукт матриц сразные размеры
  2. Набор тестов, который можно найти здесь .

Вот мои результаты:

Машины

Linux (MKL, ATLAS, No-MKL, GotoBlas2):

  • OS : Ubuntu Lucid 10,4 64 бит.
  • Процессор : 2 x 4 Intel (R) Xeon (R) E5504 @ 2,00 ГГц (8 ядер)
  • RAM : 24 ГБ
  • Компилятор Intel : 11,1 / 073
  • Scipy : 0,8
  • Numpy : 1,5

Mac Book Pro (Accelerate Framework):

  • ОС : Mac OS X Snow Leopard (10,6)
  • CPU : 1 Intel Core 2 Duo 2,93 ГГц (2 ядра)
  • RAM : 4 ГБ
  • Scipy : 0,7
  • Numpy : 1,3

Mac Server (Accelerate Framework):

  • ОС : сервер Mac OS X Snow Leopard (10,6)
  • ЦП : 4 X Intel (R) Xeon (R) E5520 @ 2,26 ГГц (8 ядер)
  • RAM : 4 ГБ
  • Scipy : 0,8
  • Numpy : 1.5.1

Точка сравнения продукта

Код :

import numpy as np
a = np.random.random_sample((size,size))
b = np.random.random_sample((size,size))
%timeit np.dot(a,b)

Результаты :

    System        |  size = 1000  | size = 2000 | size = 3000 |
netlib BLAS       |  1350 ms      |   10900 ms  |  39200 ms   |    
ATLAS (1 CPU)     |   314 ms      |    2560 ms  |   8700 ms   |     
MKL (1 CPUs)      |   268 ms      |    2110 ms  |   7120 ms   |
MKL (2 CPUs)      |    -          |       -     |   3660 ms   |
MKL (8 CPUs)      |    39 ms      |     319 ms  |   1000 ms   |
GotoBlas2 (1 CPU) |   266 ms      |    2100 ms  |   7280 ms   |
GotoBlas2 (2 CPUs)|   139 ms      |    1009 ms  |   3690 ms   |
GotoBlas2 (8 CPUs)|    54 ms      |     389 ms  |   1250 ms   |
Mac OS X (1 CPU)  |   143 ms      |    1060 ms  |   3605 ms   |
Mac Server (1 CPU)|    92 ms      |     714 ms  |   2130 ms   |

Dot product benchmark - chart

Benchmark Suite

Код :
Для получения дополнительной информациио наборе тестов см. здесь .

Результаты :

    System        | eigenvalues   |    svd   |   det  |   inv   |   dot   |
netlib BLAS       |  1688 ms      | 13102 ms | 438 ms | 2155 ms | 3522 ms |
ATLAS (1 CPU)     |   1210 ms     |  5897 ms | 170 ms |  560 ms |  893 ms |
MKL (1 CPUs)      |   691 ms      |  4475 ms | 141 ms |  450 ms |  736 ms |
MKL (2 CPUs)      |   552 ms      |  2718 ms |  96 ms |  267 ms |  423 ms |
MKL (8 CPUs)      |   525 ms      |  1679 ms |  60 ms |  137 ms |  197 ms |  
GotoBlas2 (1 CPU) |  2124 ms      |  4636 ms | 147 ms |  456 ms |  743 ms |
GotoBlas2 (2 CPUs)|  1560 ms      |  3278 ms | 116 ms |  295 ms |  460 ms |
GotoBlas2 (8 CPUs)|   741 ms      |  2914 ms |  82 ms |  262 ms |  192 ms |
Mac OS X (1 CPU)  |   948 ms      |  4339 ms | 151 ms |  318 ms |  566 ms |
Mac Server (1 CPU)|  1033 ms      |  3645 ms |  99 ms |  232 ms |  342 ms |

Benchmark suite - chart

Установка

Установка MKL включала в себя установку полного набора Intel Compiler Suite, который довольно прост.Однако из-за некоторых ошибок / проблем конфигурирование и компиляция Numpy с поддержкой MKL было немного хлопотно.

GotoBlas2 - это небольшой пакет, который может быть легко скомпилирован как общая библиотека.Однако из-за ошибки вам необходимо заново создать разделяемую библиотеку после ее построения, чтобы использовать ее с numpy.
В дополнение к этому построению она для нескольких целевых платформ не работала для некоторыхпричина.Поэтому мне пришлось создать файл .so для каждой платформы, для которой я хочу иметь оптимизированный файл libgoto2.so .

Если вы установите numpy из репозитория Ubuntu, он автоматически установит и настроит numpy для использования ATLAS .Установка ATLAS из исходного кода может занять некоторое время и потребует дополнительных действий (fortran и т. Д.).

Если вы установите numpy на компьютер Mac OS X с Fink или Порты Mac , он либо настроит numpy для использования ATLAS или Apple's Accelerate Framework .Вы можете проверить, запустив ldd в файле numpy.core._dotblas или вызвав numpy.show_config () .

Выводы

MKL работает лучше всего, за ним следует GotoBlas2 .
В тесте собственное значение GotoBlas2 работает на удивление хуже, чем ожидалось.Не уверен, почему это так.
Apple Accelerate Framework работает действительно хорошо, особенно в однопоточном режиме (по сравнению с другими реализациями BLAS).

Оба GotoBlas2 и MKL очень хорошо масштабируются с количеством потоков.Так что, если вам приходится иметь дело с большими матрицами, запуск их в нескольких потоках очень поможет.

В любом случае не используйте стандартную реализацию netlib blas , поскольку она слишком медленная длялюбая серьезная вычислительная работа.

В нашем кластере я также установил ACML от AMD и производительность была похожа на MKL и GotoBlas2 .У меня нет жестких чисел.

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

Если вы хотите кодировать на C ++ / C, также проверьте Eigen3 , который должен опережать MKL / GotoBlas2 в некоторых случаях и являетсятакже довольно прост в использовании.

17 голосов
/ 10 марта 2011

Не все NumPy используют BLAS, только некоторые функции, в частности dot(), vdot() и innerproduct() и несколько функций из модуля numpy.linalg. Также обратите внимание, что многие операции NumPy ограничены пропускной способностью памяти для больших массивов, поэтому оптимизированная реализация вряд ли даст какое-либо улучшение. Способность многопоточности повышать производительность, если вы ограничены пропускной способностью памяти, сильно зависит от вашего оборудования.

2 голосов
/ 11 марта 2011

Возможно, потому что умножение Matrix x Matrix ограничено памятью, что добавление дополнительных ядер в одну и ту же иерархию памяти не даст вам много.Конечно, если вы видите существенное ускорение, когда вы переключаетесь на реализацию на Фортране, то я могу ошибаться.

Насколько я понимаю, правильное кэширование гораздо важнее для такого рода проблем, чем вычислительная мощность.Предположительно BLAS делает это для вас.

Для простого теста вы можете попробовать установить 1006 * дистрибутив Python для сравнения.Они связаны с Intel Math Kernel Library , которая, как мне кажется, использует несколько ядер, если таковые имеются.

1 голос
/ 10 августа 2013

Вы слышали о MAGMA? Матричная алгебра на GPU и многоядерная архитектура http://icl.cs.utk.edu/magma/

Проект MAGMA направлен на разработку библиотеки плотной линейной алгебры, аналогичной LAPACK, но для гетерогенных / гибридных архитектур, начиная с современных систем "Multicore + GPU".

...