신경망 추론의 메모리 트래픽 — 학습서

· 기초 어휘

목차

신경망이 왜 느린지를 따지려면 먼저 무엇을 세는지 약속해야 한다. 이 장은 책 전체에서 쓸 단어 일곱 개를 정의한다. byte와 자료형, 가중치와 활성값, 메모리 트래픽, 재사용, 연산강도, 그리고 roofline이다. 다음 장부터는 이 단어들을 정의 없이 쓴다.

0.1 byte와 자료형 — 숫자 하나가 차지하는 자리

신경망은 수많은 숫자로 이루어진다. 그 숫자 하나가 메모리에서 몇 바이트(byte)를 차지하는지가 모든 계산의 출발점이다. 숫자를 어떤 자료형(dtype)으로 저장하느냐가 이 폭을 정한다.

  • FP32 — 32비트 부동소수점. 숫자 하나가 4 byte. 학습과 일반 추론의 기본값이다.
  • FP16 — 16비트 부동소수점. 숫자 하나가 2 byte.
  • INT8 — 8비트 정수. 숫자 하나가 1 byte.

이 책은 따로 말하지 않으면 FP32(4 byte) 를 쓴다. INT8 비교는 05장에서 한 번 한다.

자료형이 폭을 정하므로, 어떤 텐서가 차지하는 바이트는 늘 같은 꼴로 센다.

바이트 = (원소 수) × (자료형 byte)

INT8에서는 원소 하나가 1 byte이니 원소 수가 곧 바이트 수다. 이 점은 나중에 INT8 트래픽을 셀 때 계산을 가볍게 해 준다.

광고 · Advertisements

0.2 가중치와 활성값 — 모델이 가진 것과 추론이 만드는 것

신경망 안의 숫자는 성격이 다른 두 무리로 나뉜다. 이 구별이 책 전체를 떠받친다.

가중치(weight) 는 학습으로 정해진 파라미터다. 합성곱의 커널 값, 전결합층의 행렬이 모두 가중치다. 모델을 저장하면 그대로 디스크에 들어가는 것이 가중치다. 가중치의 크기는 모델 구조, 곧 채널 수와 커널 크기가 정한다. 입력 영상이 무엇이든, batch가 몇이든 가중치의 양은 그대로다.

활성값(activation) 은 레이어와 레이어 사이를 흐르는 중간 텐서다. feature map이라고도 부른다. 한 레이어가 입력을 받아 계산한 결과가 활성값이고, 그 활성값을 다음 레이어가 입력으로 받는다. 활성값의 크기는 모델 구조뿐 아니라 입력 해상도와 batch가 함께 정한다. 같은 모델이라도 큰 사진을 넣으면 활성값이 커진다.

구분 가중치 활성값
무엇인가 학습된 파라미터 레이어 사이의 중간 텐서
크기를 정하는 것 모델 구조(채널·커널) 모델 구조 + 입력 해상도 + batch
언제 오가나 레이어마다 한 번 읽음 한 레이어가 쓰고, 다음 레이어가 읽음

가중치 메모리와 활성값 메모리는 별개의 덩어리다. 이 둘을 합쳐서 "모델이 무겁다"고 뭉뚱그리면 왜 느린지를 놓친다. 합성곱 신경망에서는 초기 고해상도 레이어에서 활성값이 메모리를 지배하고, 후반 레이어와 분류 헤드에서 가중치가 지배한다. 이것이 표준 관찰이다(Stanford CS231n; Lin et al., MCUNetV2 2021). 그 까닭과 정확한 수치는 02장에서 직접 센다.

0.3 메모리 트래픽 — 추론 한 번에 오가는 바이트

이제 핵심 단어다. 메모리 트래픽(memory traffic) 은 추론 한 번 동안 메모리와 연산기 사이를 오가는 바이트의 총합이다. 기호로는 Q로 쓴다. 더 정확히는 주 메모리(DRAM)와 프로세서·온칩 캐시 사이를 오가는 전송 바이트 수다(Williams, Waterman, Patterson 2009).

여기서 중요한 구별이 하나 있다. 트래픽은 모델 크기가 아니라 데이터 이동량이다. 모델을 한 번 메모리에 올리는 일과, 추론할 때마다 숫자를 읽고 쓰는 일은 다르다. 가중치를 한 번 읽는 것도 트래픽에 들어가지만, 활성값은 레이어마다 새로 쓰고 다음 레이어가 다시 읽으므로 추론할 때마다 거듭 발생한다.

한 합성곱 레이어가 추론 한 번에 메모리와 주고받는 바이트는 깔끔하게 세 덩어리로 나뉜다.

weights read

Q

input activations read

output activations write

가중치 읽기 더하기 입력 활성값 읽기 더하기 출력 활성값 쓰기. 이 세 항을 더하는 법이 01장의 전부다.

한 가지 미리 밝혀 둔다. 실제로 칩이 옮기는 바이트는 이 합보다 작을 수 있다. 온칩 SRAM에 중간 텐서를 잠시 담아 두면 DRAM까지 안 내려가도 되기 때문이다. 이 책은 그런 절약을 빼고 모든 활성값이 메모리를 한 번 왕복한다고 보는 상한으로 센다. 이 가정의 경계는 05장에서 다룬다.

