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

Я пытаюсь сделать простой матрично-векторный продукт с 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, мой графический процессор — NVIDIA Geforce GTX 670)

0

Решение

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() вместо.

1

Другие решения


По вопросам рекламы [email protected]