brunch

You can make anything
by writing

C.S.Lewis

by Qscar Feb 28. 2023

[AI]Optimization Technique 01

Intro & Quantization

Intro

모델의 메모리 사용과 레이턴시를 줄여줄 수 있는 최적화 방법에는 여러가지가 있다. 이러한 최적화 방법은 e-commerce, game, finance와 같이 빠른 시간 내에 많은 작업을 수행해야하는 비즈니스 영역에선 특히 중요하다.

이번 글에서 시작되는 최적화와 관련된 포스팅에서는 양자화, 가지치기와 같은 기본적인 방법부터 최근 각광받고 있는 Transformer 혹은 생성모델 등에서 사용되는 최적화 방법에 대해 다루고자 한다. ML Engineer들은 다음과 같은 방법을 사용한다.


Optimization Techniques

1. Quantization

2. Pruning

3. Distilation


본론부터 말하자면 Distillation은 가장 최적의 방법으로 알려진 방법 중 하나이며, Quantization(달리 '양자화'라고도 한다)은 대부분의 관련 라이브러리들에서 간단한 코드로 지원하는 가장 쉬운 방법이다. Pruning의 경우 가장 사용하기 어려운 방법이다.

일반적으로 위의 최적화 기법들은 독립적으로 사용되지 않는다. 가장 많은 이용자들이 참여하는 게임 중 하나인 Roblox의 블로그 글에 의하면, 아래 그림에서 볼 수 있다시피 DistillationQuantization을 결합한 방법으로 최적의 결과를 보였다고 한다.

Performance Improvement with Model Optimization - Image by Roblox

그들은 위 혼합 최적화 방법을 통해 적어도 30배 이상 빠른 성능을 보이고 있으며, 이는 추가적인 설비투자 없이도 30배 이상의 사람들에게 서비스를 제공하거나 더 적은 수의 인원들에게 더 쾌적한 서비스를 제공할 수 있다는 것을 의미한다.


이와 같이 실제 인공지능 모델을 서비스하기 위한 방법론들에 대해 간단한 코드와 설명, 관련 이미지를 이용해 정리해놓고자 한다.




1. Quantization


What is Quantization?

Quantization은 간단히 말해 연속적인 실수값(floating-point numbers)들을 이산화(dicretization)하는 것이다. 실수로 이루어진 원래의 값 [Fmax, Fmin]을 선형분포를 이용해 양자화된 값 [Qmax, Qmin]으로 바꾸는 것으로, 간단히 비유하자면 0에서 10 사이의 소수점까지를 표현해 [0, 0.0...01, ~9.9...99, 10]의 형태처럼 나오던 것을 정수형태로 딱 [0,1,2,...,9,10]과 같이 열 개로만 표현하는 식이다.


quantization effect on a transformer attention layer's weight

실제 Bert Model의 attention layer 하나가 가진 가중치를 양자화하기 전후로 나누면 위 그림과 같다. 위 그림을 구현하기 위해 huggingface hub를 통해 공개된 distilBert 모델을 불러와 그 중 하나의 attention 가중치를 Pytorch의 quantize_per_tensor 모듈을 통해 구현한 것으로 세부 코드는 아래와 같다.

code to compare between quantization and not


Quantized Tensor Performance

그렇다면 양자화로 인한 성능(속도) 향상은 어느정도일까? 소요시간을 비교해보자, 테스트 코드는 아래와 같다. 각기 양자화되지 않은 가중치와 양자화된 가중치끼리 행렬 곱 연산을 하는 경우이다. Pytorch의 경우, 양자화된 값끼리의 연산을 위해선 torch.nn.qauntized의 QFunctional이라는 모듈이 필요하다.


code to compare latency between normal and quantized one


그리고 위 코드의 결과는 아래와 같다.

result of test code(quantized one is about 5,500 times faster than normal one)


위에서 볼 수 있다시피 양자화된 가중치 간 연산은 무려 약 5,400배(2.15ms ≒ 396ns * 5,429)나 더 빠른 것으로 나타났다. 물론 이러한 성능은 위 코드를 실행하는 머신의 사양에 따라서도 꽤나 변화하는데, 내 랩탑에서는 약 100배 정도 빠른 성능으로 바뀌었다.

