2017-02-21 7 views
3

Я пытаюсь измерить время выполнения графического процессора и сравнить его с CPU. Я написал функцию simple_add, чтобы добавить все элементы короткого int vector. Ядро код:Мой тест opencl работает не быстрее, чем CPU

global const int * A, global const uint * B, global int* C) 
    { 
     ///------------------------------------------------ 
     /// Add 16 bits of each 
     int AA=A[get_global_id(0)]; 
     int BB=B[get_global_id(0)]; 
     int AH=0xFFFF0000 & AA; 
     int AL=0x0000FFFF & AA; 
     int BH=0xFFFF0000 & BB; 
     int BL=0x0000FFFF & BB; 
     int CL=(AL+BL)&0x0000FFFF; 
     int CH=(AH+BH)&0xFFFF0000;  
     C[get_global_id(0)]=CH|CL;    
    } 

Я написал другую версию процессора для выполнения этой функции и после 100 время казни измерили их время выполнения

clock_t before_GPU = clock(); 
for(int i=0;i<100;i++) 
{ 
    queue.enqueueNDRangeKernel(kernel_add,1, 
    cl::NDRange((size_t)(NumberOfAllElements/4)),cl::NDRange(64)); 
    queue.finish(); 
} 
clock_t after_GPU = clock(); 


clock_t before_CPU = clock(); 
for(int i=0;i<100;i++) 
    AddImagesCPU(A,B,C); 
    clock_t after_CPU = clock(); 

результат был ниже после того, как 10 раз вызывая всю функцию измерения :

 CPU time: 1359 
     GPU time: 1372 
     ---------------- 
     CPU time: 1336 
     GPU time: 1269 
     ---------------- 
     CPU time: 1436 
     GPU time: 1255 
     ---------------- 
     CPU time: 1304 
     GPU time: 1266 
     ---------------- 
     CPU time: 1305 
     GPU time: 1252 
     ---------------- 
     CPU time: 1313 
     GPU time: 1255 
     ---------------- 
     CPU time: 1313 
     GPU time: 1253 
     ---------------- 
     CPU time: 1384 
     GPU time: 1254 
     ---------------- 
     CPU time: 1300 
     GPU time: 1254 
     ---------------- 
     CPU time: 1322 
     GPU time: 1254 
     ---------------- 

Проблема в том, что я действительно ожидал, что GPU будет намного быстрее, чем процессор, но это не так. Я не понимаю, почему скорость моего GPU не намного выше, чем у процессора. Есть ли какие-то проблемы в моих кодах? Вот мои свойства GPU:

 ----------------------------------------------------- 
     ------------- Selected Platform Properties-------------: 
     NAME: AMD Accelerated Parallel Processing 
     EXTENSION:  cl_khr_icd cl_amd_event_callback cl_amd_offline_devices cl_khr_d3d10_sharing 
     VENDOR:   Advanced Micro Devices, Inc. 
     VERSION:  OpenCL 1.2 AMD-APP (937.2) 
     PROFILE:  FULL_PROFILE 
     ----------------------------------------------------- 
     ------------- Selected Device Properties-------------: 
     NAME : ATI RV730 
     TYPE : 4 
     VENDOR :  Advanced Micro Devices, Inc. 
     PROFILE :  FULL_PROFILE 
     VERSION :  OpenCL 1.0 AMD-APP (937.2) 
     EXTENSIONS : cl_khr_gl_sharing cl_amd_device_attribute_query cl_khr_d3d10_sharing 
     MAX_COMPUTE_UNITS :  8 
     MAX_WORK_GROUP_SIZE : 128 
     OPENCL_C_VERSION :  OpenCL C 1.0 
     DRIVER_VERSION:   CAL 1.4.1734 
     ========================================================== 

