2012-12-12 6 views
1

CUDA 스레드/블록 및 어레이에 대해 여러 번 읽었지만 여전히 CUDA가 커널 기능을 위해 다중 스레드를 실행하기 시작하는 시점과 시점을 이해하지 못합니다. 호스트가 커널 함수를 호출하거나 커널 함수를 호출 할 때.CUDA : 스레드 및 배열 할당

예를 들어,이 예가 있습니다. 간단히 배열을 조 변경합니다. (그래서,이 배열의 값을 다른 배열에 복사합니다).

__global__ 
void transpose(float* in, float* out, uint width) { 
    uint tx = blockIdx.x * blockDim.x + threadIdx.x; 
    uint ty = blockIdx.y * blockDim.y + threadIdx.y; 
    out[tx * width + ty] = in[ty * width + tx]; 
} 

int main(int args, char** vargs) { 
    /*const int HEIGHT = 1024; 
    const int WIDTH = 1024; 
    const int SIZE = WIDTH * HEIGHT * sizeof(float); 
    dim3 bDim(16, 16); 
    dim3 gDim(WIDTH/bDim.x, HEIGHT/bDim.y); 
    float* M = (float*)malloc(SIZE); 
    for (int i = 0; i < HEIGHT * WIDTH; i++) { M[i] = i; } 
    float* Md = NULL; 
    cudaMalloc((void**)&Md, SIZE); 
    cudaMemcpy(Md,M, SIZE, cudaMemcpyHostToDevice); 
    float* Bd = NULL; 
    cudaMalloc((void**)&Bd, SIZE); */ 
    transpose<<<gDim, bDim>>>(Md, Bd, WIDTH); // CALLING FUNCTION TRANSPOSE 
    cudaMemcpy(M,Bd, SIZE, cudaMemcpyDeviceToHost); 
    return 0; 
} 

나는 기능 tranpose를 호출 라인을 제외하고 main 함수의 모든 라인을 이해하고있다 (나는 중요하지, 단지 기능 전치 전화 라인이있는 모든 라인을 댓글을 달았). 내가 말할 때 사실입니까? 우리가 함수 transpose<<<gDim, bDim>>>(Md, Bd, WIDTH)을 호출하면 CUDA는 배열의 각 요소를 하나의 스레드 (및 블록)에 자동으로 할당하고 "한 번에"호출하면 CUDA는 gDim * bDim 번 스레드를 gDim * bDim 스레드에서 실행합니다.

이 점은 자바 멀티 스레드를 좋아하지 않기 때문에 내가 가르쳐주세요.

감사합니다 :)

답변

5

이해는 정확한 본질에 :(사용하는 경우 나, 너무 많은 좌절 느낄 수 있습니다.

transpose은 기능이 아니라 CUDA 커널입니다. 일반 함수를 호출하면 한 번만 실행됩니다. 그러나 한 번에 커널을 실행하면 CUDA가 자동으로 커널에서 코드를 여러 번 실행합니다. CUDA는 많은 스레드를 시작하여이를 수행합니다. 각 스레드는 커널에서 코드를 한 번 실행합니다. 트리클 괄호 안의 숫자 (<<< >>>)를 커널 실행 구성이라고합니다. CUDA에 의해 시작될 스레드 수를 결정하고 스레드 간의 관계를 지정합니다.

시작할 스레드 수는 격자의 모든 값을 곱하고 대괄호 안의 블록 크기를 계산하여 계산합니다. 예를 들어, 스레드 수는 1,048,576 (16 * 16 * 64 * 64)입니다.

각 스레드는 스레드를 확인하기 위해 일부 변수를 읽을 수 있습니다. 그것들은 커널 상단에 blockIdxthreadIdx 구조입니다. 값은 커널 실행 구성의 값을 반영합니다. 따라서 격자를 16 x 16 (첫 번째 dim3)으로 커널을 실행하면 blockIdx 구조의 xy 값을 읽을 때 가능한 모든 조합을 얻을 수있는 스레드가 만들어집니다. xy은 0에서 15 사이입니다.

따라서 CUDA는 배열 요소 나 커널과 관련된 기타 데이터 구조에 대해 알지 못하며 스레드, 스레드 인덱스 및 블록 인덱스 만 처리합니다. 그런 다음 해당 인덱스를 사용하여 주어진 스레드가 수행해야하는 작업 (특히 응용 프로그램에서 작동해야하는 특정 데이터의 값)을 결정합니다.