C++ 具有临时消除功能的 OpenCL 矩阵库

C++ OpenCL matrix library with temporary elimination

本文关键字:OpenCL 功能 C++      更新时间:2023-10-16

犰狳矩阵库写入

犰狳采用延迟评估方法将多项操作合并为一项,并减少(或消除)对临时人员的需求。在适用的情况下,优化操作顺序。延迟评估和优化是通过递归模板和模板元编程实现的。

这意味着您可以编写如下操作

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 根据犰狳决定的操作自动生成内核的可能性可能,但我看不出有什么方法可以直接做到这一点。

有什么建议吗?

你可能想看看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库的开发人员之一。

示例中的操作可以使用最近添加的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()只能用于单设备上下文。