犰狳矩阵库写
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根据Armadillo决定的操作自动生成内核的可能性,但我看不出任何方法可以直接使用。
有什么建议吗?
答案 0 :(得分:3)
您可能需要查看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内核中执行。没有创造临时工。我们还有单线程CPU,CUDA和OpenCL的后端。
披露:我是ArrayFire库的开发人员之一。
答案 1 :(得分:2)
您的示例中的操作可以使用最近添加的tensordot()
操作在VexCL中编写:
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()
只能用于单设备上下文。