ERROR: SYCL kernel cannot call through a function pointer, DPCPP, TBB
ERROR: SYCL kernel cannot call through a function pointer, DPCPP, TBB
我尝试定义一个函数数组并传递给地图,我将其定义为 class,然后如果我的设备是 CPU,则我的每个函数的执行都在vector 通过 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
你不能。引用 SYCL 2020 规范:
SYCL device code, as defined by this specification, does not support
virtual function calls, function pointers in general, exceptions,
runtime type information or the full set of C++ libraries that may
depend on these features or on features of a particular host compiler.
你不应该忘记你的目标是各种设备,每个设备都执行自己的功能版本。
首先,使用函数指针是没有意义的,因为它只有一个值,它不能代表同一函数的 CPU 和 GPU 版本。
其次,如果您使用的函数不是 consteval 来获取您的函数指针,并且您使用的编程模型不需要将您的函数声明为内核(如 CUDA) ,那么我看不出编译器如何确定为您的不同设备编译哪些函数。
我尝试定义一个函数数组并传递给地图,我将其定义为 class,然后如果我的设备是 CPU,则我的每个函数的执行都在vector 通过 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
你不能。引用 SYCL 2020 规范:
SYCL device code, as defined by this specification, does not support virtual function calls, function pointers in general, exceptions, runtime type information or the full set of C++ libraries that may depend on these features or on features of a particular host compiler.
你不应该忘记你的目标是各种设备,每个设备都执行自己的功能版本。
首先,使用函数指针是没有意义的,因为它只有一个值,它不能代表同一函数的 CPU 和 GPU 版本。
其次,如果您使用的函数不是 consteval 来获取您的函数指针,并且您使用的编程模型不需要将您的函数声明为内核(如 CUDA) ,那么我看不出编译器如何确定为您的不同设备编译哪些函数。