ОШИБКА: неявный захват this недопустим для функций ядра, SYCL, DPCPP
Я пытаюсь написать своего рода класс «карты», который обертывает вызовы OneAPI, скрывая проблемы с аппаратным нацеливанием, с помощью некоторого параметра, указывающего тип цели (ЦП или графический процессор / ускоритель). Карта направляет код в ядро SYCL или в TBB для реализации операции сопоставления через параллельный для. Он принимает в качестве параметров тип устройства, CPU или GPU, а также функцию и применяется ко всем элементам в коллекции. Но в функции ядра у меня есть ошибка, неявный захват которой недопустим. Я не могу понять, в чем моя ошибка. это мой код:
#include <CL/sycl.hpp>
#include <iostream>
#include <tbb/tbb.h>
#include <tbb/parallel_for.h>
#include <vector>
#include <string>
#include <queue>
#include <CL/sycl/handler.hpp>
using namespace std;
using namespace cl::sycl;
using namespace tbb;
template<typename Tin, typename Tout>
class Map {
private:
function<Tout(Tin)> fun;
//cl::sycl::device device_type;
public:
Map() {}
Map(function<Tout(Tin)> f):fun(f) {}
//Map(cl::sycl::device d): device_type(d){}
cl::sycl::device device_type;
void f(function<Tout(Tin)> ff) {
fun = ff;
}
void d(cl::sycl::device dd){
device_type = dd;
}
vector<Tout> operator()(vector<Tin>& v) {
cl::sycl::device my_dev = cl::sycl::device(device_type.get());
//my_dev->is_cpu()
if(my_dev.is_cpu()) {
vector<Tout> r(0);
tbb::parallel_for(tbb::blocked_range<Tin>(0, v.size()), [&](Tin &t) {
r.push_back(fun(t));
});
return r;
}
if(my_dev.is_gpu()) {
//
vector<Tout> r(v.size());
cl::sycl::queue gpuQueue{cl::sycl::device(cl::sycl::gpu_selector())};
//sycl::range<1> n_item{v.size()};
//cl::sycl::buffer<Tin, 1> in_buffer(&v[0], range<1>(v.size()));
cl::sycl::buffer<Tin, 1> in_buffer(&v[0], range<1>(v.size()));
cl::sycl::buffer<Tout, 1> out_buffer(&r[0], range<1>(v.size()));
gpuQueue.submit([&](sycl::handler &h){
constexpr auto sycl_read = cl::sycl::access::mode::read;
constexpr auto sycl_write = cl::sycl::access::mode::write;
auto in_accessor = in_buffer.template get_access<sycl_read>(h);
auto out_accessor = out_buffer.template get_access<sycl_write>(h);
h.parallel_for(range<1>(v.size()), [=](id<1> index) {
out_accessor[index]= fun(in_accessor[index]);
}
);
});
return r;
}
}
};
int main() {
cout << "success\n";
vector<int> v = {1,2,3,4,5,6,7,8};
auto f = [](int x){return (++x);};
sycl::device dev = sycl::cpu_selector().select_device();
Map <int,int> m(f);
m.device_type = dev;
auto r = m(v);
for(auto &e:r) {
cout << e << "\n";
}
return 0;
}
Когда я проверяю Проблемы в консоли Eclipse, он показывает мне эти три ошибки:
1- неявный захват 'this' не разрешен для функций ядра
2- make: *** [subdir.mk:20: main.o] Ошибка 13- нет функции сопоставления для вызова объекта типа 'const (lambda at ../main.cpp:37:60)'
1 ответ
Вы пытаетесь получить доступ
Однако, даже если бы вы выполняли захват в своем ядре, это не сработало бы, потому что
Одно очень простое решение для этого обычно - просто использовать локальные копии в вашем ядре:
class X {
void run(sycl::queue& q){
q.submit([&](sycl::handler& cgh){
int local_var = var; // Note: This can also be expressed using the lambda capture list
cgh.parallel_for(..., [=](...){ /* use local_var here*/});
});
}
int var;
};
Начиная с C++ 17, вы также можете просто скопировать класс:
Более фундаментальная проблема с вашим кодом заключается в том, что спецификация SYCL не позволяет использовать внутренний код устройства. В некоторых случаях и для некоторых реализаций SYCL это может работать (например, для серверных модулей хоста), но это расширение. Проблема в том, что реализация обычно использует механизмы, которые не могут поддерживаться устройством для стирания типов, такие как динамический полиморфизм.
Одним из решений может быть включение типа функции в аргументы шаблона класса вместо использования