BOOST UBLAS матричный продукт очень медленно - PullRequest
4 голосов
/ 17 октября 2011

Есть ли способ улучшить производительность продукта boost ublas?

У меня есть две матрицы A, B, которые я хочу умножить / добавить / sub /...

В MATLAB vs. C ++ я получаю следующие значения [с] для операций с матрицами 2000x2000

OPERATION | MATLAB | C++ (MSVC10)
A + B     |  0.04  |  0.04
A - B     |  0.04  |  0.04
AB        |  1.0   | 62.66
A'B'      |  1.0   | 54.35

Почему здесь такая огромная потеря производительности?

Матрицы являются только действительными двойными числами. Но мне также нужны положительно определенные, симметричные, прямоугольные произведения.

EDIT: Код тривиален

matrix<double> A( 2000 , 2000 );
// Fill Matrix A
matrix<double> B = A;

C = A + B;
D = A - B;
E = prod(A,B);
F = prod(trans(A),trans(B));

РЕДАКТИРОВАТЬ 2: Результаты представляют собой средние значения 10 попыток. Стандартное значение было меньше 0,005

Я бы ожидал, что коэффициент 2-3 может быть, но не 50 (!)

РЕДАКТИРОВАТЬ 3: Все было исправлено в режиме выпуска (NDEBUG / MOVE_SEMANTICS / ..).

РЕДАКТИРОВАТЬ 4: Предварительно выделенные матрицы для результатов продукта не влияли на время выполнения.

Ответы [ 4 ]

4 голосов
/ 17 октября 2011

Опубликуйте свой код C + для совета по любым возможным оптимизациям.

Вы должны знать, однако, что Matlab является высокоспециализированным для своей заданной задачи, и вы вряд ли сможете соответствовать ему с помощью Boost. С другой стороны - Boost бесплатен, а Matlab определенно нет.

Я считаю, что наилучшей производительности Boost можно добиться, связав код uBlas с базовой реализацией LAPACK.

2 голосов
/ 08 июля 2012

Вы должны использовать noalias в левой части умножения матриц, чтобы избавиться от ненужных копий.

Вместо E = prod(A,B); используйте noalias(E) = prod(A,b);

Из документации:

Если вы точно знаете, что выражение левой руки и правой руки У выражения нет общего хранилища, тогда присваивание не имеет псевдонимов. в этом случае можно указать более эффективное назначение: noalias (C) = prod (A, B); Это позволяет избежать создания временной матрицы, которая требуется в обычном назначении. назначение 'noalias' требует, чтобы левая и правая стороны должны соответствовать размеру.

1 голос
/ 28 октября 2011

Существует множество эффективных реализаций BLAS, таких как ATLAS, gotoBLAS, MKL, вместо них используйте их.

Я не выбираю код, но думаю, что ublas :: prod (A, B) использует три цикла, без блоков и не подходит для кэширования. Если это правда, prod (A, B.trans ()) будет намного быстрее, чем другие.

Если cblas доступен, используйте cblas_dgemm для выполнения расчета. Если нет, вы можете просто переставить данные, значит, вместо этого prod (A, B.trans ()).

0 голосов
/ 18 октября 2011

Вы не знаете, какую роль здесь играет управление памятью.prod приходится выделять 32-мегабайтную матрицу, как и trans, дважды, и затем вы делаете все это 10 раз.Возьмите несколько стековых снимков и посмотрите, что на самом деле делает 1006 *.Мое глупое предположение: если вы предварительно распределите матрицы, вы получите лучший результат.

Другие способы ускорения умножения матриц:

  • , предварительно транспонировав левую- матрица, поддерживающая кеширование, и

  • , пропускающая нули.Только если A (i, k) и B (k, j) отличны от нуля, любое значение будет добавлено.

Независимо от того, сделано ли это в uBlas, можно только догадываться.

...