2012-05-15 8 views
1

성능 테스트를 위해 간단한 CUDA 프로그램을 작성하고 있습니다.
이것은 벡터 계산과 관련이 없지만 단순한 (병렬) 문자열 변환의 경우에만 해당됩니다. 내가 2에서 1000 BLOCK_SIZE 값을 변경할 때CUDA 성능 테스트

#include <stdio.h> 
#include <string.h> 
#include <cuda_runtime.h> 


#define UCHAR   unsigned char 
#define UINT32   unsigned long int 

#define CTX_SIZE  sizeof(aes_context) 
#define DOCU_SIZE  4096 
#define TOTAL   100000 
#define BBLOCK_SIZE  500 


UCHAR   pH_TXT[DOCU_SIZE * TOTAL]; 
UCHAR   pH_ENC[DOCU_SIZE * TOTAL]; 
UCHAR*   pD_TXT; 
UCHAR*   pD_ENC; 


__global__ 
void TEST_Encode(UCHAR *a_input, UCHAR *a_output) 
{ 
    UCHAR  *input; 
    UCHAR  *output; 

    input = &(a_input[threadIdx.x * DOCU_SIZE]); 
    output = &(a_output[threadIdx.x * DOCU_SIZE]); 

    for (int i = 0 ; i < 30 ; i++) { 
     if ((input[i] >= 'a') && (input[i] <= 'z')) { 
      output[i] = input[i] - 'a' + 'A'; 
     } 
     else { 
      output[i] = input[i]; 
     } 
    } 
} 


int main(int argc, char** argv) 
{ 
    struct cudaDeviceProp xCUDEV; 

    cudaGetDeviceProperties(&xCUDEV, 0); 


    // Prepare Source 
    memset(pH_TXT, 0x00, DOCU_SIZE * TOTAL); 

    for (int i = 0 ; i < TOTAL ; i++) { 
     strcpy((char*)pH_TXT + (i * DOCU_SIZE), "hello world, i need an apple."); 
    } 

    // Allocate vectors in device memory 
    cudaMalloc((void**)&pD_TXT, DOCU_SIZE * TOTAL); 
    cudaMalloc((void**)&pD_ENC, DOCU_SIZE * TOTAL); 

    // Copy vectors from host memory to device memory 
    cudaMemcpy(pD_TXT, pH_TXT, DOCU_SIZE * TOTAL, cudaMemcpyHostToDevice); 

    // Invoke kernel 
    int threadsPerBlock = BLOCK_SIZE; 
    int blocksPerGrid = (TOTAL + threadsPerBlock - 1)/threadsPerBlock; 

    printf("Total Task is %d\n", TOTAL); 
    printf("block size is %d\n", threadsPerBlock); 
    printf("repeat cnt is %d\n", blocksPerGrid); 

    TEST_Encode<<<blocksPerGrid, threadsPerBlock>>>(pD_TXT, pD_ENC); 

    cudaMemcpy(pH_ENC, pD_ENC, DOCU_SIZE * TOTAL, cudaMemcpyDeviceToHost); 

    // Free device memory 
    if (pD_TXT)   cudaFree(pD_TXT); 
    if (pD_ENC)   cudaFree(pD_ENC); 

    cudaDeviceReset(); 
} 

는, 나는 그렇게 (NVIDIA 비주얼 프로파일 러에서)는 다음과 같은 지속 시간

TOTAL  BLOCKS  BLOCK_SIZE Duration(ms) 
100000  50000  2   28.22 
100000  10000  10   22.223 
100000  2000  50   12.3 
100000  1000  100   9.624 
100000  500   200   10.755 
100000  250   400   29.824 
100000  200   500   39.67 
100000  100   1000  81.268 

내 GPU는 지포스 GT520 및 최대 threadsPerBlock 값은 1024입니다있어 나는 BLOCK이 1000 일 때 최상의 성능을 얻을 것이라고 예측했지만 위 표는 다른 결과를 보여줍니다.

왜 지속 시간이 선형이 아닌지 이해할 수 없으며이 문제를 어떻게 해결할 수 있습니까? (또는 나는 (mimimum 기간 시간) 자사의 디자인은 훨씬 더 많은 스레드를 시작하는 것입니다 때문에

답변

3

그것은, GPU의 기능을 활용하지 않는 50 개 스레드 (10), 2 보인다.

최적화 된 블록 값을 찾을 수있는 방법을 귀하의 카드 계산 능력 2.1이 있습니다.

    멀티 당 주민 스레드
  • 최대 = 블록 = 1024
  • 멀티 당 주민 블록
  • 최대 = 8
  • 0 당 스레드 1536
  • 최대
  • 워프 크기 = 32

이 두 가지 문제가 있습니다

당신은 그것의 definetly 지역 천천히 아웃소싱 것을 스레드 당 너무 많은 레지스터 메모리를 차지하려고 1.

블록 크기가 증가하면 메모리 공간. 이 카드의 휨의 크기는 많은 메모리 작업이 워프 크기의 여러과 스레드 크기에 최적화되어 있기 때문에

2

(32)의 복수와 함께 테스트를 수행합니다.

따라서 SM 당 약 1 개의 블록 만 할당 할 수 있으므로 블록 당 약 1024 개 (사용자의 경우 1000 개) 스레드를 사용하는 경우 gpu의 33 %가 유휴 상태입니다.

다음과 같은 100 % 점유율을 사용하면 어떻게됩니까?

  • 128 = 12 블록 -> 만 8 블록 실행
  • 256 = 6 개 상주 블록 SM 당 SM 당 직렬화
  • 192 = 8 상주 블록이다 SM 당 상주 할 수 있으므로
  • 512 = sm 당 상주 블록 3 개