광고 · Advertisements

0.4 재사용 — 같은 바이트로 몇 번 일하나

트래픽이 왜 중요한지는 재사용(reuse) 이라는 말로 설명된다. 메모리에서 숫자 하나를 읽어 오는 데에는 비용이 든다. 그 한 번 읽은 숫자로 곱셈-덧셈을 여러 번 할 수 있다면, 읽기 비용을 여러 연산에 나눠 쓰는 셈이다. 이것이 재사용이 높은 경우다. 반대로 한 번 읽어 한 번만 쓰고 버리면 재사용이 낮다.

표준 합성곱은 가중치 재사용이 높다. 한 출력 채널의 커널이 입력의 모든 공간 위치에서 거듭 쓰이고, 채널끼리도 곱해지기 때문이다. 그래서 가중치 한 벌을 읽어 아주 많은 곱셈을 한다. 반대로 뒤에서 볼 depthwise 합성곱(채널별 합성곱)은 재사용이 낮다. 채널마다 커널이 딱 하나라, 같은 가중치로 할 수 있는 곱셈이 적다. 이 차이가 속도를 좌우한다.

0.5 연산강도 — 바이트당 연산 횟수

재사용을 하나의 숫자로 잰 것이 연산강도(arithmetic intensity) 다. 한 작업이 하는 일 W를 그 작업이 일으킨 메모리 트래픽 Q로 나눈 값이다.

I = W / Q     [연산/byte]

일을 곱셈-누산(MAC, multiply-accumulate) 횟수로 재면 단위는 MAC/byte다. 곱셈 하나와 덧셈 하나를 묶어 1 MAC으로 센다. 연산강도가 크다는 말은 바이트 하나를 옮길 때마다 연산을 많이 한다는 뜻이다. 작다는 말은 옮기기만 하고 연산은 별로 못 한다는 뜻이다.

depthwise 합성곱의 연산강도가 왜 낮은지를 한 줄로 풀면 이렇다. 채널당 커널이 하나뿐이라 가중치 바이트를 한 번 읽어 할 수 있는 곱셈이 적고, 큰 활성값 텐서는 통째로 읽고 써야 한다. 일은 적은데 옮길 바이트는 많으니 I = W/Q가 작아진다. 02장에서 이 값이 1.1 MAC/byte 언저리까지 떨어지는 것을 본다.

0.6 roofline — 연산이 병목인가, 대역폭이 병목인가

연산강도가 정해지면, 그 작업의 속도를 무엇이 막는지 판정할 수 있다. 그 판정 도구가 roofline 모델(대역폭-연산 한계선) 이다(Williams, Waterman, Patterson 2009).

칩에는 두 가지 천장이 있다. 하나는 연산 천장으로, 초당 할 수 있는 최대 연산 횟수 π다. 다른 하나는 대역폭 천장으로, 초당 옮길 수 있는 최대 바이트 β다. 실제로 낼 수 있는 성능 P는 둘 중 먼저 부딪히는 천장이 정한다.

P = min( π , β · I )
  π = 최대 연산 성능   [MAC/s]
  β = 최대 메모리 대역폭 [byte/s]
  I = 연산강도         [MAC/byte]

연산강도 I가 작을 때는 β · I가 작아서 대역폭 천장에 먼저 막힌다. I가 클 때는 β · I가 충분히 커져서 연산 천장 π에 막힌다. 두 천장이 만나는 지점의 연산강도를 변곡점(ridge) 이라 부르고, 그 값은 I = π/β다.

I ≥ π/β   →  compute-bound (연산 병목, π가 속도를 정함)
I < π/β   →  memory-bound  (대역폭 병목, β가 속도를 정함)

ridge보다 연산강도가 높으면 연산이 병목인 compute-bound(연산 한계) 영역이다. 연산기를 더 빠르게 하면 빨라진다. ridge보다 낮으면 대역폭이 병목인 memory-bound(대역폭 한계) 영역이다. 이 영역에서는 연산기를 아무리 키워도 소용없고, 메모리를 더 빨리 읽어 와야 빨라진다.

실제 칩의 ridge는 보통 수십에서 수백 MAC/byte에 있다. 05장에서 쓸 예시 칩의 ridge는 약 85 MAC/byte다. 그런데 MobileNet-v2의 연산강도는 모델 전체로 봐도 4.3 MAC/byte에 그친다. ridge보다 한참 아래다. 그래서 이 모델은 "곱셈은 적은데도" memory-bound이고, 메모리 트래픽이 속도를 정한다. 이 책이 메모리 트래픽을 세는 이유가 여기 있다.

용어 메모: 원논문은 고성능 컴퓨팅 맥락에서 "operational intensity"라 부르고, 이후 머신러닝·가속기 문헌은 "arithmetic intensity"를 흔히 쓴다. 같은 양이다. 이 책은 연산강도로 통일한다.

이제 어휘가 모두 갖춰졌다. 다음 장에서 한 레이어의 트래픽을 실제로 세어 본다.

광고 · Advertisements
이 시리즈 전체 챕터

학습경로 의존맵 보기 →