Я хотел бы написать программу, которая широко использует функциональные возможности линейной алгебры BLAS и LAPACK. Поскольку производительность - это проблема, я провел несколько тестов и хотел бы знать, законен ли принятый мной подход.
У меня, так сказать, три участника, и я хочу проверить их выступление с помощью простого умножения матрицы на матрицу. Конкурсанты:
- Numpy, используя только функциональность
dot
. - Python, вызывающий функции BLAS через общий объект.
- C ++, вызывающий функции BLAS через общий объект.
Сценарий
Я реализовал умножение матрицы на матрицу для разных измерений i
. i
работает от 5 до 500 с шагом 5 и матрицы m1
и m2
настроены следующим образом:
m1 = numpy.random.rand(i,i).astype(numpy.float32)
m2 = numpy.random.rand(i,i).astype(numpy.float32)
1. Нумпи
Используемый код выглядит так:
tNumpy = timeit.Timer("numpy.dot(m1, m2)", "import numpy; from __main__ import m1, m2")
rNumpy.append((i, tNumpy.repeat(20, 1)))
2. Python, вызывающий BLAS через общий объект.
С функцией
_blaslib = ctypes.cdll.LoadLibrary("libblas.so")
def Mul(m1, m2, i, r):
no_trans = c_char("n")
n = c_int(i)
one = c_float(1.0)
zero = c_float(0.0)
_blaslib.sgemm_(byref(no_trans), byref(no_trans), byref(n), byref(n), byref(n),
byref(one), m1.ctypes.data_as(ctypes.c_void_p), byref(n),
m2.ctypes.data_as(ctypes.c_void_p), byref(n), byref(zero),
r.ctypes.data_as(ctypes.c_void_p), byref(n))
тестовый код выглядит так:
r = numpy.zeros((i,i), numpy.float32)
tBlas = timeit.Timer("Mul(m1, m2, i, r)", "import numpy; from __main__ import i, m1, m2, r, Mul")
rBlas.append((i, tBlas.repeat(20, 1)))
3. c ++, вызов BLAS через общий объект
Теперь код C ++, естественно, немного длиннее, поэтому я сокращаю информацию до минимума.
Я загружаю функцию с помощью
void* handle = dlopen("libblas.so", RTLD_LAZY);
void* Func = dlsym(handle, "sgemm_");
Я измеряю время gettimeofday
так:
gettimeofday(&start, NULL);
f(&no_trans, &no_trans, &dim, &dim, &dim, &one, A, &dim, B, &dim, &zero, Return, &dim);
gettimeofday(&end, NULL);
dTimes[j] = CalcTime(start, end);
где j
цикл выполняется 20 раз. Я подсчитываю прошедшее время с
double CalcTime(timeval start, timeval end)
{
double factor = 1000000;
return (((double)end.tv_sec) * factor + ((double)end.tv_usec) - (((double)start.tv_sec) * factor + ((double)start.tv_usec))) / factor;
}
Полученные результаты
Результат показан на графике ниже:
Вопросы
- Как вы думаете, мой подход справедлив, или я могу избежать ненужных накладных расходов?
- Ожидаете ли вы, что результат покажет такое огромное расхождение между подходами c ++ и python? Оба используют общие объекты для своих вычислений.
- Поскольку я предпочитаю использовать в своей программе python, что я могу сделать для увеличения производительности при вызове подпрограмм BLAS или LAPACK?
Скачать
Полную версию теста можно скачать здесь . (JF Себастьян сделал эту ссылку возможной ^^)
r
матрицы несправедливо. Решаю "вопрос" прямо сейчас и выкладываю новые результаты.np.ascontiguousarray()
(рассмотрите порядок C и Fortran). 2. Убедитесь, чтоnp.dot()
использует то же самоеlibblas.so
.m1
иm2
имеютascontiguousarray
флаг какTrue
. И numpy использует тот же общий объект, что и C. Что касается порядка массива: в настоящее время меня не интересует результат вычисления, поэтому порядок не имеет значения.Ответы:
Я проверил ваш тест . На моей машине нет разницы между C ++ и numpy:
Это кажется справедливым из-за отсутствия разницы в результатах.
Нет.
Убедитесь, что numpy использует оптимизированную версию библиотек BLAS / LAPACK в вашей системе.
источник
ОБНОВЛЕНИЕ (30.07.2014):
Я повторно запустил тест на нашем новом HPC. Как аппаратное обеспечение, так и программный стек изменились по сравнению с настройкой в исходном ответе.
Я помещаю результаты в электронную таблицу Google (содержит также результаты из исходного ответа).
Оборудование
Наш HPC имеет два разных узла: один с процессорами Intel Sandy Bridge, а другой - с новыми процессорами Ivy Bridge:
Сэнди (MKL, OpenBLAS, ATLAS):
Плющ (MKL, OpenBLAS, ATLAS):
Программное обеспечение
Программный стек предназначен для обоих узлов sam. Вместо того , чтобы GotoBLAS2 , OpenBLAS используется , и есть также многопоточный ATLAS BLAS , который установлен в 8 потоков (зашиты).
Тест точечного продукта
Код теста такой же, как показано ниже. Однако для новых машин я также провел тест для размеров матрицы 5000 и 8000 .
В таблице ниже представлены результаты тестов из исходного ответа (переименованные: MKL -> Nehalem MKL, Netlib Blas -> Nehalem Netlib BLAS и т. Д.)
Однопоточная производительность:
Многопоточная производительность (8 потоков):
Потоки и размер матрицы (Ivy Bridge MKL) :
Benchmark Suite
Однопоточная производительность:
Многопоточная (8 потоков) производительность:
Вывод
Результаты нового теста аналогичны результатам в исходном ответе. OpenBLAS и MKL работают на одном уровне, за исключением теста на собственное значение . В собственных значениях тест выполняет только достаточно хорошо на OpenBLAS в режиме однотридового . В многопоточном режиме производительность хуже.
Таблица "Размер матрицы и количество нитей" также показывает, что, хотя MKL и OpenBLAS обычно хорошо масштабируются с количеством ядер / потоков, это зависит от размера матрицы. Для небольших матриц добавление большего количества ядер не сильно улучшит производительность.
При переходе от Sandy Bridge к Ivy Bridge производительность увеличивается примерно на 30%, что может быть связано либо с более высокой тактовой частотой (+ 0,8 ГГц), либо с лучшей архитектурой.
Исходный ответ (04.10.2011):
Некоторое время назад мне пришлось оптимизировать некоторые вычисления / алгоритмы линейной алгебры, которые были написаны на Python с использованием numpy и BLAS, поэтому я протестировал / протестировал различные конфигурации numpy / BLAS.
В частности, я тестировал:
Я провел два разных теста:
Вот мои результаты:
Машины
Linux (MKL, ATLAS, No-MKL, GotoBlas2):
Mac Book Pro (Accelerate Framework):
Mac Server (Accelerate Framework):
Тест точечного продукта
Код :
Результаты :
Benchmark Suite
Код :
дополнительную информацию о наборе тестов см. Здесь .
Результаты :
Монтаж
Установка 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 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, а также довольно прост в использовании.
источник
Вот еще один тест (в Linux просто введите
make
): http://dl.dropbox.com/u/5453551/blas_call_benchmark.ziphttp://dl.dropbox.com/u/5453551/blas_call_benchmark.png
Я не вижу существенной разницы между разными методами для больших матриц, между Numpy, Ctypes и Fortran. (Fortran вместо C ++ --- и если это важно, вероятно, ваш тест не работает.)
Возможно, в вашем тесте есть и другие ошибки, например, сравнение между разными библиотеками BLAS или разными настройками BLAS, такими как количество потоков, или между реальным временем и временем процессора?CalcTime
Кажется, что ваша функция на C ++ имеет знаковую ошибку.... + ((double)start.tv_usec))
должно быть вместо этого... - ((double)start.tv_usec))
.РЕДАКТИРОВАТЬ : не удалось подсчитать фигурные скобки в
CalcTime
функции - все в порядке.В качестве ориентира: если вы проводите тест, всегда публикуйте где-нибудь весь код. Комментирование тестов, особенно когда это удивительно, без полного кода обычно непродуктивно.
Чтобы узнать, с каким BLAS Numpy связана ссылка, выполните:
ОБНОВЛЕНИЕ : если вы не можете импортировать numpy.core._dotblas, ваш Numpy использует свою внутреннюю резервную копию BLAS, которая работает медленнее и не предназначена для использования в вычислениях производительности! Ответ от @Woltan ниже указывает на то, что это объяснение разницы, которую он / она видит в Numpy против Ctypes + BLAS.
Чтобы исправить ситуацию, вам понадобится ATLAS или MKL --- ознакомьтесь с этими инструкциями: http://scipy.org/Installing_SciPy/Linux Большинство дистрибутивов Linux поставляются с ATLAS, поэтому лучший вариант - установить их
libatlas-dev
пакет (название может отличаться) .источник
import numpy.core._dotblas
. В чем может быть проблема? Я постараюсь очистить свой тест и написать make-файл, чтобы другие могли его протестировать.otool -L
вместоldd
LinuxУчитывая строгость, которую вы продемонстрировали в своем анализе, я удивлен результатами, полученными на данный момент. Я поставил это как «ответ», но только потому, что он слишком длинный для комментария и дает возможность (хотя я полагаю, вы это учли).
Я бы подумал, что подход numpy / python не добавит много накладных расходов для матрицы разумной сложности, поскольку по мере увеличения сложности доля, в которой участвует python, должна быть небольшой. Меня больше интересуют результаты в правой части графика, но показанное там несоответствие на порядки будет тревожным.
Интересно, используете ли вы лучшие алгоритмы, которые может использовать numpy. Из руководства по компиляции для linux:
"Build FFTW (3.1.2): SciPy Versions> = 0.7 и Numpy> = 1.2: из-за проблем с лицензией, конфигурацией и обслуживанием поддержка FFTW была удалена в версиях SciPy> = 0.7 и NumPy> = 1.2. Вместо этого теперь используется встроенная версия fftpack. Есть несколько способов воспользоваться скоростью FFTW, если это необходимо для анализа. Перейдите на версию Numpy / Scipy, которая включает поддержку. Установите или создайте свою собственную оболочку FFTW. См. http: //developer.berlios.de/projects/pyfftw/ в качестве неподтвержденного примера ".
Вы скомпилировали numpy с помощью mkl? ( http://software.intel.com/en-us/articles/intel-mkl/ ). Если вы работаете в Linux, инструкции по компиляции numpy с помощью mkl находятся здесь: http://www.scipy.org/Installing_SciPy/Linux#head-7ce43956a69ec51c6f2cedd894a4715d5bfff974 (несмотря на URL-адрес). Ключевая часть:
Если вы работаете в Windows, вы можете получить скомпилированный двоичный файл с помощью mkl (а также получить pyfftw и многие другие связанные алгоритмы) по адресу: http://www.lfd.uci.edu/~gohlke/pythonlibs/ , с Я хочу поблагодарить Кристофа Гольке из лаборатории динамики флуоресценции Калифорнийского университета в Ирвине.
Предостережение, в любом случае есть много проблем с лицензированием и т. Д., О которых следует знать, но страница Intel объясняет их. Опять же, я полагаю, вы об этом думали, но если вы соответствуете требованиям лицензирования (что в Linux очень легко сделать), это значительно ускорит работу с numpy по сравнению с использованием простой автоматической сборки, даже без FFTW. Мне будет интересно подписаться на эту тему и узнать, что думают другие. Тем не менее, отличная строгость и отличный вопрос. Спасибо, что разместили это.
источник