AMD Quark

AMD Quark

양자화는 최소한의 정확도 손실로 메모리와 대역폭 사용을 효과적으로 줄이고 계산을 가속하며 처리량을 높일 수 있어요. vLLM은 유연하고 강력한 양자화 툴킷인 Quark 를 활용해 AMD GPU에서 실행할 고성능 양자화 모델을 만들 수 있습니다. Quark는 가중치, 활성화, kv-cache 양자화로 대규모 언어 모델을 양자화하는 특화 지원과 AWQ, GPTQ, Rotation, SmoothQuant 같은 최첨단 양자화 알고리즘을 갖추고 있어요.

출처: 문서

본문

Quark 설치 (Quark Installation)

모델을 양자화하기 전에 Quark를 설치해야 합니다. 최신 Quark 릴리즈는 pip으로 설치할 수 있어요.

pip install amd-quark

더 자세한 설치 내용은 Quark 설치 가이드 를 참고하세요.

또한 평가를 위해 vllmlm-evaluation-harness 를 설치합니다.

pip install vllm "lm-eval[api]>=0.4.12"

양자화 과정 (Quantization Process)

Quark 설치 후 예시로 Quark 사용법을 보여드릴게요. Quark 양자화 과정은 아래 5단계로 요약할 수 있습니다.

  1. 모델 로드
  2. 보정 데이터로더 준비
  3. 양자화 구성 설정
  4. 모델 양자화 및 내보내기
  5. vLLM에서 평가

1. 모델 로드 (Load the Model)

Quark는 Transformers 를 사용해 모델과 토크나이저를 가져옵니다.

from transformers import AutoTokenizer, AutoModelForCausalLM

MODEL_ID = "meta-llama/Llama-2-70b-chat-hf"
MAX_SEQ_LEN = 512

model = AutoModelForCausalLM.from_pretrained(
    MODEL_ID,
    device_map="auto",
    dtype="auto",
)
model.eval()

tokenizer = AutoTokenizer.from_pretrained(MODEL_ID, model_max_length=MAX_SEQ_LEN)
tokenizer.pad_token = tokenizer.eos_token

2. 보정 데이터로더 준비 (Prepare the Calibration Dataloader)

Quark는 PyTorch Dataloader 를 사용해 보정 데이터를 로드합니다. 보정 데이터셋을 효율적으로 사용하는 자세한 방법은 Adding Calibration Datasets 를 참고하세요.

from datasets import load_dataset
from torch.utils.data import DataLoader

BATCH_SIZE = 1
NUM_CALIBRATION_DATA = 512

# Load the dataset and get calibration data.
dataset = load_dataset("mit-han-lab/pile-val-backup", split="validation")
text_data = dataset["text"][:NUM_CALIBRATION_DATA]

tokenized_outputs = tokenizer(
    text_data,
    return_tensors="pt",
    padding=True,
    truncation=True,
    max_length=MAX_SEQ_LEN,
)
calib_dataloader = DataLoader(
    tokenized_outputs['input_ids'],
    batch_size=BATCH_SIZE,
    drop_last=True,
)

3. 양자화 구성 설정 (Set the Quantization Configuration)

양자화 구성을 설정해야 합니다. 자세한 내용은 quark config guide 를 확인하세요. 여기서는 가중치, 활성화, kv-cache에 FP8 per-tensor 양자화를 사용하며 양자화 알고리즘은 AutoSmoothQuant입니다.

참고: 양자화 알고리즘은 JSON 구성 파일이 필요하며, 해당 파일은 Quark PyTorch examples 안의 examples/torch/language_modeling/llm_ptq/models 디렉터리에 있습니다. 예를 들어 Llama용 AutoSmoothQuant 구성 파일은 examples/torch/language_modeling/llm_ptq/models/llama/autosmoothquant_config.json 입니다.

from quark.torch.quantization import (Config, QuantizationConfig,
                                    FP8E4M3PerTensorSpec,
                                    load_quant_algo_config_from_file)

# Define fp8/per-tensor/static spec.
FP8_PER_TENSOR_SPEC = FP8E4M3PerTensorSpec(
    observer_method="min_max",
    is_dynamic=False,
).to_quantization_spec()

# Define global quantization config, input tensors and weight apply FP8_PER_TENSOR_SPEC.
global_quant_config = QuantizationConfig(
    input_tensors=FP8_PER_TENSOR_SPEC,
    weight=FP8_PER_TENSOR_SPEC,
)

# Define quantization config for kv-cache layers, output tensors apply FP8_PER_TENSOR_SPEC.
KV_CACHE_SPEC = FP8_PER_TENSOR_SPEC
kv_cache_layer_names_for_llama = ["*k_proj", "*v_proj"]
kv_cache_quant_config = {
    name: QuantizationConfig(
        input_tensors=global_quant_config.input_tensors,
        weight=global_quant_config.weight,
        output_tensors=KV_CACHE_SPEC,
    )
    for name in kv_cache_layer_names_for_llama
}
layer_quant_config = kv_cache_quant_config.copy()

# Define algorithm config by config file.
LLAMA_AUTOSMOOTHQUANT_CONFIG_FILE = "examples/torch/language_modeling/llm_ptq/models/llama/autosmoothquant_config.json"
algo_config = load_quant_algo_config_from_file(LLAMA_AUTOSMOOTHQUANT_CONFIG_FILE)

EXCLUDE_LAYERS = ["lm_head"]
quant_config = Config(
    global_quant_config=global_quant_config,
    layer_quant_config=layer_quant_config,
    kv_cache_quant_config=kv_cache_quant_config,
    exclude=EXCLUDE_LAYERS,
    algo_config=algo_config,
)

4. 모델 양자화 및 내보내기 (Quantize the Model and Export)

그 다음 양자화를 적용할 수 있습니다. 양자화 후 내보내기 전에 먼저 양자화된 모델을 동결(freeze)해야 해요. HuggingFace safetensors 형식으로 모델을 내보내야 하며, 더 자세한 내보내기 형식 내용은 HuggingFace format exporting 를 참고하세요.

import torch
from quark.torch import ModelQuantizer, ModelExporter
from quark.torch.export import ExporterConfig, JsonExporterConfig

# Apply quantization.
quantizer = ModelQuantizer(quant_config)
quant_model = quantizer.quantize_model(model, calib_dataloader)

# Freeze quantized model to export.
freezed_model = quantizer.freeze(model)

# Define export config.
LLAMA_KV_CACHE_GROUP = ["*k_proj", "*v_proj"]
export_config = ExporterConfig(json_export_config=JsonExporterConfig())
export_config.json_export_config.kv_cache_group = LLAMA_KV_CACHE_GROUP

# Model: Llama-2-70b-chat-hf-w-fp8-a-fp8-kvcache-fp8-pertensor-autosmoothquant
EXPORT_DIR = MODEL_ID.split("/")[1] + "-w-fp8-a-fp8-kvcache-fp8-pertensor-autosmoothquant"
exporter = ModelExporter(config=export_config, export_dir=EXPORT_DIR)
with torch.no_grad():
    exporter.export_safetensors_model(
        freezed_model,
        quant_config=quant_config,
        tokenizer=tokenizer,
    )

5. vLLM에서 평가 (Evaluation in vLLM)

이제 LLM 엔트리포인트를 통해 Quark 양자화 모델을 직접 로드해 실행할 수 있습니다.

from vllm import LLM, SamplingParams

# Sample prompts.
prompts = [
    "Hello, my name is",
    "The president of the United States is",
    "The capital of France is",
    "The future of AI is",
]
# Create a sampling params object.
sampling_params = SamplingParams(temperature=0.8, top_p=0.95)

# Create an LLM.
llm = LLM(
    model="Llama-2-70b-chat-hf-w-fp8-a-fp8-kvcache-fp8-pertensor-autosmoothquant",
    kv_cache_dtype="fp8",
    quantization="quark",
)
# Generate texts from the prompts. The output is a list of RequestOutput objects
# that contain the prompt, generated text, and other information.
outputs = llm.generate(prompts, sampling_params)
# Print the outputs.
print("\nGenerated Outputs:\n" + "-" * 60)
for output in outputs:
    prompt = output.prompt
    generated_text = output.outputs[0].text
    print(f"Prompt:    {prompt!r}")
    print(f"Output:    {generated_text!r}")
    print("-" * 60)

또는 lm_eval 로 정확도를 평가할 수 있습니다.

lm_eval --model vllm \
  --model_args pretrained=Llama-2-70b-chat-hf-w-fp8-a-fp8-kvcache-fp8-pertensor-autosmoothquant,kv_cache_dtype='fp8',quantization='quark' \
  --tasks gsm8k

Quark 양자화 스크립트 (Quark Quantization Script)

위 Python API 예시 외에도 Quark는 대규모 언어 모델을 더 편리하게 양자화하는 양자화 스크립트 를 제공합니다. 다양한 양자화 체계와 최적화 알고리즘으로 모델을 양자화하는 것을 지원하며, 양자화 모델을 내보내고 평가 작업을 즉시 실행할 수 있습니다. 이 스크립트로 위 예시는 다음과 같이 할 수 있어요.

python3 quantize_quark.py --model_dir meta-llama/Llama-2-70b-chat-hf \
                          --output_dir /path/to/output \
                          --quant_scheme w_fp8_a_fp8 \
                          --kv_cache_dtype fp8 \
                          --quant_algo autosmoothquant \
                          --num_calib_data 512 \
                          --model_export hf_format \
                          --tasks gsm8k

OCP MX(MXFP4, MXFP6) 모델 사용 (Using OCP MX models)

vLLM은 Open Compute Project (OCP) 사양 을 준수하는 AMD Quark로 오프라인 양자화된 MXFP4 및 MXFP6 모델의 로드를 지원합니다.

이 체계는 현재 활성화에 대한 동적 양자화만 지원합니다.

최신 AMD Quark 릴리즈 설치 후 사용 예시:

vllm serve fxmarty/qwen_1.5-moe-a2.7b-mxfp4 --tensor-parallel-size 1
# or, for a model using fp6 activations and fp4 weights:
vllm serve fxmarty/qwen1.5_moe_a2.7b_chat_w_fp4_a_fp6_e2m3 --tensor-parallel-size 1

OCP MX 연산을 네이티브로 지원하지 않는 디바이스(예: AMD Instinct MI325, MI300, MI250)에서는 퓨즈드 커널을 사용해 FP4/FP6에서 절반 정밀도로 가중치를 실시간 디양자화하는 MXFP4/MXFP6 행렬 곱셈 실행 시뮬레이션을 수행할 수 있어요. 이는 예를 들어 vLLM으로 FP4/FP6 모델을 평가하거나, (~2.5-4x의 메모리 절감을 float16/bfloat16과 비교해) 활용하는 데 유용합니다.

MXFP4 데이터 타입으로 양자화된 오프라인 모델을 생성하는 가장 쉬운 방법은 AMD Quark의 양자화 스크립트 를 사용하는 것입니다. 예시:

python quantize_quark.py --model_dir Qwen/Qwen1.5-MoE-A2.7B-Chat \
    --quant_scheme w_mxfp4_a_mxfp4 \
    --output_dir qwen_1.5-moe-a2.7b-mxfp4 \
    --skip_evaluation \
    --model_export hf_format \
    --group_size 32

현재 통합은 가중치나 활성화에 사용되는 모든 FP4, FP6_E3M2, FP6_E2M3 조합 을 지원합니다.

Quark 양자화 레이어별 자동 혼합 정밀도(AMP) 모델 사용

vLLM은 AMD Quark로 양자화된 레이어별 혼합 정밀도 모델의 로드도 지원합니다. 현재 {MXFP4, FP8}의 혼합 체계가 지원되며, 여기서 FP8은 FP8 per-tensor 체계를 나타냅니다. 더 많은 혼합 정밀도 체계가 곧 지원될 예정입니다.

  • 각 레이어에 대한 옵션으로 미양자화 Linear 및/또는 MoE 레이어, 즉 {MXFP4, FP8, BF16/FP16} 혼합.
  • MXFP6 양자화 확장, 즉 {MXFP4, MXFP6, FP8, BF16/FP16}.

주어진 기기에서 지원되는 가장 낮은 정밀도(예: AMD Instinct MI355에서는 MXFP4, AMD Instinct MI300에서는 FP8)를 사용해 서빙 처리량을 극대화할 수 있지만, 이런 공격적인 체계는 목표 작업에서 양자화에서 회복되는 정확도에 해로울 수 있어요. 혼합 정밀도는 정확도와 처리량 극대화 사이의 균형을 잡을 수 있게 합니다.

AMD Quark로 양자화된 혼합 정밀도 모델을 생성하고 배포하는 두 가지 단계가 있습니다.

1. AMD Quark에서 혼합 정밀도로 모델 양자화

먼저 주어진 LLM 모델에 대한 레이어별 혼합 정밀도 구성을 검색한 다음 AMD Quark로 양자화합니다. 자세한 튜토리얼은 Quark API와 함께 나중에 제공될 예정입니다.

예시로, vLLM에서 사용법과 정확도 이점을 보여주는 바로 사용 가능한 양자화 혼합 정밀도 모델을 제공합니다.

  • amd/Llama-2-70b-chat-hf-WMXFP4FP8-AMXFP4FP8-AMP-KVFP8
  • amd/Mixtral-8x7B-Instruct-v0.1-WMXFP4FP8-AMXFP4FP8-AMP-KVFP8
  • amd/Qwen3-8B-WMXFP4FP8-AMXFP4FP8-AMP-KVFP8

2. vLLM에서 양자화 혼합 정밀도 모델 추론

AMD Quark로 혼합 정밀도를 사용해 양자화된 모델은 vLLM에서 네이티브로 다시 로드될 수 있으며, 예를 들어 lm-evaluation-harness로 다음과 같이 평가할 수 있습니다.

lm_eval --model vllm \
    --model_args pretrained=amd/Llama-2-70b-chat-hf-WMXFP4FP8-AMXFP4FP8-AMP-KVFP8,tensor_parallel_size=4,dtype=auto,gpu_memory_utilization=0.8,trust_remote_code=False \
    --tasks mmlu \
    --batch_size auto

온라인 양자화 (Online Quantization)

위의 모든 워크플로우는 오프라인 양자화입니다. 스크립트를 실행하고 새 양자화 체크포인트를 디스크에 쓴 다음 나중에 서빙을 위해 로드합니다. 이 방식은 내보내기 중 정확도 회복 알고리즘(rotation, SmoothQuant, GPTQ, AWQ)을 실행할 수 있어 가장 정확하고 가장 작은 체크포인트를 만들지만, 별도의 양자화 단계와 디스크의 모델 두 번째 복사본이 필요합니다.

온라인 양자화는 대신 고정밀도 체크포인트에서 직접 로드 시점에 가중치를 양자화하며, 오프라인 흐름보다 여러 이점이 있습니다.

  • 내보내기 단계 없음 — 원본 bf16 / fp16 체크포인트에서 직접 서빙합니다. 배포 전 별도의 양자화 실행이 필요 없습니다.
  • 추가 디스크 풋프린트 없음 — 아무것도 디스크에 새로 쓰이지 않아 저장하거나 관리할 모델의 두 번째 사본이 없습니다.
  • 보정 데이터 없음 — 활성화가 런타임에 동적으로 스케일링되므로 보정 데이터셋이 필요 없습니다.
  • 빠른 반복 — 재내보내기 없이 구성 변경만으로 체계나 per-layer 선택을 즉시 바꿉니다.

vLLM 온라인 양자화

vLLM은 내보내기 단계를 건너뛰는 내장 온라인 양자화 를 갖고 있습니다. 일반적인 고정밀도(bf16) 체크포인트를 로드하고 사전 양자화된 체크포인트나 보정 데이터 없이 로드 시점에 각 레이어의 가중치를 FP8이나 MXFP4 같은 체계로 양자화합니다. 새 체크포인트는 디스크에 쓰이지 않습니다. 지원 체계와 구성은 Online Quantization 을 참고하세요.

Quark 온라인 양자화

AMD Quark는 Quark의 오프라인 내보내기와 per-layer 혼합 정밀도 구성의 패리티를 원하는 사용자를 위해 quark_online 양자화 백엔드로 노출되는 자체 온라인 경로를 제공합니다. vLLM의 내장 온라인 양자화처럼 가중치 로딩 훅 안에서 가중치를 양자화하며 서빙 직전에 수행하고 새 체크포인트는 쓰지 않습니다.

그 양자화 수학은 Quark의 오프라인 내보내기와 바이트 단위로 정렬되어, 온라인에서 검증한 것이 오프라인에서 얻는 것과 같습니다. 원하는 체계와 per-layer 선택을 찾는 데 사용하세요.

vLLM의 내장 온라인 양자화와 비교해 quark_online 플러그인은 다음을 추가합니다.

  • 유연한 구성 파싱 — 간결한 구성이 Quark의 상세한 per-layer 구성으로 확장되며, 모든 per-layer 매칭을 실제 QuarkConfig 에 위임합니다.
  • Per-layer / 혼합 체계 — 레이어별로 다른 메서드를 디스패치합니다(예: MoE 모델에서 FP8 attention을 가진 MXFP4 전문가). 각 온라인 메서드는 해당 오프라인 체계를 서브클래싱하므로, 로드 시점에 양자화된 레이어는 오프라인 레이어와 동일한 추론 커널을 실행합니다.
  • 이미 양자화된 체크포인트 재양자화 — FP8 block-scale 체크포인트(예: DeepSeek-R1)가 로드 시점에 레이어 로컬로 디양자화되고 대상 체계로 재양자화되며 새 체크포인트는 없습니다.

플러그인은 AMD Quark에 포함되어 있습니다. vLLM 포크도, 패치된 체크포인트 형식도 필요 없습니다. 자세한 내용은 Quark 문서 를 참고하세요. 바로 사용할 수 있는 세 가지 프리셋이 제공됩니다.

프리셋 키 체계
ptpc_fp8 FP8 E4M3, per-channel 가중치 + 동적 per-token 활성화
mxfp4 MXFP4, per-group(그룹 크기 32) + E8M0 블록 스케일
linear_ptpc_fp8_moe_mxfp4 혼합: attention은 FP8, MoE 전문가는 MXFP4

Python API

from vllm import LLM, SamplingParams
from quark.online_quantization.vllm import HF_QUANTIZATION_CONFIGS

llm = LLM(
    model="Qwen/Qwen3-30B-A3B-Thinking-2507",
    quantization="quark_online",
    hf_overrides=HF_QUANTIZATION_CONFIGS["ptpc_fp8"],
    enforce_eager=True,
    tensor_parallel_size=1,
)
out = llm.generate(["The capital of France is"], SamplingParams(temperature=0.0, max_tokens=100))
print(out)

네이티브 vLLM CLI

export VLLM_PLUGINS="${VLLM_PLUGINS:-quark_online_quant}"
ONLINE_QUANT_CONFIG='{"online_quant_config": {"global_quant_config": "ptpc_fp8", "exclude_layer": ["lm_head"]}}'

vllm serve Qwen/Qwen3-8B \
  --trust-remote-code \
  --tensor-parallel-size 1 \
  --additional-config "$ONLINE_QUANT_CONFIG"

오프라인 체크포인트 재양자화

추가 인자는 없습니다. 같은 hf_overrides 메커니즘이 체크포인트의 기존 구성(hf_quant_config)을 감지하고 자동으로 병합합니다.

llm = LLM(
    model="deepseek-ai/DeepSeek-R1",           # ships quant_method: "fp8"
    quantization="quark_online",
    hf_overrides=HF_QUANTIZATION_CONFIGS["ptpc_fp8"],
    tensor_parallel_size=8,
)

플러그인은 QUARK_DISABLE_VLLM_PLUGIN=1 로 비활성화할 수 있고, 다른 플랫폼 플러그인(예: ATOM)이 이미 백엔드를 인계한 경우 자동으로 물러납니다.

더 알아보기 (Learn more)