Reduction Pattern

cudareductionsoftmaxnorm

elementwise kernel은 보통 input 하나 또는 몇 개로 output 하나를 만든다.

y[i] = f(x[i])

reduction은 여러 input을 하나의 값으로 줄인다.

sum = x[0] + x[1] + ... + x[n-1]
max = max(x[0], x[1], ..., x[n-1])
25143607
many inputs -> one statistic
sum28
max7
mean3.5
Reduction은 여러 원소를 읽어 하나의 통계량을 만든다.

왜 중요할까

Transformer kernel에는 reduction이 계속 나온다.

softmax:
  row max
  row sum(exp)

RMSNorm:
  row sum(x^2)

sampling:
  top-k, top-p, max

병렬화가 다르다

elementwise는 독립적이다.

thread 0 -> y[0]
thread 1 -> y[1]
thread 2 -> y[2]

reduction은 여러 thread의 결과를 합쳐야 한다.

thread partial sums
-> block sum
-> final sum

그래서 __syncthreads, shared memory, warp shuffle 같은 도구가 최적화 단계에서 필요해진다.

Path 2의 위치

이 path에서는 reduction을 깊게 최적화하지 않는다. 대신 다음을 구분할 수 있으면 충분하다.

elementwise:
  각 output이 독립적

reduction:
  output 하나가 여러 input에 의존

이 구분이 있어야 Path 3에서 softmax/RMSNorm을 최적화할 수 있다.

확인

  • softmax에서 어떤 부분이 reduction인가?
  • RMSNorm에서 어떤 부분이 reduction인가?
  • reduction kernel이 elementwise kernel보다 어려운 이유는 무엇인가?