Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
cuda.doc
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
651.26 Кб
Скачать

2.6 Подключение cuda модулей и выполнение их на cuda-устройстве из Java-программы

CUDA модуль представляет собой файл с расширением ‘.cu‘. Подключение CUDA модуля представляет собой подключение функции из ‘.cu‘ файла:

String folder="t_cuda//p_task_1//";//директория в которой находится .cu файл

KernelLauncher kernelLauncher=KernelLauncher.create(folder+ "func.cu","func","");//подключение функции “func” из “func.cu” файла

Как видно в переменной ‘folder‘ прописан относительный путь, который указывает местонахождение файла ‘.cu‘, если он находится в корневой папке Java-проекта.

Особенности распараллеливания программы при выполнении на GPU задаются параметрами ‘BLOCKSIZE‘, ‘nThreads‘, ‘nBlocks‘ (‘N‘ - размер одномерного массива, который обрабатывается на GPU). ‘N‘ должен делиться на ‘BLOCKSIZE‘ без остатка, иначе расчет на GPU будет неверным.

int BLOCKSIZE = 50;

dim3 nThreads = new dim3(BLOCKSIZE, 1, 1);

dim3 nBlocks = new dim3(N/BLOCKSIZE, 1, 1);

Создание указателей на массив, расположенный в GPU:

CUdeviceptr dOutput = new CUdeviceptr();

CUdeviceptr dInput = new CUdeviceptr();

Выделение памяти для указателя (для массива типа float размером N значений):

cuMemAlloc(dOutput, N*Sizeof.FLOAT);

cuMemAlloc(dInput, N*Sizeof.FLOAT);

Помещение массива ‘masInput‘ в память GPU (‘cudaMemcpyHostToDevice‘):

cudaMemcpy(dInput,Pointer.to(masInput),N*Sizeof.FLOAT,cudaMemcpyHostToDevice);

Выполнение функции ‘func‘ из файла ‘func.cu‘ на GPU:

kernelLauncher.setup(nBlocks, nThreads).call(N,pi,dInput,dOutput);

В методе ‘call‘ указываются входные параметры функции ‘func‘. Выделение памяти под простые типы данных (переменные ‘N‘, ‘pi‘) не производится. Массив, на который указывает ‘dOutput‘, создается при вычислениях на GPU, поэтому для него не производится помещение в память GPU до вычислений на GPU.

После вычислений на GPU результат в виде массива возвращается (‘cudaMemcpyDeviceToHost‘) в основную часть программы и записывается в массив ‘masOutput‘:

cudaMemcpy(Pointer.to(masOutput),dOutput,N*Sizeof.FLOAT,cudaMemcpyDeviceToHost);

Затем необходимо освободить память GPU:

cuMemFree(dInput);

cuMemFree(dOutput);

Рекомендуется вычисление на GPU кода, на выполнение которого будет затрачиваться время длительностью не менее десятых долей секунды, при том, что количество таких вычислений с возвратом результата в основную часть программы должно быть минимизировано. В обратном случае (при большом количестве непродолжительных вычислений на GPU c почти непрерывным обменом данными между GPU и основной частью программы) не будет получено большое ускорение вычислений на GPU по сравнению с CPU.

Таким образом получается код, который при выполнении на GPU в количестве ‘number‘ раз в цикле ‘for‘ примет вид:

String folder="t_cuda//p_task_1//";

KernelLauncher kernelLauncher=KernelLauncher.create(folder+"func.cu","func","");

int BLOCKSIZE = 50;

dim3 nThreads = new dim3(BLOCKSIZE, 1, 1);

dim3 nBlocks = new dim3(N/BLOCKSIZE, 1, 1);

CUdeviceptr dOutput = new CUdeviceptr();

CUdeviceptr dInput = new CUdeviceptr();

for(int i=1;i<number;i++){

cuMemAlloc(dOutput, N*Sizeof.FLOAT);

cuMemAlloc(dInput, N*Sizeof.FLOAT);

cudaMemcpy(dInput,Pointer.to(masInput),N*Sizeof.FLOAT, cudaMemcpyHostToDevice);

kernelLauncher.setup(nBlocks, nThreads).call(N,pi,dInput,dOutput);

cudaMemcpy(Pointer.to(masOutput),dOutput,N*Sizeof.FLOAT,cudaMemcpyDeviceToHost);

cuMemFree(dInput);

cuMemFree(dOutput);

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]