또한 Quantization양자화하기 전의 데이터 타입인 FP32보다 4배 적은 bit를 사용하는 INT8을 사용하기 때문에 메모리 사용량 또한 줄일 수 있다는 장점이 있다.


Two Quantization Strategies

조금 더 깊게 들어가면, 양자화에는 크게 두 가지 방법이 있다. 하나는 동적 양자화(Dynamic Quantization)이고, 다른 하나는 정적 양자화(Static Quantization)이다. 


동적 양자화는 학습 이후의 추론 단계에서만 진행되기에 학습 과정에서는 별다른 수정사항이 없다. 모델의 가중치와 활성화층이 즉시 INT8 타입으로 변환되며 양자화된다. 비록 INT8과 FP32 간의 변환 과정에서 성능적 병목이 발생할 수 있다는 단점이 있으나 가장 간단한 방법이고 다른 최적화 방법과의 결합성이 높다는 장점으로 인해 일반적으로 거의 모든 최적화 전략에 사용된다.


정적 양자화는 단계적으로 진행된다. 정적 양자화는 샘플 데이터셋으로부터 최적 패턴을 탐색해 INT8와 FP32 간의 변환에서 발생하는 병목 문제를 해결하고, 더 빠른 추론 속도를 위해 Quantization Schema를 계산한다. 그러나 이 방법 또한 문제가 존재하는데, 정적 양자화의 경우 샘플 데이터셋에 큰 영향을 받게 된다는 것이다. 마치 모델의 과적합과 같이 추출한 샘플 데이터셋이 대표성을 지니지 못하거나, 비정상적인 상황이 발생하거나, 기존 데이터셋과 성격이 다른 데이터가 들어오는 경우 등에 대해 정적 양자화는 낮은 성능을 보이곤 한다.


Quantized Model vs Not Quantized Model

위 이유로 인해 동적 양자화가 데이터 타입 변환 간 병목에도 불구하고 일반적으로 사용된다. 동적 양자화는 Pytorch, Tensorflow, Transformers 등의 거의 모든 딥러닝 라이브러리에서 쉽게 사용할 수 있는 모듈과 코드 등을 제공한다. 이를 통해 양자화된 모델의 성능을 확인해보자.


성능을 측정하기 위한 벤치마크 코드는 아래와 같다.

benchmark code

위 벤치마크 코드는 부여한 'optim_type'을 key값으로 하여 모델의 사이즈(mb)와 성능(accuracy), 그리고 latency를 측정해 value로 저장한다. 테스트할 모델은 정확도를 측정할 수 있도록 분류 문제에 파인튜닝된 모델이고, 이때 파인튜닝 데이터셋은 clinc_oos로 텍스트와 그 텍스트의 의도가 쌍으로 구성된 데이터셋이다.


모델을 로드하고 양자화하는 코드는 아래와 같다.

Load Model Code


이제 양자화하기 전후의 성능을 확인해보자.

Check Benchmark

위 그림에서 볼 수 있듯 양자화된 모델은 절반도 채 되지 않는 용량으로 20% 빠르며, 비슷한 수준의 성능을 내고 있다. 아마 100~10,000배 이상 빠른 결과를 기대했었겠지만, 아쉽게도 불가능하다. 왜냐하면 모델의 모든 부분을 양자화할 수 있는 것이 아니고(그랬다면 모델의 사이즈가 1/2이 아닌 1/4로 줄어들었을 것이다), 텐서화된 값을 처리하는 과정에서 양자화할 수 없거나, 해선 안되는 여러 병목들이 존재하기 때문이다.


그렇기 때문에 우리는 모델의 일부 층에 대해 가중치와 활성화 층 등을 양자화할 수 있을 뿐이며, 이로 인해 어느정도의 성능향상은 기대할 수 있지만 만족할만한 수준은 되지 않는다(엄밀히 말하면 추가적인 최적화 방법을 적용할 수 있기 때문에 만족하지 않는다). 때문에 모델 최적화는 단독적으로 사용되는 것이 아닌 다른 방법들과 함께 사용되며, 이후의 전략에 대해서는 다음 포스팅에서 정리하도록 한다.



[reference]

[1] https://medium.com/@quocnle/how-we-scaled-bert-to-serve-1-billion-daily-requests-on-cpus-d99be090db26

[2] https://huggingface.co/transformersbook

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari