Global Index와 Boundary Check

cudaindexingboundary-check

1D CUDA indexing의 핵심 공식은 하나다.

int i = blockIdx.x * blockDim.x + threadIdx.x;

i가 전체 배열에서 현재 thread가 처리할 위치다.

왜 이 공식인가

전체 위치는 두 부분으로 나뉜다.

현재 block의 시작 위치
+
block 안에서 thread의 위치

blockDim.x = 4이면 block 하나가 thread 4개를 가진다.

block 0 시작 위치 = 0 * 4 = 0
block 1 시작 위치 = 1 * 4 = 4
block 2 시작 위치 = 2 * 4 = 8

여기에 threadIdx.x를 더한다.

block 2, thread 0 -> 2 * 4 + 0 = 8
block 2, thread 1 -> 2 * 4 + 1 = 9
block 2, thread 2 -> 2 * 4 + 2 = 10
block 2, thread 3 -> 2 * 4 + 3 = 11

그래서:

global index = block start + local thread offset

왜 boundary check가 필요한가

block 수는 보통 올림 나눗셈으로 계산한다.

int blocksPerGrid = (n + threadsPerBlock - 1) / threadsPerBlock;

예를 들어 n = 17, threadsPerBlock = 4이면 block은 5개가 필요하다.

총 thread 수 = 5 * 4 = 20
실제 원소 수 = 17
초과 thread = i 17, 18, 19

그래서 kernel 안에서 막아야 한다.

if (i < n) {
    c[i] = a[i] + b[i];
}

이 조건이 없으면 배열 바깥 메모리에 접근할 수 있다.

확인

  • n = 33, threadsPerBlock = 8이면 block은 몇 개 필요한가?
  • blockIdx.x * blockDim.x는 무엇을 의미하는가?
  • if (i < n)을 제거하면 어떤 thread가 위험한가?