-
FP32, TF32, FP16, BF16, Mixed Precision에 대한 이해자연어처리(NLP)와 인공지능(AI) 2024. 10. 3. 09:05
본 글은 [Open-Up] 오픈소스 소프트웨어 통합지원센터에 지원받아 작성하였습니다.
언어 모델은 data science와 computer science의 절묘한 조합이라고 생각합니다.
특히, LLM 쪽으로 넘어갈수록 인프라의 한계를 마주하기에, 자원에 대한 이해가 필수입니다.
오늘은 컴퓨터가 우리의 data(모델 가중치, input, output 등)를 어떤 format으로 저장하는지
(이를 '부동소수점 표현'이라 한다.)에 대해 정리해보겠습니다.
아래 내용부터는 편하게 평서문으로 작성합니다.
FP32, TF32, FP16, BFLOAT16, Mixed Precision의 개념
위 그림은 nividia에서 FP32와 TF32, FP16, BF16의 부동소수점 표현방식을 표현한 그림이다.
- 어떤 포맷이든, 공통적으로 모든 부동소수점 표현 방식은 1bit를 부호용(+/-)으로 사용한다.
- Range(범위) 또는 Exponential(지수)라 불리는 부분은 2**E로서 '수의 범위', 즉, '자릿수'를 표현하는데 활용된다.
- Precision(정밀도) 또는 Mantissa(가수)라 불리는 부분은 '자릿수'를 제외한 '수의 생김새'를 표현하는데 활용된다.
- 예를 들어, -18.875에 대해 fp32로 표현해보자.
- 18.875는 음수이므로 sign bit = 1이 될 것이고, 18.875에 대한 2진수 표현은 10010.111이 된다.(설명 생략)
- 소수점을 4칸 이동하면 1.0010111 * 2^4 로 표현할수 있다.
- 따라서, sign bit = 1, E = 4, M = 001011100~000 이 된다.(지수 부분은 사실 bias라는 과정을 거쳐, 4+127 = 131로, 10000011 되어야 한다. 여기선 생략하자.)
- 따라서, fp32는 1 00000100 00101110000000000000000 로 표현될 것이다.
1. FP32는 Precision에 23bit나 할당하기때문에 '표현력'이 좋다. 대신에 그만큼 메모리 할당과 연산에 비용이 든다.
- 널리 쓰이는 방식이며, 대부분의 하드웨어는 FP32를 지원한다.
- 32bit 즉, 4 Byte를 할당받는 방식을 Full-Precision이라고도 표현한다.
2. FP16은 이런 부분을 개선하고자. Range도 5bit로 줄이고, Precision도 10bit로 줄였다.
- 계산량과 메모리 할당 부담이 줄겠지만,대신에 Range의 표현범위가 적으므로 '오버플로우' 또는 '언더플로우'의 위험이 존재한다.
- 또한, Precision의 bit도 줄었으므로 수의 생김새를 표현할 '표현력' 자체도 줄어들었다.
- 낮은 정밀도가 성능에 크게 영향을 끼치지 않는다는 전제를 통해서,일반적으로 딥러닝에서 FP32보다는 FP16을 더 선호하는 경향을 보인다.
- 16bit 즉, 2 Byte를 할당받는 방식을 Half-Precision이라고도 표현한다.
3. BF16은 FP32와 같이 8 bits를 지수부에 사용하지만, 가수부는 7 bits를 적용하여 '표현력'을 fp32/fp16에 비해 제일 줄인 포맷이 된다.
- 큰 숫자에는 문제가 없겠지만 수의 생김새를 표현하는 '표현력'에는 문제가 생길수 있다.
- fp16보다는 선호도가 낮은 것 같다.(개인적 의견)
4. 여기에 NVIDIA에서는 FP32와 FP16의 중간격인 TF32(TensorFloat 32)라는 독특한 format을 제시했는데, 총 bit수가 19bit가 되는 어정쩡(?)한 format이다.
- Range는 8bit를 적용하여, FP32의 '자릿수 범위'를 그대로 사용할수 있도록 하였다.
- 대신에, Precision은 10 bit를 적용하여, FP16과 동일한 수준의 '수의 생김새'를 표현할 '표현력'을 갖도록 했다.
- NVIDIA는 cuDNN 라이브러리의 기본 포맷으로 TF32를 채택했다.일반적인 Python/Torch 수준의 코드에서는 적용할 일이 없을 것 같다.
컴파일러 지원이 내부 깊숙한 수준, 즉 CUDA 컴파일러 내부에서 필요하다.
5. Mixed Precision : Mixed Precision은 fp16와 fp32를 섞어가며 모델학습에 활용하는 방식이다. 현재 많이 활용되고 있다. (Mixed Precision Training 라는 논문으로 ICLR에 2018에 게재됨)
- fp32의 모델의 가중치는 fp32(마스터)와 fp16(복사본) 2개로 저장.
- fp32의 입력 데이터는 fp16 형식으로 변환하여 계산 (이때, scaling 적용)
- forward/backward 모두 계산과정에서는 fp16으로 계산
- fp 16형식으로 계산하는 과정에서 숫자의 정밀도가 손실될 가능성이 존재하므로,가중치 업데이트시, fp16으로 나온 최종 gradient값을 fp32로 변경하고(descaling과 gradient clipping 적용),
모델의 마스터 가중치(fp32)에 적용하여 업데이트함. 이를 통해 정밀도를 일부 보완.
- 업데이트 된 모델의 마스터 가중치(fp32)를 fp16의 복사본으로 재저장(덮어쓰기)
- 위 과정이 step(가중치 갱신시기)마다 반복됨
- 학습이 완료되면, 모델의 가중치를 fp32로 재변환하여 저장.
- 이러한 방식을 통해, 계산시의 메모리 할당 / 계산량 부담을 완화함.
- 추론시에는 fp16도 어느정도 퀄리티를 보장하므로, 상황에 따라 fp16으로 바꿔서 추론하기도 함.
- 모델 복사본을 하나 더 만드는데, 메모리 효율성이 있는지? :더보기모델의 weight를 복사본으로 하나 더 가지고 있는게, 메모리 부담이 되는건 맞지만 실제로 훈련 중에 메모리의 비중을 많이 차지하는건 역전파에서의 activation이라고 한다.
이 역전파 activation을 fp16으로 저장하는 행위가 전체적으로 봤을때는 훨씬 메모리 비용 효율적이 된다고 한다.
"""논문 번역본 : FP32 학습과 비교해 추가적인 가중치 사본을 유지하면 메모리 요구량이 50% 증가하지만, 전체 메모리 사용에 미치는 영향은 훨씬 적습니다. 훈련 중 메모리 소비는 배치 크기와 각 레이어의 활성화 값을 다시 사용하기 위해 저장하는 역전파 패스에서의 활성화 값에 의해 지배됩니다. 활성화 값도 FP16 형식으로 저장되므로, 딥러닝 모델을 훈련할 때 전체 메모리 소비는 대략 절반으로 줄어듭니다."""앞서 얘기한 것과 같이, fp16을 활용해도 성능에 크게 차이가 없는 경우가 있다.
아래는 AWS 컨퍼런스에서 발표된 자료로, 임베딩을 fp32, fp16으로 적용했을때의 성능 차이를 보인 표이다.
해당 자료에서는 성능의 차이가 보이지 않는다. 따라서, 추론시 fp16을 해도 무방할 때가 있다.Format 별 속도에 대한 차이
그림처럼, FP16이 BF16보다 속도에서 비슷하거나, 근소 우세한 것으로 보인다.
Tensor Core 활용 기준으로, TF32 < BF16 = FP16
전체적인 기준으로, FP32 < TF32 < BF16 <= FP16 정도로 볼수 있지 않을까 싶다.Format 별 성능에 대한 차이
에 대한 제대로 된 벤치마크/성능 비교 결과는 찾기 어려웠다.
vllm에서 가끔씩 양자화된 포맷과 fp16을 비교해서 올려놓기는 하는 것 같다.차후, 비교 결과를 찾게되면 업데이트 할 계획이다.아래 그림은 fp16, fp8 등을 적용한 성능 비교표이다.
참고로 fp32의 llama3 8B의 MMLU 성능은 0.666이다. 크게 차이가 나지는 않는 모습이다.728x90'자연어처리(NLP)와 인공지능(AI)' 카테고리의 다른 글
Last_hidden_state와 Logit (5) 2024.09.24 Batch Size, Iteration, Step, Epoch 이해하기 (4) 2024.09.22 왜 대부분의 LLM은 Decoder-only 형태로 구현되는걸까 (2) 2024.06.05 문장 기반 임베딩 모델의 Semi-supervised 학습 방법 (0) 2024.05.23 음성인식에서 쓰이는 FFT(Fast Fourier Transform)와 STFT(Short Time Fourier Transform) 그리고 Spectrogram의 개념과 차이점 (0) 2024.05.23