Привет ЛОР, я вам тут покушать принёс.
В нашей науке довольно часто используется метод максимального правдоподобия. Максимум такой функции обычно находят с помощью какой-нибудь уже готовой библиотеки, вроде медленного, но проверенного временем Minuit, или чего-нибудь из nlopt. Основная сложность заключается в вычислении самой функции правдоподобия на каждом шаге итерации поиска максимума и её градиента, потому что данных-то много и надо просуммировать их всех, да и пространство параметров уже давно переваливает за пару сотен (вот пример такого анализа данных). Обычно задачу вычисления ненормированной вероятности одного события упрощают до линейной, однако сумма-то идёт по логарифмам вероятности, так что в конце-концов всё равно на каждом шаге возникает сумма от миллиона логарифмов от свёрток матриц с параметрами аппроксимации.
Но это была присказка.
А теперь сама сказка: как лучше всего сворачивать матрицы с параметрами? Как делать это быстро? Я написал простенький бенчмарк на плюсах, который генерит псевдослучайные данные; каждое событие представлено в виде эрмитовской матрицы, для бенча же вычисляется сумма - ln V^dag M V
, V — комплексные параметры (тоже генерятся случайно, но только один раз).
Я потестил Eigen и boost на дремучем i7 860 без avx инструкций, получается как-то так:
Compiler flags: -O3 -ffast-math -I/usr/include/eigen3
Number of events: 1000000
************************* Matrix size 10x10 ************************
=== Eigen with fixed size matrix
- ln L = -3.34078e+06 [n. u.]
Float size: 4 [Bytes]
FCN duration: 240.944 [ms]
=== Eigen with fixed size matrix
- ln L = -3.34073e+06 [n. u.]
Float size: 8 [Bytes]
FCN duration: 378.355 [ms]
=== Eigen with dynamic size matrix
- ln L = -3.34078e+06 [n. u.]
Float size: 4 [Bytes]
FCN duration: 262.532 [ms]
=== Eigen with dynamic size matrix
- ln L = -3.34073e+06 [n. u.]
Float size: 8 [Bytes]
FCN duration: 398.018 [ms]
=== Boost hermitian matrix
- ln L = -3.34078e+06 [n. u.]
Float size: 4 [Bytes]
FCN duration: 654.639 [ms]
=== Boost hermitian matrix
- ln L = -3.34073e+06 [n. u.]
Float size: 8 [Bytes]
FCN duration: 662.562 [ms]
************************* Matrix size 5x5 ************************
=== Eigen with fixed size matrix
- ln L = -1.51895e+06 [n. u.]
Float size: 4 [Bytes]
FCN duration: 242.141 [ms]
=== Eigen with fixed size matrix
- ln L = -1.51894e+06 [n. u.]
Float size: 8 [Bytes]
FCN duration: 380.236 [ms]
=== Eigen with dynamic size matrix
- ln L = -1.51895e+06 [n. u.]
Float size: 4 [Bytes]
FCN duration: 151.074 [ms]
=== Eigen with dynamic size matrix
- ln L = -1.51894e+06 [n. u.]
Float size: 8 [Bytes]
FCN duration: 169.722 [ms]
=== Boost hermitian matrix
- ln L = -1.51895e+06 [n. u.]
Float size: 4 [Bytes]
FCN duration: 204.22 [ms]
=== Boost hermitian matrix
- ln L = -1.51894e+06 [n. u.]
Float size: 8 [Bytes]
FCN duration: 205.454 [ms]
Как видите, буст начинает проигрывать при переходе от матриц 5x5 к 10x10. Однако я помню когда я гонял этот тест недели три назад на других (более новых) хостах, ситуация не была такой уж однозначной.
Я добавлю код теста в комментарии, авось уважаемая публика ткнёт меня носом в мои ошибки. cast Siborgium AntonI byko3y
WitcherGeralt annerleen вы там какие-то бенчи гоняли и устраивали традиционный срач синих с красными, вот вам однопоточный тест для вполне себе реальной задачи.