Производительность clFFT падает при повторении одного и того же FFT по сравнению с FFTW - PullRequest
0 голосов
/ 17 февраля 2019

Я пытаюсь измерить и сравнить производительность fft на CPU и GPU, с FFTW и clFFT соответственно.

Для одной итерации или одного преобразования, кажется, что GPU вычисляет ее быстрее.Данные одинаковы в обоих случаях, а также размер и размер.Я пытаюсь вычислить только время, необходимое для вычисления БПФ.Для CPU и FFTW я использую функцию clock () C для измерения времени, а для GPU и clFFT я использую инструменты профилирования событий, предоставляемые OpenCL API.

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

Моя система: CPU: Intel i3 4690, GPU: Nvidia GTX 960 2 ГБ, ОС: Linux, Device OpenCL ver: 1.2, Для процессора я использую библиотеку FFTW, Для GPU и OpenCL я использую библиотеку clFFT.

Сценарий одиночного преобразования:

fftw.c

...
fftw_plan plan_signal_fft = fftw_plan_dft_1d(SAMPLES_PER_CODE, signalComplex, signalComplex_freq, FFTW_FORWARD, FFTW_ESTIMATE);
clock_t start, end;
// execute it once in case there is any initialization by the fftw library
fftw_execute(plan_signal_fft);

start = clock();
fftw_execute(plan_signal_fft);
end = clock();
double t = ((double)(end - start)) / CLOCKS_PER_SEC;
...

t = 0,000100 с

clFFT.c

...
ctx = clCreateContext(NULL, 1, &device_id, NULL, NULL, &return_val);
queue = clCreateCommandQueue(ctx, device_id, CL_QUEUE_PROFILING_ENABLE, &return_val);

clfftPlanHandle planHandle;
clfftDim dim = CLFFT_1D;
size_t clLengths[1] = {SAMPLES_PER_CODE};

clfftSetupData fftSetup;
return_val = clfftInitSetupData(&fftSetup);
return_val = clfftSetup(&fftSetup);

buff = clCreateBuffer(ctx, CL_MEM_READ_WRITE, SAMPLES_PER_CODE*2*sizeof(double), NULL, &return_val);
buff_results = clCreateBuffer(ctx, CL_MEM_READ_WRITE, SAMPLES_PER_CODE*2*sizeof(double), NULL, &return_val);
return_val = clEnqueueWriteBuffer(queue, buff, CL_TRUE, 0, SAMPLES_PER_CODE*2*sizeof(double), signalComplex, 0, NULL, NULL);

// read buffer
clFinish(queue);

return_val = clfftCreateDefaultPlan(&planHandle, ctx, dim, clLengths);
return_val = clfftSetPlanPrecision(planHandle, CLFFT_DOUBLE);
return_val = clfftSetResultLocation(planHandle, CLFFT_OUTOFPLACE);
return_val = clfftBakePlan(planHandle, 1, &queue, NULL, NULL);

return_val = clfftEnqueueTransform(planHandle, CLFFT_FORWARD, 1, &queue, 0, NULL, &event, &buff, &buff_results, NULL);

clWaitForEvents(1, &event);
return_val = clFinish(queue);
clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_START, sizeof(time_start), &time_start, NULL);
clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_END, sizeof(time_end), &time_end, NULL);
double nanoSeconds = time_end - time_start;
double t = nanoSeconds*pow(10,-9) // get seconds
...

t = 0,000010 с

Сценарий цикла:

fftw.c

...
start = clock();
for(i = 0; i < 20000; i++){
   fftw_execute(plan_signal_fft);
}
end = clock();
...

t = 1,614688 с

clfft.c

...
return_val = clfftEnqueueTransform(planHandle, CLFFT_FORWARD, 1, &queue, 0, NULL, &event, &buff, &buff_results, NULL);
clWaitForEvents(1, &event);
return_val = clFinish(queue);
clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_START, sizeof(time_start), &time_start, NULL);

for(i = 0; i < 19998; i++){
  return_val = clfftEnqueueTransform(planHandle, CLFFT_FORWARD, 1, &queue, 0, NULL, NULL, &buff, &buff_results, NULL);
  return_val = clFinish(queue);
}

return_val = clfftEnqueueTransform(planHandle, CLFFT_FORWARD, 1, &queue, 0, NULL, &event, &buff, &buff_results, NULL);
clWaitForEvents(1, &event);
return_val = clFinish(queue);
clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_END, sizeof(time_end), &time_end, NULL);
double nanoSeconds = time_end - time_start;
...

t = 1,945254 с

Я получаю одинаковые результаты в обоих случаях, поэтому преобразование корректно.Но я не знаю, правильно ли я выполняю итерации в OpenCL и clFFT.Почему при одном преобразовании clFFT работает быстрее, чем FFTW, и как только я повторяю то же преобразование, производительность clFFT так сильно падает?

Заранее спасибо.

...