Я пытаюсь реализовать большое количество матрично-матричных умножений в Python. Первоначально я предполагал, что NumPy будет автоматически использовать мои потоковые библиотеки BLAS, поскольку я построил их для этих библиотек. Однако, когда я смотрю top или что-то еще, похоже, что код не использует потоковую передачу вообще.
Любые идеи, что не так, или что я могу сделать, чтобы легко использовать производительность BLAS?
Ответ 2
Я уже разместил это в другом потоке, но я думаю, что он лучше подходит в этом:
ОБНОВЛЕНИЕ (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 ядер)
- ОЗУ: 64 ГБ
Ivy (MKL, OpenBLAS, ATLAS):
- CPU: 2 x 20 Intel (R) Xeon (R) E2680 V2 Ivy Bridge @2,80 ГГц (20 ядер, с HT = 40 ядер)
- ОЗУ: 256 ГБ
Программное обеспечение
Программный стек предназначен для обоих узлов sam. Вместо GotoBLAS2 используется OpenBLAS, а также есть многопоточный ATLAS BLAS, который настроен на 8 потоков (hardcoded).
- ОС: Suse
- Компилятор Intel: ictce-5.3.0
- Numpy: 1.8.0
- OpenBLAS: 0.2.6
- ATLAS:: 3.8.4
Контрольная точка Dot-Product
Контрольный код такой же, как и ниже. Однако для новых машин я также использовал контрольный показатель для размеров матрицы 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 выполняются на одном уровне, за исключением теста Собственное значение.
Тест Собственные значения работает достаточно хорошо на OpenBLAS в режиме с одним потоком.
В многопоточном режиме производительность хуже.
Таблица "Матрица по сравнению с диаграммой потоков" также показывает, что хотя MKL, а также OpenBLAS обычно хорошо масштабируются с количеством ядер/потоков, это зависит от размера матрицы. Для небольших матриц добавление большего количества ядер не улучшит производительность.
Также наблюдается увеличение производительности примерно на 30% от Sandy Bridge до Ivy Bridge, что может быть связано с более высокой тактовой частотой (+ 0,8 ГГц) и/или лучшей архитектурой,
Оригинальный ответ (04.10.2011):
Некоторое время назад мне приходилось оптимизировать вычисления/алгоритмы линейной алгебры, написанные на питоне с использованием numpy и BLAS, поэтому я тестировал/тестировал различные конфигурации numpy/BLAS.
В частности, я тестировал:
- Numpy с ATLAS
- Numpy с GotoBlas2 (1.13)
- Numpy с MKL (11.1/073)
- Numpy with Accelerate Framework (Mac OS X)
Я выполнил два разных теста:
- простой точечный продукт матриц разного размера
- Набор тестов, который можно найти здесь.
Вот мои результаты:
Машины
Linux (MKL, ATLAS, No-MKL, GotoBlas2):
- ОС: Ubuntu Lucid 10.4 64 бит.
- CPU: 2 x 4 Intel (R) Xeon (R) E5504 @2,00 ГГц (8 ядер)
- ОЗУ: 24 ГБ
- Компилятор Intel: 11.1/073
- Scipy: 0.8
- Numpy: 1.5
Mac Book Pro (ускорение):
- ОС: Mac OS X Snow Leopard (10.6)
- CPU: 1 Intel Core 2 Duo 2.93 Ghz (2 ядра)
- ОЗУ: 4 ГБ
- Scipy: 0.7
- Numpy: 1.3
Mac Server (ускорение):
- ОС: Mac OS X Snow Leopard Server (10.6)
- CPU: 4 X Intel (R) Xeon (R) E5520 @2.26 Ghz (8 ядер)
- ОЗУ: 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, который довольно прост. Однако из-за некоторых ошибок/проблем настройка и компиляция numpy с поддержкой MKL была немного сложной.
GotoBlas2 - это небольшой пакет, который можно легко скомпилировать как общую библиотеку. Однако из-за ошибки вам необходимо заново создать общую библиотеку после ее создания, чтобы использовать ее с numpy.
В дополнение к этому зданию он для нескольких целевых платформ не работал по какой-то причине. Поэтому мне пришлось создать файл .so для каждой платформы, для которой я хочу иметь оптимизированный файл libgoto2.so.
Если вы установите numpy из репозитория Ubuntu, он автоматически установит и настроит numpy для использования ATLAS. Установка ATLAS из источника может занять некоторое время и потребует дополнительных шагов (fortran и т.д.).
Если вы установите numpy на машине Mac OS X с Fink или Mac-портами, он либо настроит numpy на использование ATLAS, либо Apple Accelerate Framework.
Вы можете проверить, запустив ldd в файле numpy.core._dotblas или вызвав numpy.show_config().
Выводы
MKL лучше всего отслеживается GotoBlas2.
В тесте собственное значение GotoBlas2 работает на удивление хуже ожидаемого. Не знаю, почему это так.
Apple Accelerate Framework работает очень хорошо, особенно в однопоточном режиме (по сравнению с другими реализациями BLAS).
Оба GotoBlas2 и MKL очень хорошо масштабируются с количеством потоков. Поэтому, если вам приходится иметь дело с большими матрицами, запускающими его на нескольких потоках, это очень поможет.
В любом случае не используйте стандартную реализацию netlib blas, потому что она слишком медленна для любой серьезной вычислительной работы.
В нашем кластере я также установил AMD ACML, а производительность была похожа на MKL и GotoBlas2. У меня нет никаких жестких цифр.
Я лично рекомендовал бы использовать GotoBlas2, потому что он проще установить и бесплатно.
Если вы хотите ввести код на С++/C, также проверьте Eigen3, который должен превосходить MKL/GotoBlas2 в некоторых случаях и также довольно проста в использовании.