Как определить и выполнить массив функций на Sycl OpenCL DPCPP

# #opencl #sycl #dpc

Вопрос:

В своей программе я определил массив функций

     #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>amp; 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()),
                        [amp;](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(amp;v[0], n_item);
                sycl::buffer<Tout, 1> out_buffer(amp;r[0], n_item);
                gpuQueue.submit([amp;](sycl::handleramp; 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};
    //auto f = [](int x){return (  x);};
    //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]);

    //auto m1 = make_map<int, int>(f);
    std::vector<int> r = m1(true, v);
    //print the result
    for(auto amp;e:r) {
        std::cout << e << " ";
        }
    }


  return 0;
}
 

вместо того, чтобы каждый раз определять функцию, я заинтересован в определении массива функций, а затем в их выполнении в своей программе. Но в части SYCL для выполнения на GPU у меня есть ошибка, и я не знаю, как ее исправить.

ОШИБКА: ядро SYCL не может вызвать через указатель функции

Комментарии:

1. По описываемому вами инструменту не так много документации, но я бы рекомендовал ознакомиться с документацией. Я думаю, что если у вас возникнут проблемы с использованием инструмента, вам следует поднять их в репозитории проекта.

2. проблема в том, что я понятия не имею, как их использовать, и не могу найти никаких примеров. я запутался и застрял в этой части

Ответ №1:

В частности, код устройства SYCL, определенный этой спецификацией, не поддерживает вызовы виртуальных функций, указатели функций в целом, исключения, информацию о типе среды выполнения или полный набор библиотек C , которые могут зависеть от этих функций или функций конкретного хост-компилятора. Тем не менее, эти основные ограничения могут быть устранены некоторыми конкретными расширениями Хроноса или поставщиков.

В соответствии со спецификацией sycl 2020, в ядре SYCL не разрешается вызывать указатели функций или любые функции, вызываемые ядром. Пожалуйста, обратитесь https://www.khronos.org/registry/SYCL/specs/sycl-2020/html/sycl-2020.html#introduction