具有临时消除功能的 C++ OpenCL 矩阵库
C++ OpenCL matrix library with temporary elimination
犰狳矩阵库写的
Armadillo employs a delayed evaluation approach to combine several operations into one and reduce (or eliminate) the need for temporaries. Where applicable, the order of operations is optimised. Delayed evaluation and optimisation are achieved through recursive templates and template meta-programming.
这意味着你可以写这样的操作
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 决定的操作自动生成内核,但我看不出有任何方法可以直接实现。
有什么建议吗?
您可能想查看 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()
只能用于单设备上下文。
犰狳矩阵库写的
Armadillo employs a delayed evaluation approach to combine several operations into one and reduce (or eliminate) the need for temporaries. Where applicable, the order of operations is optimised. Delayed evaluation and optimisation are achieved through recursive templates and template meta-programming.
这意味着你可以写这样的操作
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 决定的操作自动生成内核,但我看不出有任何方法可以直接实现。
有什么建议吗?
您可能想查看 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()
只能用于单设备上下文。