Существует старый способ эмулировать шаблоны на чистом языке Си.Он основан на включении одного файла несколько раз (без включения защиты).Так как 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);