2015-12-21 9 views
1

Я пытаюсь понять, как использовать Cuda в Java. Я использую jCuda.Не могу понять, как работает jCuda cuLaunchKernel?

Все было прекрасно, пока я не наткнулся на пример, содержащий код:

// Set up the kernel parameters: A pointer to an array 
    // of pointers which point to the actual values. 
    Pointer kernelParameters = Pointer.to(
     Pointer.to(new int[]{numElements}), 
     Pointer.to(deviceInputA), 
     Pointer.to(deviceInputB), 
     Pointer.to(deviceOutput) 
    ); 

Кернфункция прототип:

__global__ void add(int n, float *a, float *b, float *sum) 

Вопрос заключается в том: С точки зрения с, делает не похоже, что мы что-то передаем?

(***n, ***a, ***b, ***sum) 

Так в основном, мы всегда должны иметь:

Pointer kernelParameters = Pointer.to(double pointer, double pointer, ...)??? 

Спасибо

ответ

3

cuLaunchKernel function of JCuda соответствует cuLaunchKernel function of CUDA. Сигнатура этой функции CUDA является

CUresult cuLaunchKernel(
    CUfunction f, 
    unsigned int gridDimX, 
    unsigned int gridDimY, 
    unsigned int gridDimZ, 
    unsigned int blockDimX, 
    unsigned int blockDimY, 
    unsigned int blockDimZ, 
    unsigned int sharedMemBytes, 
    CUstream hStream, 
    void** kernelParams, 
    void** extra) 

где kernelParams является единственным параметром, который имеет отношение к этому вопросу. В документации указано

Параметры ядра могут быть указаны через kernelParams. Если f имеет N параметров, то kernelParams должен быть массивом из N указателей. Каждый из kernelParams[0] через kernelParams[N-1] должен указывать на область памяти, из которой будет скопирован фактический параметр ядра.


Ключевым моментом здесь является последнее предложение: Элементы kernelParams массива являются не фактические параметры ядра. Они только указывают на фактические параметры ядра.

И действительно, это имеет нечетный эффект, что для ядра, который получает один float *pointer, вы могли бы в принципе настроить параметры ядра следующим образом:

float *pointer= allocateSomeDeviceMemory(); 
float** pointerToPointer = &pointer; 
float*** pointerToPointerToPointer = &pointerToPointer; 
void **kernelParams = pointerToPointerToPointer; 

(Это просто, чтобы понять, что это действительно указатель на указатель на указатель - в действительности, Wou бы не написать это так)


Теперь, «структура» параметров ядра в основном то же самое для JCuda и CUDA , Конечно, вы не можете взять «адрес указателя» в Java, но количество косвенностей одинаково.Представьте, у вас есть ядро, как это:

__global__ void example(int value, float *pointer) 

В API CUDA C, вы можете определить параметры ядра следующим образом:

int value = 123; 
float *pointer= allocateSomeDeviceMemory(); 

int* pointerToValue = &value; 
float** pointerToPointer = &pointer; 

void **kernelParams = { 
    pointerToValue, 
    pointerToPointer 
}; 

Установка делается аналогично в API JCuda Java:

int value = 123; 
Pointer pointer= allocateSomeDeviceMemory(); 

Pointer pointerToValue = Pointer.to(new int[]{value}); 
float** pointerToPointer = Pointer.to(pointer); 

Pointer kernelParameters = Pointer.to(
    pointerToValue, 
    pointerToPointer 
); 

Основное различие, которое имеет отношение в том, что вы можете написать это немного более сжато в C, используя адрес оператора &:

void **kernelParams = { 
    &value,    // This can be imagined as a pointer to an int 
    &pointer   // This can be imagined as a pointer to a pointer 
}; 

Но это в основном так же, как в примере, что вы предоставили:

Pointer kernelParameters = Pointer.to(
    Pointer.to(new int[]{value}), // A pointer to an int 
    Pointer.to(pointer)    // A pointer to a pointer 
); 

Опять же, ключевым моментом является то, что с чем-то вроде

void **kernelParams = { 
    &value, 
}; 

или

Pointer kernelParameters = Pointer.to(
    Pointer.to(new int[]{value}), 
); 

Вы не передаете непосредственно ядру value. Вместо этого вы указываете CUDA: «Вот массив указателей. Первый указатель указывает на значение int. Скопируйте значение из этой ячейки памяти и используйте его как фактическое значение для вызова ядра».

+1

Благодарим вас за отличное объяснение! – Makketronix

Смежные вопросы