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

2.7 Создание ‘.Cu‘ файла

Необходимо создать файл с расширением ‘.cu‘, который затем редактируется программой ‘Блокнот‘ или другим текстовым редактором. Можно открыть ‘.txt‘ файл ‘Блокнотом‘ и сохранить его как ‘.cu‘ файл, добавив после имени файла ‘.cu‘ и указать в типе файла ‘Все файлы‘ вместо ‘Текстовые документы (.txt)‘.

В ‘.cu‘ файле пишется код на языке программирования С с расширениями для CUDA в виде функций, которые вызываются либо из Java-программы, либо из других функций ‘.cu‘ файла.

Перед объявлением функции указывается директива ‘extern "C"‘. Затем указывается тип функции ‘__device__‘ (выполняется на GPU, вызывается из ‘.cu‘ файла), ‘__global__‘ (выполняется на GPU, вызывается из Java-программы) или ‘__host__‘ (выполняется на СPU, вызывается из Java-программы).

Например, необходимо выполнить на GPU функцию ‘func‘, вызываемую из Java-программы (как вызвать такую функцию из Java-программы было рассмотрено выше):

extern "C" __global__void func(<... список входящих переменных ...>){

<... тело функции ....>

}

Входящими переменными являются переменные Java-программы. При описании входящих переменных функции указывается их тип и имя через запятую (если входящей переменной является массив, то перед его именем указывается ‘*‘):

extern "C" __global__ func(int N,float two_pi,float *input,float *output){ <... тело функции ....>}

Затем необходимо задать сетку и индексы потоков (переменными ‘threadIdx.x‘, ‘blockDim.x‘, ‘blockIdx.x‘). Данные переменные действительны только в пределах функции, которая выполняется на GPU. Также желательно провести синхронизацию потоков с помощью функции ‘__syncthreads()‘. Например, следующая функция вычисляет косинус для каждого элемента массива ‘input‘ и записывает результат в массив ‘output‘.

extern "C" __global__ void func(float *input, float *output){

int b = threadIdx.x + blockDim.x*blockIdx.x;

output[b]=cos(input[b]);

__syncthreads();

}

При более сложной структуре функции сложно описать параллельные вычисления в одной функции, поэтому создается вторая вспомогательная функция, которая вызывается из первой:

extern "C" __device__ float loop(int b,int N, float two_pi, float *input){

<... тело функции ....>

return (float) <... возвращаемое значение ...>;

}

extern "C" __global__ void func(int N, float two_pi, float *input, float *output){

int b = threadIdx.x + blockDim.x*blockIdx.x;

output[b]=loop(b,N,two_pi,input);

__syncthreads();

}

Таким образом получается готовый ‘.cu‘ файл, в котором все вычисления происходят в функции ‘loop‘:

extern "C" __device__ float loop(int b,int N, float two_pi, float *input){

float sum=0;

for(int a=0;a<N;a++)

if(input[a]>=input[b])sum+=cosf(two_pi*(input[b]-input[a]));

return (float)(-2*sum)/(float)N;

}

extern "C" __global__ void func(int N,float two_pi,float *input,float *output){

int b = threadIdx.x + blockDim.x*blockIdx.x;

output[b]=loop(b,N,two_pi,input);

__syncthreads();

}