Я пытаюсь написать функцию сокращения в cuda (это упражнение, я знаю, что я делаю то, что было сделано другими людьми), которое принимает двоичный ассоциативный оператор и массив и уменьшает массив с помощью оператора.function as templated parameter in cuda
У меня возникли трудности с передачей функции. Я написал hostOp() как пример на основе узла, который отлично работает.
deviceOp() работает для первого оператора с явным вызовом функции fminf(), но когда я вызываю параметр функции, возникает ошибка доступа к недопустимой памяти.
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std; //for brevity
__device__ float g_d_a = 9, g_d_b = 5;
float g_h_a = 9, g_h_b = 5;
template<typename argT, typename funcT>
__global__
void deviceOp(funcT op){
argT result = fminf(g_d_a, g_d_b); //works fine
printf("static function result: %f\n", result);
result = op(g_d_a,g_d_b); //illegal memory access
printf("template function result: %f\n", result);
}
template<typename argT, typename funcT>
void hostOp(funcT op){
argT result = op(g_h_a, g_h_b);
printf("template function result: %f\n", result);
}
int main(int argc, char* argv[]){
hostOp<float>(min<float>); //works fine
deviceOp<float><<<1,1>>>(fminf);
cudaDeviceSynchronize();
cout<<cudaGetErrorString(cudaGetLastError())<<endl;
}
ВЫВОД:
host function result: 5.000000
static function result: 5.000000
an illegal memory access was encountered
Предполагая, что я не делаю что-то ужасно глупое, как я проходил мимо fminf в deviceOp так, что не является незаконным доступом к памяти?
Если я делаю что-то ужасно глупое, что лучше?
Hm. Поэтому, когда я вызываю deviceOp с хоста, он вызывается как код устройства, но если бы я должен был вызывать его с устройства, это был бы код устройства (и знал бы, где fminf, как он это делает?) –
'deviceOp' is функция '__global__'. Он фактически не вызывается с хоста (в том виде, как обычная хост-функция вызывается из кода хоста), но на самом деле это запуск ядра (который выполняется через последовательность вызовов библиотеки - для запуска функции на устройстве). Если вы запустили 'deviceOp' из кода устройства (т. Е. Динамический параллелизм, то тот конкретный запуск ядра из кода устройства мог бы напрямую забрать адрес функции fminf устройства, и фактически сам запуск ядра был бы скомпилирован как код устройства. –
Прямой вызов 'fminf', явный в' deviceOp', на самом деле является кодом устройства. Все, что входит в квалификационные рамки функции __global__ или '__device__', является кодом устройства и скомпилировано компилятором кода устройства. Но ** запуск ** 'deviceOp' из вашей' основной' процедуры - это фактически весь код хоста. –