Здравствуйте, watch-maker, Вы писали:
_>>Вся проблема, в том как ефективно реализовать эту функцию.
__global__ void fn1_kernel ( float * result_array ) { value = fn1( x, y ); }
__global__ void fn2_kernel ( float * result_array ) { value = fn2( x, y ); }
....
__global__ void fnN_kernel ( float * result_array ) { value = fnN( x, y ); }
Пользователю позволить выбирать fn1 .. fnN
А так просто делаешь обычный компилятор для стековой машины (
можешь глянуть книжку)
которая будет тебе генерить c-код для компилятора cudы
парсишь функцию и строишь граф вычислений. оптимизируешь граф (разные тождественные преобразования). генериш код по графу.
потом его в тихоря компилишь и загружаешь на исполнение.
на скорую руку для опытов, без оптимизации можно что-нибудь типа такого запилить
struct Compiler {
Cgen cgen;
Parser p;
void compile() {
compile_expression();
}
void compile_expression() {
cgen.write("__global__ void expr_kernel ... {\n");
r=0;
int r1=L1();
cgen.write("value=r%d;\n",r1);
cgen.write("}\n");
}
int r; int allocReg(){ return ++r; }
int L1() {
int r1=L2();
switch(p.get()) {
case '+': { int r3=allocReg(); int r2=L2(); cgen.write("r%d=r%d + r%d;\n",r3,r1,r2); return r3; }
case '-': { int r3=allocReg(); int r2=L2(); cgen.write("r%d=r%d - r%d;\n",r3,r1,r2); return r3; }
...
}
return r1;
}
int L2() {
int r1=L3();
switch(p.get()) {
case '*': { int r3=allocReg(); int r2=L2(); cgen.write("r%d=r%d * r%d;\n",r3,r1,r2); return r3; }
case '/': { int r3=allocReg(); int r2=L2(); cgen.write("r%d=r%d / r%d;\n",r3,r1,r2); return r3; }
...
}
return r1;
}
...
int L5() {
if (p.check('(')) {
int r1=L1();
if (!p.check(')')) throw_error("no closing )");
return r1;
}
return L6();
}
int L6() { // digits, consts, variables, functions
int sign=+1;
if (p.check('-')) sign=-1;
int digit=p.getDigit();
if (sign<0) digit=-digit;
int r1=allocReg();
cgen.write("r%d=%d;\n",r1,digit);
return r1;
}
}
единственно что у куды набор регистров ограничен и придётся оптимизировать, хотя если повезёт их компилятор выполнит эту работу за тебя.
но лучше почитай книжку.
_>>А использование интерпретатора, заметно снижает производительность, что воопще ставит под сомнение целесообразность использовать CUDA...
а нафига интерпритатор на куде? интерприти на пц и заливай в кодовские ядра готовый код.
WM>Если код может быть эффективно распараллелен, то CUDA позволяет его значительно ускорить. При этом будет ускоряться как изначально медленный, так и изначально быстрый код.
WM>Просто иногда дешевле переписать исходный код. А иногда дешевле запустить медленный код на GPU. А вот одновременно оптимизировать код и переписывать его на CUDA нужно реже. Хотя, конечно, выигрыш в производительности в последнем случае получается самым большим, с этим не поспоришь.
грамотно распараллелить это искусство. так что пиши в ручную.