2012-03-23 2 views
3

C++ AMP를 실험하기 시작했습니다. 나는 단지 그것이 할 수있는 것을보기 위해 간단한 테스트 앱을 만들었지 만, 그 결과는 내게 놀랍다. 다음 코드를 고려하십시오 Timer이 QueryPerformanceCounter에를 사용하여 간단한 타이밍 클래스가array_view :: synchronize() 호출이 왜 그렇게 느린가요?

#include <amp.h> 
#include "Timer.h" 

using namespace concurrency; 

int main(int argc, char* argv[]) 
{ 
    uint32_t u32Threads = 16; 
    uint32_t u32DataRank = u32Threads * 256; 
    uint32_t u32DataSize = (u32DataRank * u32DataRank)/u32Threads; 
    uint32_t* pu32Data = new (std::nothrow) uint32_t[ u32DataRank * u32DataRank ]; 

    for (uint32_t i = 0; i < u32DataRank * u32DataRank; i++) 
    { 
     pu32Data[i] = 1; 
    } 

    uint32_t* pu32Sum = new (std::nothrow) uint32_t[ u32Threads ]; 

    Timer tmr; 

    tmr.Start(); 

    array< uint32_t, 1 > source(u32DataRank * u32DataRank, pu32Data); 
    array_view< uint32_t, 1 > sum(u32Threads, pu32Sum); 

    printf("Array<> deep copy time: %.6f\n", tmr.Stop()); 

    tmr.Start(); 

    parallel_for_each( 
     sum.extent, 
     [=, &source](index<1> idx) restrict(amp) 
     { 
      uint32_t u32Sum = 0; 
      uint32_t u32Start = idx[0] * u32DataSize; 
      uint32_t u32End = (idx[0] * u32DataSize) + u32DataSize; 
      for (uint32_t i = u32Start; i < u32End; i++) 
      { 
       u32Sum += source[i]; 
      } 
      sum[idx] = u32Sum; 
     } 
    ); 

    double dDuration = tmr.Stop(); 
    printf("gpu computation time: %.6f\n", dDuration); 

    tmr.Start(); 

    sum.synchronize(); 

    dDuration = tmr.Stop(); 
    printf("synchronize time: %.6f\n", dDuration); 
    printf("first and second row sum = %u, %u\n", pu32Sum[0], pu32Sum[1]); 

    tmr.Start(); 

    for (uint32_t idx = 0; idx < u32Threads; idx++) 
    { 
     uint32_t u32Sum = 0; 
     for (uint32_t i = 0; i < u32DataSize; i++) 
     { 
      u32Sum += pu32Data[(idx * u32DataSize) + i]; 
     } 
     pu32Sum[idx] = u32Sum; 
    } 

    dDuration = tmr.Stop(); 
    printf("cpu computation time: %.6f\n", dDuration); 
    printf("first and second row sum = %u, %u\n", pu32Sum[0], pu32Sum[1]); 

    delete [] pu32Sum; 
    delete [] pu32Data; 

    return 0; 
} 

하는 것으로. 어쨌든 코드 출력은 다음과 같습니다.

Array<> deep copy time: 0.089784 
gpu computation time: 0.000449 
synchronize time: 8.671081 
first and second row sum = 1048576, 1048576 
cpu computation time: 0.006647 
first and second row sum = 1048576, 1048576 

왜 전화를 동기화하는 데 시간이 오래 걸립니까? 이 문제를 해결하는 방법이 있습니까? 그 외에는 계산 성능의 성능이 놀랍습니다. 그러나 synchronize() 오버 헤드로 인해 나를 사용할 수 없게됩니다.

내가 끔찍한 일을하고있을 수도 있습니다. 그렇다면 나에게 말해주십시오. 미리 감사드립니다.

답변

5

함수 실제 커널이 작업을 완료하기를 기다리고 있기 때문에 synchronize() 함수가 너무 오래 걸릴 수 있습니다. parallel_for_each from amp.h에서

:

는 parallel_for_each, 그것은 비동기 호출 코드에 대한 동기처럼, 그러나 실제로 실행 있습니다. 나는. parallel_for_each 호출이 만들어지고 커널이 런타임에 전달되면 [parallel_for_each 뒤의 코드]는 CPU 스레드에 의해 즉시 실행되고 병렬로 커널은 GPU 스레드에 의해 실행됩니다.

따라서 parallel_for_each에서 보낸 시간을 측정하는 것은 특히 중요하지 않습니다.

편집 : 알고리즘 작성 방식에 따라 GPU 가속화에 많은 도움이되지 않습니다. 소스 [i]의 읽기는 병합되지 않으므로 병합 읽기보다 거의 16 배 더 느립니다. 공유 메모리를 사용하여 읽기를 병합하는 것은 가능하지만 그렇게 간단하지는 않습니다. GPU 프로그래밍에 대해 읽어 보는 것이 좋습니다.

C++ AMP의 유틸리티를 보여주는 간단한 예제가 필요하면 matrix multiplication을 시도하십시오.

물론 관찰 할 성능은 GPU 하드웨어 모델에 따라 크게 달라집니다.

+0

을 그래서 GPU의 실제 계산이 너무 오래 걸립니다 의미와는 이미 여기에 우리의 지침을 따르십시오, p_f_e되는 동기의 가정을) 지적? 그렇다면 속도를 높일 수있는 방법이있어서 CPU만큼 빠를 것입니까? – PeterK

+0

나는 왜 GPU 계산이 느린지를 설명하기 위해 해답을 편집했다. –

+0

감사! 더 자세히 살펴볼 것입니다. – PeterK

3

특정 알고리즘에 대한 Igor의 응답 외에도 일반적으로 C++ AMP 성능을 측정하는 방식이 여러 가지 부정확합니다 (런타임 초기화 제외 없음, 초기 JIT 삭제 없음, 데이터 준비 없음,

http://blogs.msdn.com/b/nativeconcurrency/archive/2011/12/28/how-to-measure-the-performance-of-c-amp-algorithms.aspx

+1

안녕 다니엘, 답장을 보내 주셔서 감사합니다. 나는 이미 당신이 링크하고있는 MSDN 블로그를 찾았고 거기에있는 모든 놀라운 예들을 공부하고 있습니다. 감사! – PeterK

관련 문제