Я немного новичок в 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::...
функции, как они кажутся более элегантными.
Если вы определите BOOST_COMPUTE_DEBUG_KERNEL_COMPILATION
Сбой макроса и сборка программы OpenCL, исходный код программы и журнал сборки будут записаны в стандартный вывод.
Вы не можете перейти по ссылке в OpenCL C, что вы пытаетесь сделать в BOOST_COMPUTE_CLOSURE
, Я понимаю, что вы хотели бы пройти __global
указатель на ваше закрытие и изменение значений переменной в глобальной памяти, а не локальной копии этого значения. Я не думаю, что это поддерживается в Boost.Compute, потому что в for_each
(и другие алгоритмы) Boost.Compute всегда передает значение вашей функции / замыканию.
Конечно, вы всегда можете реализовать обходной путь — добавить унарный &
оператор или реализовать пользовательский итератор устройства. Тем не менее, в представленном примере это просто снизит производительность, поскольку приведет к чтению и записи не слитой памяти. Если у вас очень много сложных структур (AoS), попробуйте изменить его структуру массивов (SoA) или разбить вашу структуру.
Других решений пока нет …