Как использовать шаблоны C ++ в ядрах OpenCL? - PullRequest
13 голосов
/ 16 декабря 2010

Я новичок в OpenCL.

У меня есть алгоритм, который использует шаблоны.Он хорошо работал с распараллеливанием OpenMP, но теперь объем данных вырос, и единственный способ обработать его - переписать его для использования OpenCL.Я могу легко использовать MPI для сборки его для кластера, но Тесла-подобный графический процессор гораздо дешевле, чем кластер:)

Есть ли способ использовать шаблоны C ++ в ядре OpenCL?

Можно ликаким-то образом расширить шаблоны с помощью компилятора C ++ или какого-либо инструмента и после этого использовать так изменившуюся функцию ядра?

EDIT.Идея обходного пути заключается в том, чтобы каким-то образом сгенерировать C99-совместимый код из кода C ++ из шаблона.

Я обнаружил следующее о Comeau:

Comeau C ++ 4.3.3 - полный и верный компиляторкоторый выполняет полную проверку синтаксиса, полную семантическую проверку, полную проверку ошибок и все другие обязанности компилятора.Исходный код C ++ транслируется во внутренние деревья компилятора и таблицы символов, не похожие на C ++ или C. Кроме того, он генерирует внутреннюю проприетарную промежуточную форму.Но вместо использования проприетарного генератора внутреннего кода Comeau C ++ 4.3.3 генерирует C-код в качестве вывода.Помимо технических преимуществ C ++, генерирующие C аспекты таких продуктов, как Comeau C ++ 4.3.3, рекламировались как причина успеха C ++, поскольку его можно было перенести на большое количество платформ благодаря общедоступности компиляторов C.

Компилятор C используется только и только для получения собственной генерации кода.Это означает, что Comeau C ++ предназначен для использования с конкретными компиляторами C на каждой соответствующей платформе.Обращаем ваше внимание на то, что Comeau обязано выполнять пошив одежды.В противном случае сгенерированный код C не имеет смысла, так как он привязан к конкретной платформе (где платформа включает, по крайней мере, компилятор ЦП, ОС и C), и, кроме того, сгенерированный код C не является автономным.Следовательно, он не может быть использован сам по себе (обратите внимание, что это является и техническим, и юридическим требованием при использовании Comeau C ++), и именно поэтому обычно нет возможности увидеть сгенерированный код C: это почти всегда бесполезно и процесс компиляции, включая его генерацию, следует рассматривать как внутренние этапы перевода.

Ответы [ 6 ]

14 голосов
/ 16 июля 2013

Существует старый способ эмулировать шаблоны на чистом языке Си.Он основан на включении одного файла несколько раз (без включения защиты).Так как OpenCL имеет полнофункциональный препроцессор и позволяет включать файлы, этот прием можно использовать.

Вот хорошее объяснение: http://arnold.uthar.net/index.php?n=Work.TemplatesC

Это все еще намного сложнее, чем шаблоны C ++: код имеетбыть разделенным на несколько частей, и вы должны явно создать экземпляр каждого экземпляра шаблона.Кроме того, кажется, что вы не можете сделать некоторые полезные вещи, такие как реализация факториала как рекурсивного шаблона.

Пример кода

Давайте применим эту идею к OpenCL.Предположим, что мы хотим вычислить обратный квадратный корень с помощью итерации Ньютона-Рафсона (обычно это не очень хорошая идея).Однако тип с плавающей запятой и количество итераций могут различаться.

Прежде всего, нам нужен вспомогательный заголовок ("templates.h"):

#ifndef TEMPLATES_H_
#define TEMPLATES_H_

#define CAT(X,Y,Z) X##_##Y##_##Z   //concatenate words
#define TEMPLATE(X,Y,Z) CAT(X,Y,Z)

#endif

Затем мы пишемФункция шаблона в "NewtonRaphsonRsqrt.cl":

#include "templates.h"

real TEMPLATE(NewtonRaphsonRsqrt, real, iters) (real x, real a) {
    int i;
    for (i = 0; i<iters; i++) {
        x *= ((real)1.5 - (0.5*a)*x*x);
    }
    return x;
}

В вашем основном файле .cl создайте экземпляр этого шаблона следующим образом:

#define real float
#define iters 2
#include "NewtonRaphsonRsqrt.cl"  //defining NewtonRaphsonRsqrt_float_2

#define real double
#define iters 3
#include "NewtonRaphsonRsqrt.cl"  //defining NewtonRaphsonRsqrt_double_3

#define real double
#define iters 4
#include "NewtonRaphsonRsqrt.cl"  //defining NewtonRaphsonRsqrt_double_4

И затем можете использовать его следующим образом:

double prec = TEMPLATE(NewtonRaphsonRsqrt, double, 4) (1.5, 0.5);
float approx = TEMPLATE(NewtonRaphsonRsqrt, float, 2) (1.5, 0.5);
5 голосов
/ 01 января 2014

Я написал экспериментальный инструмент преобразования исходного кода C ++ в OpenCL. Инструмент компилирует исходный код C ++ (даже некоторые STL) в байт-код LLVM и использует модифицированную версию бэкэнда LLVM 'C' для дизассемблирования байт-кода в OpenCL 'C'.

Пожалуйста, смотрите http://dimitri -christodoulou.blogspot.com / 2013/12 / writing-opencl-kernels-in-c.html

Например, этот код с использованием std :: enable_if в C ++ 11 можно преобразовать в OpenCL 'C' и затем выполнить на GPU:

#include <type_traits>

template<class T>
T foo(T t, typename std::enable_if<std::is_integral<T>::value >::type* = 0)
{
    return 1;
}

template<class T>
T foo(T t, typename std::enable_if<std::is_floating_point<T>::value >::type* = 0)
{
    return 0;
}

extern "C" void _Kernel_enable_if_int_argument(int* arg0, int* out)
{
    out[0] = foo(arg0[0]);
}
3 голосов
/ 28 июня 2013

Вы можете взглянуть на VexCL , который использует шаблоны выражений для генерации ядер OpenCL.Вы можете получить некоторые идеи о том, как заставить OpenCL хорошо работать с шаблонами.

Другая активно работающая библиотека - это Boost.Compute , который является слоем поверх OpenCL, чтобы позволитьуниверсальный код C ++.

Общая идея состоит в том, чтобы более или менее создать ядро ​​в виде строки C и передать ее в среду выполнения OpenCL для компиляции и выполнения.

2 голосов
/ 18 декабря 2010

Если вы действительно полны решимости добиться этого, вы можете перенаправить свой компилятор C ++ по своему выбору для генерации NVidia PTX (и Clang, скорее всего, сможет это сделать в ближайшее время).Но таким образом вы привязали бы свой код к аппаратному обеспечению NVidia.

Другой способ - реализовать пользовательский бэкэнд для LLVM на основе текущего CBE, который будет генерировать чистый код OpenCL вместо C.

0 голосов
/ 19 октября 2017

Обратите внимание, что новый стандарт SYCL Khronos имеет встроенную поддержку шаблонов C ++ в OpenCL.

0 голосов
/ 07 мая 2011

PyOpenCL теперь использует Mako в качестве движка шаблонов.http://www.makotemplates.org/

...