C++ матричная библиотека OpenCL с временным удалением

Матричная библиотека броненосца пишет

Armadillo использует метод отложенной оценки, чтобы объединить несколько операций в одну и уменьшить (или устранить) потребность во временных. Там, где это применимо, порядок операций оптимизирован. Отложенная оценка и оптимизация достигаются с помощью рекурсивных шаблонов и шаблонного метапрограммирования.

Это означает, что вы можете написать такие операции, как

arma::mat A, B;
arma::vec c, d;
...
d=(A % B)*c;

и никакие временные переменные не создаются. (обратите внимание, что% - это поэлементная операция над продуктом в броненосце)

Я хотел бы иметь возможность кодировать в подобном стиле для приложения OpenCL.

Я смотрел библиотеки VexCL, ViennaCL, Boost.Compute и clBLAS. VexCL и Boost.Compute даже не предоставляют базовых функций матрицы, таких как умножение. clBLAS не работает как библиотека шаблонов, поэтому вам нужно вручную вызывать операции. ViennaCL предоставляет все необходимые мне операции, но, похоже, не может связать их вместе.

Например

    d= linalg::prod(linalg::element_prod(A,B), c);

не компилируется.

Я думаю, что может быть некоторая возможность использования VexCL для автоматической генерации ядер на основе операций, которые решит Армадилло, но я не вижу никакого способа заставить это работать напрямую.

Какие-либо предложения?

2 ответа

Решение

Возможно, вы захотите проверить ArrayFire.

ArrayFire - это матричная библиотека с механизмом компиляции JIT, которая позволяет объединять операции в одно ядро. Это значительно уменьшает количество вызовов ядра для базовых элементарных операций, которые вы опубликовали выше. Например, код, который вы разместили, может быть записан как:

array A = randu(5, 5);       // 5x5 Matrix
array B = randu(5, 5);       // 5x5 Matrix
array c = constant(1, 1, 5); // 1x5 Matrix

array d = (A % B) + tile(c, 5);

В этом примере модуль и сложение будут выполняться в одном ядре OpenCL. Временные работы не создаются. У нас также есть бэкэнды для однопоточного процессора, CUDA и OpenCL.

Раскрытие информации: я являюсь одним из разработчиков библиотеки ArrayFire.

Операция из вашего примера может быть написана в VexCL с недавно добавленной tensordot() операция:

vex::vector<double> A(ctx, n * m), B(ctx, n * m);
vex::vector<double> c(ctx, n), d(ctx, n);

vex::slicer<1> s1(vex::extents[n]);    // shape of the vectors
vex::slicer<2> s2(vex::extents[n][m]); // shape of the matrices

using vex::_;
d = vex::tensordot(s2[_](A * B), s1[_](c), vex::axes_pairs(1, 0));

Это приведет к очень простой реализации продукта матрицы-вектора (так что, вероятно, не так эффективен, как ядро ​​BLAS, предоставляемое поставщиком). Но не будут задействованы временные фильтры, и будет запущено одно ядро.

Одно предостережение: tensordot() может использоваться только в контексте одного устройства.

Другие вопросы по тегам