2014-11-26 2 views
0

Я пытаюсь сделать простой вектор-матричный продукт с OpenCL, используя библиотеку ViennaCL.ViennaCL: матрично-векторный продукт не работает

Вот мое главное:

#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 других coefs являются 0. Когда я изменяю размеры до верхних значений, я получаю больше одного правого коэффа в начале моего вектора, но я все еще получаю кучу нулей для всех других коэффиков.

Я предполагаю, что некоторые из моих копий сделали неправильный путь, но, может быть, моя операция прода в причинах (местном выпуске/globalsize, но я полагаю, ViennaCL заботится обо всем этом)

Любой идея о том, что я делаю не так? Любая помощь или совет будут действительно оценены.

(Я бегу код на VS 2012, мой GPU является NVIDIA GeForce GTX 670)

ответ

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. Примечание:

Оба примера кода, приведенные выше, являются для ряда -мажорной матриц. Для матриц с столбцом-основными, замените петли и вместо этого используйте internal_size1().

+0

Я полностью пропустил эту часть о нулевой прокладке ... Большое спасибо за этот ясный и полный ответ! Теперь он отлично работает. – eyam