и просто сравнить это мои спецификации процессоров:

 ------------- CPU Properties-------------: 
     NAME :   Intel(R) Core(TM) i3-2100 CPU @ 3.10GHz 
     TYPE : 2 
     VENDOR :  GenuineIntel 
     PROFILE :  FULL_PROFILE 
     VERSION :  OpenCL 1.2 AMD-APP (937.2) 
     MAX_COMPUTE_UNITS :  4 
     MAX_WORK_GROUP_SIZE : 1024 
     OPENCL_C_VERSION :  OpenCL C 1.2 
     DRIVER_VERSION:   2.0 (sse2,avx) 
     ========================================================== 

Я также измерил время настенных часов, используя QueryPerformanceCounter и вот результаты:

  CPU time: 1304449.6 micro-sec 
      GPU time: 1401740.82 micro-sec 
      ---------------------- 
      CPU time: 1620076.55 micro-sec 
      GPU time: 1310317.64 micro-sec 
      ---------------------- 
      CPU time: 1468520.44 micro-sec 
      GPU time: 1317153.63 micro-sec 
      ---------------------- 
      CPU time: 1304367.29 micro-sec 
      GPU time: 1251865.14 micro-sec 
      ---------------------- 
      CPU time: 1301589.17 micro-sec 
      GPU time: 1252889.4 micro-sec 
      ---------------------- 
      CPU time: 1294750.21 micro-sec 
      GPU time: 1257017.41 micro-sec 
      ---------------------- 
      CPU time: 1297506.93 micro-sec 
      GPU time: 1252768.9 micro-sec 
      ---------------------- 
      CPU time: 1293511.29 micro-sec 
      GPU time: 1252019.88 micro-sec 
      ---------------------- 
      CPU time: 1320753.54 micro-sec 
      GPU time: 1248895.73 micro-sec 
      ---------------------- 
      CPU time: 1296486.95 micro-sec 
      GPU time: 1255207.91 micro-sec 
      ---------------------- 

Снова я попробовал профилирование opencl для выполнения.

  queue.enqueueNDRangeKernel(kernel_add,1, 
            cl::NDRange((size_t)(NumberOfAllElements/4)), 
            cl::NDRange(64),NULL,&ev); 
      ev.wait(); 
      queue.finish(); 
      time_start=ev.getProfilingInfo<CL_PROFILING_COMMAND_START>(); 
      time_end=ev.getProfilingInfo<CL_PROFILING_COMMAND_END>(); 

Результаты для одного выполнения времени были более или менее то же самое:

  CPU time: 13335.1815 micro-sec 
      GPU time: 11865.111 micro-sec 
      ---------------------- 
      CPU time: 13884.0235 micro-sec 
      GPU time: 11663.889 micro-sec 
      ---------------------- 
      CPU time: 19724.7296 micro-sec 
      GPU time: 14548.222 micro-sec 
      ---------------------- 
      CPU time: 19945.3199 micro-sec 
      GPU time: 15331.111 micro-sec 
      ---------------------- 
      CPU time: 17973.5055 micro-sec 
      GPU time: 11641.444 micro-sec 
      ---------------------- 
      CPU time: 12652.6683 micro-sec 
      GPU time: 11632 micro-sec 
      ---------------------- 
      CPU time: 18875.292 micro-sec 
      GPU time: 14783.111 micro-sec 
      ---------------------- 
      CPU time: 32782.033 micro-sec 
      GPU time: 11650.444 micro-sec 
      ---------------------- 
      CPU time: 20462.2257 micro-sec 
      GPU time: 11647.778 micro-sec 
      ---------------------- 
      CPU time: 14529.6618 micro-sec 
      GPU time: 11860.112 micro-sec 
+0

'clock()' измеряет время процессора вместо часов настенных часов. Он не будет учитываться при работе графического процессора. Время, которое вы измеряете, вероятно, принимается вызовами OpenCL API. Попробуйте 'clock_gettime()' в C или 'std :: chrono :: stable_clock' в C++ вместо этого. Вы не указали блок вашего «процессорного времени». Если это необработанный вывод функции 'clock()' (которую нужно разделить на 'CLOCKS_PER_SEC', чтобы получить количество секунд), 1200 действительно короткий период. – cuihao

