tbb - 错误 : implicit capture of 'this' is not allowed for kernel functions, SYCL、DPCPP

标签 tbb sycl intel-oneapi dpc++

我尝试编写一种“映射”类,该类包装 OneAPI 调用,通过指定目标类型(CPU 或 GPU/加速器)的某些参数隐藏硬件目标问题。 映射,将代码引导到SYCL内核或TBB,通过并行for实现映射操作。 它以设备类型、CPU 或 GPU 以及函数作为参数,并应用于集合中的所有项目。 但是在内核函数中,我有一个错误,不允许隐式捕获。我不明白我的错误是什么。 这是我的代码:

    #include <CL/sycl.hpp>
    #include <iostream>
    #include <tbb/tbb.h>
    #include <tbb/parallel_for.h>
    #include <vector>
    #include <string>
    #include <queue>
    #include<tbb/blocked_range.h>
    #include <tbb/global_control.h>
    
    using namespace std;
    using namespace cl::sycl;
    using namespace tbb;
    
    template<typename Tin, typename Tout>
    class Map {
    private:
        function<Tout(Tin)> fun;
        string device_type;
    public:
        Map() {}
        Map(function<Tout(Tin)> f):fun(f) {}
        void f(function<Tout(Tin)> ff) {
            fun = ff;
           }
        void set_device(string dev) {
                device_type = dev;
            }
    
    
        vector<Tout> operator()(vector<Tin>& v) {
            device *my_dev = new device();
            if(device_type == "cpu"){
                if(my_dev->is_cpu()) {
                    vector<Tout> r(0);
                    tbb::parallel_for(tbb::blocked_range<Tin>(0, v.size()),
                            [&](tbb::blocked_range<Tin> t) {
                        for (int index = t.begin(); index < t.end(); ++index){
                            r[index] = fun(v[index]);
                        }
                });
               return r;
             }
            }else if(device_type == "gpu"){
                if(my_dev->is_gpu()) {
                    vector<Tout> r(v.size());
                    sycl::queue gpuQueue{gpu_selector()};
                    sycl::range<1> n_item{v.size()};
                    sycl::buffer<Tin, 1> in_buffer(&v[0], n_item);
                    sycl::buffer<Tout, 1> out_buffer(&r[0], n_item);
                    gpuQueue.submit([&](sycl::handler& h){
                         //local copy of fun                        
                        //auto f = fun;
                        sycl::accessor in_accessor(in_buffer, h, sycl::read_only);
                        sycl::accessor out_accessor(out_buffer, h, sycl::write_only);
                        h.parallel_for(n_item, [=](sycl::id<1> index) {
                            out_accessor[index] = fun(in_accessor[index]);
                        });
                    }).wait();
                    return r;
                }
    
            }
        }
    
    };
    
    int main(int argc, char *argv[]) {
    
    
        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();
        string dev_type = argv[1];
        Map <int,int> m(f);
        m.set_device(dev_type);
        auto r = m(v);
        for(auto &e:r) {
            cout << e << "\n";
        }
    
      return 0;
    }

当我检查 Eclipse 控制台中的问题时,它显示了此错误:

1- 内核函数不允许隐式捕获“this”

最佳答案

您正在尝试访问内核中的fun,它是Map 的成员变量。在 C++ 中使用 this 指针访问成员变量。在 C++ 中,Lambda 函数默认不捕获 this 指针,因此会出现错误消息。

但是,即使您要在内核中捕获this,它也不起作用,因为this将指向通常在设备上无法访问的主机内存。

解决这个问题的一个非常简单的方法通常是在内核中使用本地副本:

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 开始,您还可以通过复制捕获类:[*this](...){...}

您的代码更根本的问题是 SYCL 规范不允许在设备代码内使用 std::function 。在某些情况下,对于某些 SYCL 实现,它可能有效(例如,对于主机后端),但这是一个扩展。问题在于 std::function 的实现通常使用设备上不支持的机制来进行类型删除,例如动态多态性。

一种解决方案可能是在类模板参数中包含函数的类型,而不是使用 std::function

关于tbb - 错误 : implicit capture of 'this' is not allowed for kernel functions, SYCL、DPCPP,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67349424/

相关文章:

c++ - 缓冲区内的 SYCL 缓冲区

c++ - 使用 2D std::vector 对 SYCL 进行矩阵乘法

c++ - 在 TBB 中使用递归、基于任务的并行编程获得不同的输出?

c++ - Intel TBB 并行化开销

c++ - 关于TBB/C++代码的一个问题

c++ - 我怎样才能创建一个可定制的仿函数接受 sycl 内核?

opencv - TBB parallel_for,线程数更少

c++ - 在抛出 'cl::sycl::detail::exception_implementation<(cl::sycl::detail::exception_types)9>' 实例后调用终止

c++ - Intel one-api 编译器在编译 GDAL cpp 文件时出错

ccl - CCL 代码示例中的缓冲区以及 oneapi 工具包