Передать вектор пользовательских структур по ссылке на boost :: compute closure или функцию

Я немного новичок в opencl и пытаюсь научиться правильно использовать boost :: compute. Рассмотрим следующий код:

#include <iostream>
#include <vector>
#include <boost/compute.hpp>

const cl_int cell_U_size{ 4 };

#pragma pack (push,1)
struct Cell
{
cl_double U[cell_U_size];
};
#pragma pack (pop)

BOOST_COMPUTE_ADAPT_STRUCT(Cell, Cell, (U));

int main(int argc, char* argv[])
{
using namespace boost;
auto device = compute::system::default_device();
auto context = compute::context(device);
auto queue = compute::command_queue(context, device);

std::vector<Cell> host_Cells;
host_Cells.reserve(10);
for (auto j = 0; j < host_Cells.capacity(); ++j) {
host_Cells.emplace_back(Cell());
for (auto i = 0; i < cell_U_size; ++i) {
host_Cells.back().U[i] = static_cast<cl_double>(i+j);
}
}
std::cout << "Before:\n";
for (auto const& hc : host_Cells) {
for (auto const& u : hc.U)
std::cout << " " << u;
std::cout << "\n";
}
compute::vector<Cell> device_Cells(host_Cells.size(), context);
auto f = compute::copy_async(host_Cells.begin(), host_Cells.end(), device_Cells.begin(), queue);
try {
BOOST_COMPUTE_CLOSURE(Cell, Step1, (Cell cell), (cell_U_size), {
for (int i = 0; i < cell_U_size; ++i) {
cell.U[i] += 1.0;
}
return cell;
});
f.wait(); // Wait for data to finish being copied
compute::transform(device_Cells.begin(), device_Cells.end(), device_Cells.begin(), Step1, queue);

//BOOST_COMPUTE_CLOSURE(void, Step2, (Cell &cell), (cell_U_size), {
//  for (int i = 0; i < cell_U_size; ++i) {
//      cell.U[i] += 1.0;
//  }
//});
//compute::for_each(device_Cells.begin(), device_Cells.end(), Step2, queue);

compute::copy(device_Cells.begin(), device_Cells.end(), host_Cells.begin(), queue);
}
catch (std::exception &e) {
std::cout << e.what() << std::endl;
throw;
}
std::cout << "After:\n";
for (auto const& hc : host_Cells) {
for (auto const& u : hc.U)
std::cout << " " << u;
std::cout << "\n";
}
}

У меня есть вектор пользовательских структур (на самом деле гораздо более сложных, чем показано здесь), которые я хочу обрабатывать на GPU. В без комментариев BOOST_COMPUTE_CLOSURE compute::transform передает структуры по значению, обрабатывает их и затем копирует обратно.

Я хотел бы передать их по ссылке, как показано в закомментированном BOOST_COMPUTE_CLOSURE с compute::for_each, но ядро ​​не компилируется (Build Program Failure) когда программа запущена, и я не нашел никакой документации, в которой упоминалось бы, как этого достичь.

Я знаю, что могу добиться передачи по ссылке (на самом деле это указатели, поскольку это C99), используя BOOST_COMPUTE_STRINGIZE_SOURCE и передать указатель на весь вектор структур, но я хотел бы использовать compute::... функции, как они кажутся более элегантными.

0

Решение

Если вы определите BOOST_COMPUTE_DEBUG_KERNEL_COMPILATION Сбой макроса и сборка программы OpenCL, исходный код программы и журнал сборки будут записаны в стандартный вывод.

Вы не можете перейти по ссылке в OpenCL C, что вы пытаетесь сделать в BOOST_COMPUTE_CLOSURE, Я понимаю, что вы хотели бы пройти __global указатель на ваше закрытие и изменение значений переменной в глобальной памяти, а не локальной копии этого значения. Я не думаю, что это поддерживается в Boost.Compute, потому что в for_each (и другие алгоритмы) Boost.Compute всегда передает значение вашей функции / замыканию.

Конечно, вы всегда можете реализовать обходной путь — добавить унарный & оператор или реализовать пользовательский итератор устройства. Тем не менее, в представленном примере это просто снизит производительность, поскольку приведет к чтению и записи не слитой памяти. Если у вас очень много сложных структур (AoS), попробуйте изменить его структуру массивов (SoA) или разбить вашу структуру.

1

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

Других решений пока нет …

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