0

我正在尝试使用 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. 当我将尺寸更改为较高的值时,我在向量的开头得到了多个正确的 coef,但对于每个其他的 coef,我仍然得到一堆零。

我猜我的一些副本是以错误的方式完成的,但也许我的 prod 操作是有原因的(本地/全局大小问题,但我认为 ViennaCL 会处理这一切)

知道我做错了什么吗?任何帮助或建议将不胜感激。

(我在 VS 2012 上运行代码,我的 GPU 是 NVIDIA Geforce gtx 670)

4

1 回答 1

2

1.问题:

viennacl::matrix页面中的文档manual-types-matrix指出:

默认情况下,a 的内部存储器缓冲区matrix<>用零填充,以便内部矩阵大小是例如 2 的幂的倍数。在矩阵上使用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 矩阵?

一种可能是使用 astd::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主机矩阵中 a 的内部布局,方法是在计算元素偏移量时使用internal_size代替NxNy(但不迭代它们)。

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、注意事项:

上面提供的两个代码示例都适用于优先矩阵。对于列主矩阵,交换循环并internal_size1()改用。

于 2014-11-26T18:21:20.350 回答