【问题标题】:ERROR: SYCL kernel cannot call through a function pointer, DPCPP, TBB错误:SYCL 内核无法通过函数指针、DPCPP、TBB 调用
【发布时间】:2021-05-10 15:55:47
【问题描述】:

我尝试定义一个函数数组并将其传递给我定义为一个类的映射,然后如果我的设备是 CPU,则我的每个函数在向量上的执行都通过 CPU,如果不是,则通过通过 SYCL 部分并在 GPU 上执行。 同时,我想测量我的代码的性能,用 TBB 库在 CPU 上执行我的代码的性能。 问题是,当我编译我的程序时,它显示了这个错误,我不知道如何修复它。 我应该指出,在定义函数数组之前,在 SYCL 部分定义函数的本地副本,我的代码运行良好并且得到了结果,但是在定义函数数组之后,它出现了错误。 我的代码:

    #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>
#include <chrono>


using namespace tbb;

template<class Tin, class Tout, class Function>
class Map {
private:
    Function fun;
public:
    Map() {}
    Map(Function f):fun(f) {}


    std::vector<Tout> operator()(bool use_tbb, std::vector<Tin>& v) {
        std::vector<Tout> r(v.size());
        if(use_tbb){
            // Start measuring time
            auto begin = std::chrono::high_resolution_clock::now();
            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]);
                    }
            });
            // Stop measuring time and calculate the elapsed time
            auto end = std::chrono::high_resolution_clock::now();
            auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin);
            printf("Time measured: %.3f seconds.\n", elapsed.count() * 1e-9);
            return r;
         } else {
                sycl::queue gpuQueue{sycl::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] = f(in_accessor[index]);
                    });
                }).wait();
         }
                return r;
    }
};

template<class Tin, class Tout, class Function>
Map<Tin, Tout, Function> make_map(Function f) { return Map<Tin, Tout, Function>(f);}


typedef int(*func)(int x);
//define different functions
auto function = [](int x){ return x; };
auto functionTimesTwo = [](int x){ return (x*2); };
auto functionDivideByTwo = [](int x){ return (x/2); };
auto lambdaFunction = [](int x){return (++x);};

int main(int argc, char *argv[]) {

    std::vector<int> v = {1,2,3,4,5,6,7,8,9};

    //Array of functions
    func functions[] =
        {
            function,
            functionTimesTwo,
            functionDivideByTwo,
            lambdaFunction
        };
    for(int i = 0; i< sizeof(functions); i++){
        auto m1 = make_map<int, int>(functions[i]);
        std::vector<int> r = m1(true, v);
        //print the result
        for(auto &e:r) {
            std::cout << e << " ";
         }
    }
    

  return 0;
}

错误:

SYCL kernel cannot call through a function pointer

【问题讨论】:

    标签: c++11 tbb sycl dpc++


    【解决方案1】:

    您不应该忘记您针对的是各种设备,每个设备都执行自己的功能版本。

    首先,使用函数指针是没有意义的,因为它只有一个值,并且不能同时表示同一函数的 CPU 和 GPU 版本。

    其次,如果您使用不是 consteval 的函数来获取函数指针,并且您使用的编程模型不需要将函数声明为内核(如 CUDA),那么我不会'看不出编译器如何确定要为不同的设备编译哪些函数。

    【讨论】:

      【解决方案2】:

      你不能。引用SYCL 2020 规范:

      本规范定义的 SYCL 设备代码不支持 虚函数调用,一般的函数指针,异常, 运行时类型信息或全套 C++ 库,可能 取决于这些特性或特定宿主编译器的特性。

      【讨论】:

      • 你是对的,但是在定义函数数组之前,我有可能在设备上执行函数的本地副本,我的意思是在 SYCL 设备代码的一部分。但是在定义了一个函数数组之后,我遇到了这个错误。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-13
      • 2010-10-19
      • 2016-06-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多