+0

См. [Этот ответ] (http://stackoverflow.com/a/29972269/1231073) для измерения времени ядра OpenCL. – sgarizvi

+0

Поскольку я сравнивал два времени выполнения, я думаю, что не важно использовать время процессора или время настенных часов. Тем не менее, я попытался измерить время настенных часов в микросекундах и добавить это измерение. – Afshin

ответ

1

ATI RV730 имеет структуру VLIW, так что лучше попробовать uint4 и int4 векторные типы 1/4 числа полных потоков (который является NumberOfAllElements/16). Это также поможет ускорить загрузку из памяти для каждого рабочего элемента.

Также ядро ​​не имеет большого количества вычислений по сравнению с операциями с памятью. Создание буферов, сопоставленных с ОЗУ, будет иметь лучшую производительность. Не копируйте массивы, сопоставляйте их в памяти с помощью команд map/unmap enqueue.

Если он все еще не работает быстрее, вы можете одновременно использовать как gpu, так и процессор, чтобы работать в первой половине и второй половине работы, чтобы завершить его в% 50 раз.

Также не ставьте clFinish в петлю. Поместите его сразу после окончания цикла. Таким образом, он будет запускаться в очередь намного быстрее, и у него уже есть исполнение в порядке, чтобы он не запускал другие, прежде чем заканчивать первый элемент. Я полагаю, что это очередь в очереди, и добавление clfinish после каждой очереди - дополнительные накладные расходы. Достаточно только одного clfinish после последнего ядра.


ATI RV730: 64 Устройства VLIW, каждая из которых имеет по меньшей мере 4 потоковых сердечника. 750 МГц.

i3-2100: 2 ядра (потоки только для борьбы с пузырьками), каждый из которых имеет AVX, способный одновременно передавать 8 операций. Таким образом, это может иметь 16 операций в полете. Более 3 ГГц.

Просто умножение потоковых операций с частотами:

ATI RV730 = 192 единиц (больше с умножения-сложения функций, с помощью 5-го элемента каждого VLIW)

i3-2100 = 48 единиц

поэтому gpu должен быть как минимум 4 раза быстрее (используйте int4, uint4). Это для простых операций ALU и FPU, таких как побитовые операции и умножения. Специальные функции, такие как производительность trancandentals, могут быть разными, поскольку они работают только на 5-м блоке в каждом окне.

+0

Я не рассматривал время передачи данных в моем измерении. Я guss после копирования, gpu должен выполнить более быстрое сравнение сопоставления памяти (я еще не уверен в этом) – Afshin

+0

, тогда это микроархитектура vilw, нуждающаяся в 4-х широких векторах вместо скаляров, которые вы используете.Если бы были потоки 1М, теперь только потоки 256 тыс. Быстрее выполняли бы работу, используя int4 –

+1

delete clfinish from loop, поместите его сразу после цикла –

0

Я сделал несколько дополнительных тестов и понял, что графический процессор оптимизирован для операций с плавающей запятой. я изменил тестовый код, как показано ниже:

void kernel simple_add(global const int * A, global const uint * B, global int* C) 
    { 
     ///------------------------------------------------ 
     /// Add 16 bits of each 
     int AA=A[get_global_id(0)]; 
     int BB=B[get_global_id(0)]; 
     float AH=0xFFFF0000 & AA; 
     float AL=0x0000FFFF & AA; 
     float BH=0xFFFF0000 & BB; 
     float BL=0x0000FFFF & BB; 
     int CL=(int)(AL*cos(AL)+BL*sin(BL))&0x0000FFFF; 
     int CH=(int)(AH*cos(AH)+BH*sin(BL))&0xFFFF0000; 
      C[get_global_id(0)]=CH|CL;    
    } 

и получил результат, который я ожидал (около 10 раз быстрее):

   CPU time:  741046.665 micro-sec 
       GPU time:  54618.889 micro-sec 
       ---------------------------------------------------- 
       CPU time:  741788.112 micro-sec 
       GPU time:  54875.666 micro-sec 
       ---------------------------------------------------- 
       CPU time:  739975.979 micro-sec 
       GPU time:  54560.445 micro-sec 
       ---------------------------------------------------- 
       CPU time:  755848.937 micro-sec 
       GPU time:  54582.111 micro-sec 
       ---------------------------------------------------- 
       CPU time:  724100.716 micro-sec 
       GPU time:  56893.445 micro-sec 
       ---------------------------------------------------- 
       CPU time:  744476.351 micro-sec 
       GPU time:  54596.778 micro-sec 
       ---------------------------------------------------- 
       CPU time:  727787.538 micro-sec 
       GPU time:  54602.445 micro-sec 
       ---------------------------------------------------- 
       CPU time:  731132.939 micro-sec 
       GPU time:  54710.000 micro-sec 
       ---------------------------------------------------- 
       CPU time:  727899.150 micro-sec 
       GPU time:  54583.444 micro-sec 
       ---------------------------------------------------- 
       CPU time:  727089.880 micro-sec 
       GPU time:  54594.778 micro-sec 
       ---------------------------------------------------- 

за несколько тяжелых операций с плавающей запятой, как показано ниже:

 void kernel simple_add(global const int * A, global const uint * B, global int* C) 
      { 
       ///------------------------------------------------ 
       /// Add 16 bits of each 
       int AA=A[get_global_id(0)]; 
       int BB=B[get_global_id(0)]; 
       float AH=0xFFFF0000 & AA; 
       float AL=0x0000FFFF & AA; 
       float BH=0xFFFF0000 & BB; 
       float BL=0x0000FFFF & BB; 
       int CL=(int)(AL*(cos(AL)+sin(2*AL)+cos(3*AL)+sin(4*AL)+cos(5*AL)+sin(6*AL))+ 
         BL*(cos(BL)+sin(2*BL)+cos(3*BL)+sin(4*BL)+cos(5*BL)+sin(6*BL)))&0x0000FFFF; 
       int CH=(int)(AH*(cos(AH)+sin(2*AH)+cos(3*AH)+sin(4*AH)+cos(5*AH)+sin(6*AH))+ 
         BH*(cos(BH)+sin(2*BH)+cos(3*BH)+sin(4*BH)+cos(5*BH)+sin(6*BH)))&0xFFFF0000; 
         C[get_global_id(0)]=CH|CL; 

      } 

В результате был более или менее то же самое:

   CPU time:  3905725.933 micro-sec 
       GPU time:  354543.111 micro-sec 
       ----------------------------------------- 
       CPU time:  3698211.308 micro-sec 
       GPU time:  354850.333 micro-sec 
       ----------------------------------------- 
       CPU time:  3696179.243 micro-sec 
       GPU time:  354302.667 micro-sec 
       ----------------------------------------- 
       CPU time:  3692988.914 micro-sec 
       GPU time:  354764.111 micro-sec 
       ----------------------------------------- 
       CPU time:  3699645.146 micro-sec 
       GPU time:  354287.666 micro-sec 
       ----------------------------------------- 
       CPU time:  3681591.964 micro-sec 
       GPU time:  357071.889 micro-sec 
       ----------------------------------------- 
       CPU time:  3744179.707 micro-sec 
       GPU time:  354249.444 micro-sec 
       ----------------------------------------- 
       CPU time:  3704143.214 micro-sec 
       GPU time:  354934.111 micro-sec 
       ----------------------------------------- 
       CPU time:  3667518.628 micro-sec 
       GPU time:  354809.222 micro-sec 
       ----------------------------------------- 
       CPU time:  3714312.759 micro-sec 
       GPU time:  354883.888 micro-sec 
       ----------------------------------------- 
Смежные вопросы