LLM Outliers and LLM.int8
마지막 수정:
LLM에서 activation quantization이 어려운 이유는 단순히 값의 범위가 넓어서가 아니다.
문제는 일부 hidden dimension이 반복적으로 매우 큰 값을 만들고, 그 값이 모델 품질에 중요할 수 있다는 점이다.
대부분의 activation:
작고 비슷한 범위
일부 hidden dimension:
100배 이상 큰 값
layer마다 반복적으로 등장
품질에 큰 영향
이 outlier를 일반적인 per-tensor INT8 grid에 같이 넣으면 scale이 outlier를 보호하는 쪽으로 커진다. 그러면 정상적인 작은 값들은 integer grid의 아주 좁은 구간만 쓰게 된다.
outlier 하나가 scale을 결정
-> step size가 커짐
-> 정상 값들의 resolution이 사라짐
-> activation 정보가 뭉개짐
Clip하면 안 되는 outlier가 있다
일반적인 quantization에서는 큰 값을 조금 clip해서 대부분의 값을 더 촘촘하게 표현하는 선택을 할 수 있다.
하지만 LLM activation outlier는 그냥 noise가 아닐 수 있다. 특정 hidden dimension이 다음 token 예측에 중요한 방향을 담고 있다면, 그 값을 잘라내는 순간 layer output이 크게 바뀐다.
그래서 LLM에서는 질문이 달라진다.
outlier를 버릴 것인가?
보다 정확한 질문:
outlier는 보존하되, 나머지 값들의 INT8 resolution을 어떻게 지킬 것인가?
LLM.int8은 outlier를 분리한다
LLM.int8()의 선택은 간단하다.
normal dimensions -> INT8 path
outlier dimensions -> FP16 path
final output -> 두 path를 더함
이 방식은 activation 전체를 낮은 precision으로 밀어 넣지 않는다. 대부분의 dimension은 INT8 grid를 쓰고, 작은 수의 outlier dimension만 높은 precision path로 보낸다.
중요한 점은 outlier가 token 전체가 아니라 hidden dimension 단위로 나타날 수 있다는 것이다.
나쁜 해석:
이 token은 위험하니 전체를 FP16으로 보낸다
좋은 해석:
이 hidden dimension들이 outlier이므로 그 부분만 FP16으로 보낸다
그래서 LLM.int8은 activation quantization의 실패 모드를 “전체 INT8 실패”로 보지 않고, “일부 dimension만 별도 처리하면 INT8 path를 살릴 수 있는가”로 바꾼다.
GPTQ/AWQ와 다른 문제다
GPTQ와 AWQ는 주로 weight-only INT4 문제를 다룬다.
GPTQ / AWQ:
weight를 어떻게 4-bit로 저장할 것인가?
LLM.int8:
activation outlier 때문에 INT8 matmul이 망가지는가?
둘은 같이 쓰일 수도 있지만, 해결하는 병목은 다르다. GPTQ/AWQ는 weight memory traffic을 줄이는 쪽이고, LLM.int8은 activation outlier를 피하면서 INT8 경로를 쓰는 쪽이다.
확인
- LLM activation outlier를 단순히 clip하면 위험한 이유는 무엇인가?
- LLM.int8이 전체 activation을 FP16으로 되돌리지 않고도 품질을 지키는 방식은 무엇인가?
- GPTQ/AWQ와 LLM.int8은 각각 어떤 tensor의 문제를 다루는가?