我正在尝试使用ViennaCL库在OpenCL上创建一个简单的矩阵向量产品。
这是我的主要内容:
#include "viennacl/scalar.hpp"
#include "viennacl/vector.hpp"
#include "viennacl/matrix.hpp"
#include "viennacl/linalg/prod.hpp"
#include "viennacl/matrix_proxy.hpp"
#include "viennacl/linalg/lu.hpp"
int main()
{
viennacl::ocl::set_context_device_type(0, viennacl::ocl::gpu_tag());
std::vector<viennacl::ocl::device> devices = viennacl::ocl::current_context().devices();
viennacl::ocl::current_context().switch_device(devices[0]);
int Nx=10;
int Ny=10;
//GPU vectors
viennacl::matrix<float> vcl_A(Nx,Ny);
viennacl::vector<float> vcl_b(Ny);
viennacl::vector<float> vcl_c(Nx);
//CPU vectors
std::vector<float> stl_A(Nx*Ny);
std::vector<float> stl_b(Ny);
std::vector<float> stl_c(Nx);
//filling CPU vectors
for (unsigned int i = 0; i < Nx; ++i)
for (unsigned int j = 0; j < Ny; ++j)
stl_A[i*Ny + j] = (float) (rand()%100);
for (unsigned int i = 0; i < stl_b.size(); ++i)
stl_b[i] = (float) (rand()%100);
//copying input data to GPU
viennacl::fast_copy(&(stl_A[0]),
&(stl_A[0]) + stl_A.size(),
vcl_A);
viennacl::fast_copy(stl_b, vcl_b);
//launching product c = A*b
vcl_c = viennacl::linalg::prod(vcl_A, vcl_b);
//copying output data back to CPU
viennacl::copy(vcl_c, stl_c);
viennacl::backend::finish();
}
之后,我的stl_c向量的第一个系数被正确计算,但每9个其他系数为0
。
当我将维度更改为更高的值时,我在向量的开始处获得了多个右对数,但是对于其他每个系数我仍然得到一堆零。
我猜测我的一些副本是以错误的方式完成的,但也许我的prod操作是有原因的(local / globalsize问题,但我认为ViennaCL负责这一切)
我对自己做错了什么的想法?任何帮助或建议都将非常感激。
(我在VS 2012上运行代码,我的GPU是NVIDIA Geforce gtx 670)
答案 0 :(得分:1)
<强> 1。问题:
页面viennacl::matrix
中manual-types-matrix
的文档声明:
matrix<>
的内部存储器缓冲区默认用零填充,以便内部矩阵大小为例如两个人的力量。 在矩阵上使用fast_copy()
时,需要正确考虑填充的零。查询internal_size1()
和internal_size2()
即可。
这意味着viennacl::matrix
的元素不是连续的,与用于模拟矩阵的std::vector
中的元素相反。因此,这一行不符合您的期望:
viennacl::fast_copy(&(stl_A[0]), &(stl_A[0]) + stl_A.size(), vcl_A);
<强> 2。解决方案:
那么,如何正确地将主机矩阵复制到ViennaCL矩阵?
一种可能性是使用std::vector<std::vector<float>>
来表示主机矩阵,然后使用viennacl::copy
而不是vienna::fast_copy
,并且将为您处理元素的填充。
std::vector<std::vector<float>> stl_A(Ny);
for (unsigned int i = 0; i < Ny; ++i) {
stl_A[i].resize(Nx);
for (unsigned int j = 0; j < Nx; ++j)
stl_A[i][j] = (float)(rand() % 100);
}
viennacl::copy(stl_A, vcl_A);
正如文档中所建议的,另一种可能性是使用viennacl::matrix
代替internal_size
和Nx
来匹配主机矩阵中Ny
的内部布局计算元素偏移量(但不迭代它们)时。
std::vector<float> stl_A(vcl_A.internal_size());
for (unsigned int i = 0; i < Ny; ++i)
for (unsigned int j = 0; j < Nx; ++j)
stl_A[i*vcl_A.internal_size2() + j] = (float)(rand() % 100);
viennacl::fast_copy(&(stl_A[0]), &(stl_A[0]) + stl_A.size(), vcl_A);
第3。说明:
上面提供的两个代码示例都适用于 row-major 矩阵。对于列主要矩阵,交换循环并改为使用internal_size1()
。