Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Быстрые матричные сложения


Автор: Elfet 17.5.2010, 22:18
Всем привет! 

Чиркнул на своем блоге о http://blog.elfet.ru/cpp/matrix-expressions/. Пожалуйста, прокомментируйте!  smile 

Сам пост:
Цитата

В одном проекте на С++ мне понадобилось два типа матриц: разреженные и заполненные.
Для первых выбрали матрицы из библиотеки uBLAS, для вторых выбрать библиотеку сложнее, так как важна была скорость с которой выполняются операции сложения матриц и умножения на скаляр.
Я решил протестировать несколько библиотек: uBLAS, tvmet и AlgLib.

Вот что получилось:

   1. операция: n = m + m;
      uBLAS: 1.357
      tvmet: 0.945
      AlgLib: 0.889
   2. операция: n = 2 * m – m;
      uBLAS: 1.607
      tvmet: 1.512
      AlgLib: 1.404
   3. операция: n = 2 * m + m / 3.3 – 0.1 * -m;
      uBLAS: 2.854
      tvmet: 3.176
      AlgLib: 3.682

В uBLAS хорошо оптимизированы алгоритмы по работе с выражениями и большими матрицами, но хуже работает на простых выражениях и маленьких матрицах чем AlgLib.

Тогда мне в голову пришла гениальная идея о том как можно ускорить простые операции с матрицами до максимума – использовать для этого циклы smile
А для красоты использовать вот такой-вот define:

Код

#define MatrixExp(n, exp) {\
for(int i = 0; i < n.size1(); i++)  \
for(int j = 0; j < n.size2(); j++) \
    n(i, j) = exp; \
}


Этим дефайном очень просто пользоваться: MatrixExp([новая матрица], [выражение с индексами (i,j)] ),
пример:

Код

MatrixExp(new_matrix, 2 * m1(i,j) + m2(i,j) -m3(i,j) / 5 );


Для любых выражений скорость на порядок выше ~ 0.515 (так не создаются временные объекты)

Вот пример из рабочего кода:

Код

Matrix total(varsize, varsize);
MatrixExp(total,  Ck[j] * k(i,j) + Ckx[j] * k_x(i,j) + Cky[j] * k_y(i,j)  );


PS Matrix – это моя обертка над классом ap::real_2d_array из AlgLib. Так как у них уж очень не удобно всё.

Автор: kemiisto 17.5.2010, 22:43
Elfet, хотелось бы посмотреть на результаты http://eigen.tuxfamily.org/index.php?title=Main_Page.

Автор: toxx 17.5.2010, 23:43
Elfet
а какого размера матрицы тестировались?

Автор: Elfet 17.5.2010, 23:49
kemiisto,  smile 

uBLAS я выбрал так как для неё нашёл реализованный метод GMRES. tvmet же рекомендуется на сайте ublas для маленьких матриц. AlgLib так же взял потому что уже используем её (SVD-разложение).

Добавлено через 1 минуту и 27 секунд
toxx, для 3х3 и 4х4.

Автор: toxx 17.5.2010, 23:53
Elfet
я думал побольше =) что-то типа 1000х1000 и побольше =) интересно же как будет вести себя всё это дело...

p.s. спасибо за ответ в блоге.

Автор: Elfet 17.5.2010, 23:58
toxx, ну 1000 у нас просто редко встречаются smile Если матрица большая и разреженная то лучше конечно же будет справляться специализированные библиотеки такие как uBLAS.

Чаще всего встречаются матрицы 3х3, 4х4 и очень большие 1000000х1000000.

Автор: toxx 18.5.2010, 00:07
Elfet
ага, понятно.я просто к тому, что эти измерения очень интересны в плане цифр(даже выступают с докладами на такие темы),
видел вот такие же замеры выполнения для различных видов сортировки(больше 3х разновидностей) 
различных матриц( как раз от 1000х1000 до 5000х5000 элементов,заполненных разными способами) очень интересно было смотреть что и как быстро справляется.

Автор: borisbn 18.5.2010, 06:18
Elfet, попробуй Intel Performance Primitives. На своём процессоре они творят чудеса. Правда, платные. Но, если ты не вольный каменьщик, попроси фирму купить. По-моему, не очень дорого. 

Автор: Alexeis 18.5.2010, 09:20
Elfet, попробуй еще вспомогательную библиотеку DirectX для работы с матрицами фиксированного размера. Кроме, думаю будет эффективно загружать флоаты/даблы сразу блоками по 128/256 бит и проводить вычисления при помощи инструкций SSE. Например в 256 битный регистр SSE влезет сразу 4 дабла или 8 флоатов. Для матрицы 4х4 это либо одна строка либо пол матрицы за одну инструкцию.

Автор: GoldFinch 18.5.2010, 09:52
Цитата(Elfet @  17.5.2010,  23:18 Найти цитируемый пост)
Тогда мне в голову пришла гениальная идея о том как можно ускорить простые операции с матрицами до максимума – использовать для этого циклы 

почитайте про expression templates

Автор: Elfet 18.5.2010, 10:26
borisbn, я это, диплом делаю smile


Alexeis, использовать железо для просчётов? нам правда нужна кросс-платформеность. 


Цитата(GoldFinch @  18.5.2010,  10:52 Найти цитируемый пост)
почитайте про expression templates 

Как я понимаю, они реализованы в uBLAS, однако быстрее всё-равно использовать define MatrixExp. smile

Автор: GoldFinch 18.5.2010, 10:46
Цитата(Elfet @  18.5.2010,  11:26 Найти цитируемый пост)
однако быстрее всё-равно использовать define MatrixExp

что быстрее? кодить? сомневаюсь.
код работает? скорость та же.

Автор: W4FhLF 18.5.2010, 11:04
У меня есть Intel Performance Primitives for Small Matrices. Правда я не юзал эту часть библиотеки, но наверняка она уделает все остальные.

Цитата(Alexeis @  18.5.2010,  09:20 Найти цитируемый пост)
Например в 256 битный регистр SSE влезет сразу 4 дабла или 8 флоатов.


В SSE таких регистров нет. 

Автор: Elfet 18.5.2010, 11:27
Цитата(GoldFinch @  18.5.2010,  11:46 Найти цитируемый пост)
что быстрее? кодить? сомневаюсь.
код работает? скорость та же. 

А же провёл тесты. uBLAS проигрывает smile

Автор: Alexeis 18.5.2010, 12:01
Цитата(Elfet @  18.5.2010,  09:26 Найти цитируемый пост)
Alexeis, использовать железо для просчётов? нам правда нужна кросс-платформеность. 

  В каком смысле железо? Речь о процессоре. Процессоры выше PIV гарантировано имеют SSE2. Для машин не старше 4х лет можно запросто рассчитывать на SSE3.
  Кросс-платформеность Windows-Linux будет. 

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

Добавлено @ 12:10
Цитата(W4FhLF @  18.5.2010,  10:04 Найти цитируемый пост)
В SSE таких регистров нет.  

  А что за регистры такие YMM0 — YMM15 ?

Вот например Intel рекомендует использовать их для оптимизации задач линейной алгебры.
http://software.intel.com/ru-ru/articles/optimize-for-intel-avx-using-intel-math-kernel-librarys-basic-linear-algebra-subprograms-blas-with-dgemm-routine/

Это что-то не то. Значит была речь о том, что можно производить параллельно 2е операции над 128 битными регистрами. В сумме получается 4 дабла или 8 флоатов. 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)