2017-02-21 2 views
3

GPU의 실행 시간을 측정하여 CPU와 비교하려고합니다. 짧은 int 벡터의 모든 요소를 ​​추가하는 simple_add 함수를 작성했습니다. 커널 코드이다 :이 함수에 대해 100 개 시간의 실행 후, 다른 CPU 버전 쓴 내 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;    
    } 

, 결과는 10 회 전체 측정 함수를 호출 한 후 다음과 같이했다

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(); 

그 실행 시간이 측정 :

 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 
     ---------------- 

문제는 내가 정말 CPU보다 훨씬 빠른 것으로 GPU를 예상하지만이 아니었다는 것이다. 내 GPU 속도가 CPU보다 그리 높지 않은 이유를 이해할 수 없습니다. 내 코드에 문제가 있습니까 ?? 그냥 내 CPU 사양입니다 비교

 ----------------------------------------------------- 
     ------------- 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 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 
      ---------------------- 
: 나는 여기 QueryPerformanceCounter에와를 사용하여 벽 시계 시간을 측정
 ------------- 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) 
     ========================================================== 

는 결과입니다 여기 내 GPU의 숙박 시설이다

다시 한 번 실행 시간에 대해 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()'은 벽시계 시간이 아닌 CPU 시간을 측정합니다. GPU 실행 시간에는 포함되지 않습니다. 측정하는 시간은 아마도 OpenCL API 호출에 의해 취해집니다. C에서'clock_gettime()'을하거나 C++에서'std :: chrono :: steady_clock'을 시도하십시오. "CPU 시간"의 단위는 언급하지 않았습니다. 'clock()'함수의 원시 출력 (초 수를 얻기 위해'CLOCKS_PER_SEC'으로 나눠 져야 함)이라면, 1200은 실제로 짧은 기간입니다. – cuihao

+0

OpenCL 커널 시간 측정은 [이 답변] (http://stackoverflow.com/a/29972269/1231073)을 참조하십시오. – sgarizvi

+0

두 개의 실행 시간을 비교 했으므로 CPU 시간 또는 벽시계를 사용하는 것이 중요하지 않다고 생각합니다. 그러나 벽 시계 시간을 마이크로 초 단위로 측정하고이 측정 값을 추가하려고했습니다. – Afshin

답변

1
이 전체 스레드의 1/4 번호 uint4int4 벡터 형식을 시도하는 것이 좋습니다 그래서

ATI RV730은 VLIW 구조를 가지고 (NumberOfAllElements/16)입니다. 또한 각 작업 항목에 대해 메모리에서 더 빨리로드하는 데 도움이됩니다.

또한 커널은 메모리 연산에 비해 계산이 많지 않습니다. 버퍼를 RAM에 매핑하면 성능이 향상됩니다. 배열을 복사하지 말고 맵/맵핑 해제 명령을 사용하여 배열을 메모리에 매핑하십시오.

여전히 빠르지 않다면 gpu와 cpu를 동시에 사용하여 전반 및 후반 작업을 % 50 시간에 완료 할 수 있습니다.

또한 루프에 clFinish를 넣지 마십시오. 루프가 끝난 직후에 놓으십시오. 이렇게하면 훨씬 더 빠르게 큐에 넣을 수 있고 이미 순서대로 실행되므로 첫 번째 항목을 완료하기 전에 다른 항목을 시작하지 않습니다. 그것은 in-order 큐이며, 각각의 enqueue가 추가 오버 헤드 인 후에 clfinish를 추가합니다. 최신 커널 이후에 단 하나의 단점만으로 충분합니다.


ATI RV730 : 64 VLIW 유닛에는 각각 4 개 이상의 스트리밍 코어가 있습니다. 750 MHz.

i3-2100 : 8 개의 작업을 동시에 스트리밍 할 수있는 AVX가있는 코어 2 개 (방염 방지용 스레드). 따라서 이것은 비행 중 16 개의 작전을 가질 수 있습니다. 3GHz 이상.

주파수로 동작 스트리밍 단순히 승산 = 192 개 단위 (각 VLIW의 5 요소로 함수를 승산 - 가산 더)

i3-2100 = 48 유닛에게

ATI RV730

따라서 gpu는 적어도 4 배 이상 빠릅니다 (int4, uint4 사용). 이것은 비트 연산과 곱셈과 같은 간단한 ALU 및 FPU 연산을위한 것입니다. trancandentals 성능과 같은 특수 기능은 각 회선의 5 번째 장치에서만 실행되기 때문에 다를 수 있습니다.

+0

나는 고려하지 않았다. 내 측정에서 데이터 전송 시간. 나는 guss가 메모리 매핑을 비교하는 것을 더 빨리 수행해야만한다. (나는 아직 이것에 대해 확신하지 못한다.) – Afshin

+0

그렇다면 사용하는 스칼라 대신에 4-wide 벡터를 필요로하는 vliw 마이크로 아키텍처이다.1M 쓰레드가 있다면 지금은 256k 쓰레드 만 int4 –

+1

루프에서 clfinish를 삭제하고, 루프 바로 뒤에 넣습니다. –

0

몇 가지 추가 테스트를 통해 GPU가 부동 소수점 연산에 맞게 최적화되었음을 알았습니다. 나는 아래와 같이 테스트 코드 변경 :

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 
       -----------------------------------------