C++ VexCL中的稠密矩阵向量乘法
VexCL似乎是一个非常有吸引力的gpu编程库 不幸的是,这是一个非常年轻的图书馆,那里几乎没有什么信息。 我一直在寻找如何执行矩阵向量乘法,但我找到的唯一矩阵表示形式是vex::SpMat,它包含一个稀疏矩阵 如果矩阵是稠密的,那么稀疏表示的计算效率通常较低 我所有的矩阵都很密集,我想知道如何在VexCL中高效地执行此操作。我是库的开发人员 我必须承认密集线性代数运算不在我的优先考虑范围之内。我相信,要以一种能够在VexCL(即OpenCL/CUDA)支持的各种设备上实现性能可移植的方式实现这些功能是非常困难的。这项任务最好由供应商BLAS实现(但欢迎使用补丁!) 您可能还想看看opensource库,它提供了密集的矩阵操作,并支持OpenCL、CUDA和OpenMP后端。它们的特性使它们能够获得接近供应商优化的库的可移植性能 话虽如此,对于VexCL中的稠密矩阵-向量积,您有两个选项(除了提供自定义内核之外)。首先,您可以使用基于矩阵向量积定义的直接实现:C++ VexCL中的稠密矩阵向量乘法,c++,opencl,gpgpu,vexcl,C++,Opencl,Gpgpu,Vexcl,VexCL似乎是一个非常有吸引力的gpu编程库 不幸的是,这是一个非常年轻的图书馆,那里几乎没有什么信息。 我一直在寻找如何执行矩阵向量乘法,但我找到的唯一矩阵表示形式是vex::SpMat,它包含一个稀疏矩阵 如果矩阵是稠密的,那么稀疏表示的计算效率通常较低 我所有的矩阵都很密集,我想知道如何在VexCL中高效地执行此操作。我是库的开发人员 我必须承认密集线性代数运算不在我的优先考虑范围之内。我相信,要以一种能够在VexCL(即OpenCL/CUDA)支持的各种设备上实现性能可移植的方式实现这
using namespace vex;
Context ctx(Filter::Env && Filter::Count(1));
// The n x m matrix stored row-wise.
vector<double> A(ctx, n * m);
// The LHS and RHS vectors.
vector<double> x(ctx, m);
vector<double> y(ctx, n);
// Make an n x m matrix from vector x by replicating it along the first
// dimension (reshape), multiply it elementwise by A, and reduce the result
// along the second dimension.
// In other words, y_i = sum_j (A_ij * x_j)
y = reduce<SUM>(
extents[n][m], // Shape of the expression to reduce,
A * reshape(
x,
extents[n][m], // (We need an n x m matrix...
extents[1] // ... but we only have vector of size m).
), // the expression,
1 // and the dimension to reduce along.
);
第一种方法应该不如调用cuBLAS有效。它的优点是reduce()
调用的结果是一个向量表达式,原则上可以将其中的几个组合到一个融合的计算内核中。例如,您可以在单个内核调用中计算Ax+By
,或sin(Ax)+cos(By)
,或(A+B)(x-y)
,或任何其他向量表达式:
z = prod(n, m, A, x) + prod(n, m, B, y);
z = sin(prod(n, m, A, x)) + cos(prod(n, m, B, y));
z = prod(n, m, A + B, x - y);
这可能比几个链接的cuBLAS调用更有效。由于这一点,我发现VexCL的表现比cuBLAS好1.5倍。谢谢您的回答!我写了一个内核来实现它们之间的乘法,但是我不擅长创建一个好的接口来使用它。我将比较所提出方法的速度和它们的可用性,然后选择一种。再次,非常感谢!
double one = 1;
double zero = 0;
cublasDgemv(
cublas_handle, CUBPLAS_OP_N, n, m,
&zero,
A(0).raw_ptr(), m,
x(0).raw_ptr(), 1
&one,
y(0).raw_ptr(), 1
);
z = prod(n, m, A, x) + prod(n, m, B, y);
z = sin(prod(n, m, A, x)) + cos(prod(n, m, B, y));
z = prod(n, m, A + B, x - y);