ViennaCL: матрично-векторное произведение дает сбой

0

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

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

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

(Я запускаю код на VS 2012, мой GPU - NVIDIA Geforce gtx 670)

Теги:
opencl
viennacl

1 ответ

1
Лучший ответ

1. Проблема:

Документация для viennacl::matrix в 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
    Я полностью пропустил ту часть о заполнении нулями ... большое спасибо за этот ясный и полный ответ! Теперь работает нормально.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню