Connect with us

프롬프트 엔지니어링

대규모 언어 모델 추론 가속화: 효율적인 배포를 위한 기법

mm
LLM Inference Speed up

GPT-4, LLaMA, PaLM과 같은 대규모 언어 모델(LLM)은 자연어 처리의 가능성 경계를 넓혀가고 있습니다. 그러나 이러한 방대한 모델을 프로덕션 환경에 배포하는 것은 계산 요구 사항, 메모리 사용량, 지연 시간 및 비용 측면에서 상당한 과제를 제기합니다. LLM이 계속해서 더 커지고 능력이 향상됨에 따라, 실제 애플리케이션을 위해 추론 성능을 최적화하는 것은 매우 중요합니다.

이 기술 심층 분석에서는 LLM 추론을 가속화하여 더 빠른 응답 시간, 더 높은 처리량, 하드웨어 리소스의 더 효율적인 활용을 가능하게 하는 최첨단 기법들을 탐구해 보겠습니다. 수치 정밀도 기법과 새로운 어텐션 메커니즘부터 효율적인 텍스트 생성을 위해 명시적으로 맞춤화된 아키텍처 혁신에 이르기까지 다양한 방법을 다룰 것입니다.

먼저, LLM 추론이 기존 NLP 모델에 비해 왜 그렇게 어려운지 이해해 봅시다.

대규모 언어 모델의 추론 과제

LLM이 등장하기 전까지, 자연어 처리는 텍스트 분류, 개체명 인식, 감정 분석과 같은 특정 작업에 중점을 둔 더 작은 모델에 의존했습니다. 여전히 계산 집약적이었지만, 이러한 모델은 적당한 하드웨어에 배포될 수 있었고 비교적 직관적인 추론 과정을 따랐습니다.

반면, LLM은 패러다임의 전환을 나타냅니다. 이러한 모델은 수십억 개의 매개변수를 사용하여 방대한 데이터셋으로 훈련되어, 놀라운 숙련도로 광범위한 언어 작업을 수행할 수 있습니다. 그러나 이러한 힘은 훈련과 추론 모두에서 극적으로 증가한 계산 수요라는 대가를 치르게 합니다.

한 가지 핵심 과제는 LLM을 이용한 텍스트 생성의 자기회귀적 특성입니다. 인간과 같은 텍스트를 생성하기 위해, 이러한 모델은 한 번에 하나의 토큰(단어 또는 하위 단어)을 예측하며, 각 새로운 토큰은 이전에 생성된 출력에 의존합니다. 이 순차적 의존성은 효율적인 병렬화를 방해하고 시퀀스 길이에 따라 다항식적으로 확장되는 계산 요구 사항을 초래합니다.

또한, LLM은 고품질 텍스트 생성을 위해 필요한 컨텍스트를 설정하기 위해 긴 입력 시퀀스(프롬프트)를 요구하는 경우가 많습니다. 더 긴 입력 길이는 중간 상태와 어텐션 행렬을 저장하는 데 더 많은 메모리를 요구하여 하드웨어 리소스에 추가 부담을 줍니다.

이러한 독특한 과제들로 인해, 양자화와 정적 계산 그래프와 같은 전통적인 최적화 기법은 LLM 성능을 유지하면서 의미 있는 속도 향상을 제공하는 데 어려움을 겪을 수 있습니다. LLM 추론 가속화를 위해 명시적으로 맞춤화된 몇 가지 핵심 전략을 자세히 살펴보겠습니다.

수치 정밀도 기법

32비트에서 16비트 정밀도로

32비트에서 16비트 정밀도로

LLM 추론을 가속화하는 한 가지 방법은 모델 가중치와 활성화에 대해 감소된 수치 정밀도를 활용하는 것입니다. PyTorch 및 TensorFlow와 같은 현대적인 딥러닝 프레임워크는 일반적으로 기본적으로 32비트 부동 소수점(FP32) 정밀도를 사용합니다. 그러나 연구에 따르면, LLM은 종종 16비트(FP16), 8비트 정수(INT8) 또는 심지어 4비트 정수(INT4)와 같은 더 낮은 정밀도에서도 높은 정확도를 유지할 수 있습니다.

수치 정밀도를 낮추는 것은 몇 가지 이점을 제공합니다:

  • 감소된 메모리 사용량: 낮은 정밀도 표현은 더 적은 메모리를 필요로 하여, 동일한 하드웨어 제약 내에서 더 큰 모델 또는 배치 크기를 수용할 수 있게 합니다.
  • 더 빠른 계산: 많은 현대 CPU와 GPU는 낮은 정밀도 산술 연산을 위한 특수 명령어와 하드웨어 가속을 제공하여 상당한 속도 향상을 가능하게 합니다.
  • 향상된 에너지 효율: 더 작은 메모리 요구 사항과 더 빠른 계산으로 인해, 낮은 정밀도 추론은 에너지 소비 감소로 이어질 수 있습니다 – 엣지 및 모바일 배포에 있어 중요한 장점입니다.

강력하지만, 수치 정밀도 기법은 FP32 연산에 비해 약간의 정확도 손실을 초래합니다. 핵심은 특정 사용 사례에 대해 계산적 이득과 잠재적 성능 저하 사이의 균형을 신중하게 평가하는 것입니다.

LLM 양자화에는 두 가지 주요 접근 방식이 있습니다:

훈련 후 양자화 (PTQ): 이 방법에서는 LLM이 먼저 표준 FP32 정밀도를 사용하여 훈련됩니다. 훈련 후, 모델 가중치는 INT8 또는 INT4와 같은 낮은 정밀도 형식으로 양자화(변환)됩니다. PTQ는 구현하기 간단하지만 더 큰 정확도 하락을 초래할 수 있습니다.

양자화 인지 훈련 (QAT): QAT에서는 양자화 과정 자체가 훈련 단계 중에 시뮬레이션됩니다. 이를 통해 모델이 양자화 오류를 보상하는 방법을 학습하여, 최종 양자화된 모델이 배포될 때 정확도 저하를 최소화할 수 있습니다. QAT는 더 복잡하지만 종종 PTQ에 비해 더 나은 결과를 제공합니다.

실용적인 적용을 위해, Hugging Face와 같은 플랫폼에서 사용 가능한 사전 양자화된 모델을 활용할 수 있습니다. 이 플랫폼은 다양한 양자화 방법으로 최적화된 다양한 모델을 호스팅합니다. 예를 들어, Auto-GPTQ를 사용하여 양자화된 모델이 필요한 경우, 사용자는 Hugging Face의 transformers 라이브러리를 사용하여 쉽게 로드할 수 있습니다. 또한, 모델을 양자화하기 위해 AutoGPTQ와 같은 도구를 활용할 수 있으며, 이는 기존 라이브러리와 원활하게 통합되어 모델을 효율적으로 압축합니다. 다음은 Hugging Face transformers 라이브러리를 사용하여 사전 양자화된 Llama-2-7b 모델을 로드하는 예시입니다:

 from transformers import AutoModelForCausalLM, AutoTokenizer model_id = "TheBloke/Llama-2-7b-Chat-GPTQ" tokenizer = AutoTokenizer.from_pretrained(model_id) model = AutoModelForCausalLM.from_pretrained(model_id) 그리고 사용자 정의 양자화의 경우, AutoGPTQ 도구 키트를 사용하여 다음 단계를 따를 수 있습니다: from transformers import AutoModelForCausalLM, AutoTokenizer, GPTQConfig model_id = "llama-2-7b-original" tokenizer = AutoTokenizer.from_pretrained(model_id) quantization_config = GPTQConfig(bits=4, dataset="your-dataset", tokenizer=tokenizer) model = AutoModelForCausalLM.from_pretrained(model_id, quantization_config=quantization_config) 

양자화는 모델 품질을 유지하기 위해 양자화 후 미세 조정 또는 프롬프트 엔지니어링을 필요로 할 수 있다는 점을 기억하세요. 새로운 양자화의 경우, Hugging Face와 같은 플랫폼에 양자화된 모델을 푸시하여 커뮤니티에 기여할 수 있습니다. 특정 사용 사례에 대한 양자화 전략을 선택할 때는 항상 모델 크기, 계산 요구 사항 및 성능 사이의 균형을 유지하세요.  

플래시 어텐션 알고리즘

다중 헤드 어텐션 메커니즘은 트랜스포머 기반 LLM의 핵심 구성 요소로, 모델이 장거리 의존성과 맥락화된 표현을 포착할 수 있게 합니다. 그러나 이 어텐션 연산은 자기회귀적 텍스트 생성에 대해 계산적으로 비효율적입니다. 각 새로운 토큰에 대해 동일한 값 중 많은 부분을 재계산해야 하기 때문입니다.

FlashAttention 논문에서 소개된 플래시 어텐션 알고리즘은 어텐션 연산에 대해 더 메모리 효율적이고 병렬화에 친화적인 접근 방식을 제공합니다. 각 토큰에 대한 어텐션 값을 재계산하는 대신, 플래시 어텐션은 중간 키/값 행렬을 캐시하고 재사용하여 중복 계산을 피합니다.

이 최적화는 계산 오버헤드를 줄일 뿐만 아니라 메모리 액세스 패턴을 개선하여 GPU 메모리 대역폭과 병렬 처리의 활용도를 높입니다.

플래시 어텐션의 세부 사항은 상당히 복잡하지만, 높은 수준의 아이디어는 어텐션 연산을 두 단계로 분해하는 것입니다:

  1. 접두사 합 임베딩: 이 단계에서는 모든 입력 토큰에 대한 키/값 임베딩을 계산하고 캐시하여 생성 중에 효율적으로 재사용할 수 있게 합니다.
  2. 인과적 어텐션: 실제 어텐션 연산으로, 이제 첫 번째 단계에서 캐시된 키/값 임베딩을 활용하도록 최적화되었습니다.

이러한 단계를 분리함으로써, 플래시 어텐션은 고도로 병렬화된 GPU 연산의 이점을 취할 수 있어 LLM 추론의 어텐션 병목 현상을 상당히 가속화합니다.

다음은 LLM과 함께 플래시 어텐션을 구현하는 개념적인 간략한 예시입니다:

 from transformers import AutoModelForCausalLM import torch from flash_attention import flash_attention # OctoCoder와 같은 LLM 로드 model = AutoModelForCausalLM.from_pretrained("bigcode/octocoder") # 모델을 더 나은 코딩 어시스턴트로 이끄는 샘플 시스템 프롬프트 system_prompt = """... (system prompt details) ...""" # 시스템 프롬프트가 포함된 더 긴 입력 준비 long_prompt = system_prompt + "Question: Please write a function in Python that transforms bytes to Gigabytes." # 플래시 어텐션 최적화를 위해 모델 변환 model.to_bettertransformer() # 플래시 어텐션으로 모델 실행 start_time = time.time() with torch.backends.cuda.sdp_kernel(enable_flash=True): result = model.generate(long_prompt, max_new_tokens=60) print(f"Generated in {time.time() - start_time} seconds.") 

플래시 어텐션이 인상적인 성능 향상을 제공하지만, 이는 기존 트랜스포머 아키텍처 내에서 작동합니다. 가속화된 LLM 추론의 잠재력을 완전히 발휘하기 위해서는 이 작업에 특화된 아키텍처 혁신을 탐구해야 합니다.

LLM 가지치기

LLM 가지치기는 기능성을 유지하면서 모델 크기를 줄이는 기법입니다. 이는 헤세 행렬 근사를 기반으로 한 데이터 의존적 가중치 중요도 추정기를 사용합니다. 가지치기에서는 덜 중요한 가중치 그룹이 제거된 후, 모델이 정확도를 회복하도록 미세 조정됩니다. LLM-Pruner 패키지는 다양한 전략을 지원하는 가지치기 스크립트를 제공합니다. 가지치기에는 의존성 발견, 그룹 기여도 추정 및 간단한 사후 훈련을 포함하는 회복 단계가 포함됩니다. 다음은 LLaMa 모델에 LLM-Pruner 사용을 보여주는 간소화된 Python 코드 예시입니다:

 from transformers import AutoModelForSequenceClassification from pruning import LLMPruner # 사전 훈련된 LLaMa 모델 로드 model = AutoModelForSequenceClassification.from_pretrained("llama-base") # 원하는 구성으로 가지치기 도구 초기화 pruner = LLMPruner( model, pruning_ratio=0.25, block_mlp_layers=(4, 30), block_attention_layers=(4, 30), pruner_type='taylor' ) # 가지치기 실행 pruned_model = pruner.prune() # 가지치기된 모델 미세 조정 pruned_model.fine_tune(training_data) 

이 코드 스케치는 사전 훈련된 LLaMa 모델을 로드하고, 특정 구성(예: 어떤 레이어를 가지치기할지 및 가지치기 유형)으로 가지치기 도구를 설정하고, 가지치기 프로세스를 실행하며, 마지막으로 가지치기된 모델을 미세 조정하는 과정을 나타냅니다. 실제 구현을 위해서는 특정 모델 이름, 데이터 경로 및 미세 조정 프로세스에 대한 추가 매개변수와 같은 세부 사항을 채워야 합니다. 또한, 이 코드는 개념적 표현이며 실제 구문은 사용된 라이브러리 및 버전에 따라

I have spent the past five years immersing myself in the fascinating world of Machine Learning and Deep Learning. My passion and expertise have led me to contribute to over 50 diverse software engineering projects, with a particular focus on AI/ML. My ongoing curiosity has also drawn me toward Natural Language Processing, a field I am eager to explore further.