Views
No views yet
nn.Linear layers: per-tensor activations / per-row weightsexperts.gate_up_proj, experts.down_proj): per-row activations / per-row weights via FqnToConfiglm_head, router[!NOTE] zentorch v2.11.0.1 for PyTorch v2.11.0 has to be built from source.
1import os
2from collections import OrderedDict
3
4import torch
5from transformers import AutoModelForCausalLM, AutoTokenizer, TorchAoConfig
6from torchao.quantization import (
7 Int8DynamicActivationInt8WeightConfig,
8 quantize_,
9)
10from torchao.quantization.granularity import PerRow
11from torchao.quantization.quant_api import FqnToConfig
12from torchao.quantization.quant_primitives import MappingType
13
14MODEL_ID = "unsloth/gpt-oss-20b-BF16"
15OUTPUT_DIR = "amd/gpt-oss-20b-da8w8-torchao-v0.17.0"
16os.makedirs(OUTPUT_DIR, exist_ok=True)
17
18# Pass 1: standard dynamic-act / weight INT8 for nn.Linear layers.
19# Skip lm_head and router (kept in BF16).
20ao_config = Int8DynamicActivationInt8WeightConfig(
21 version=2,
22 act_mapping_type=MappingType.SYMMETRIC,
23)
24quantization_config = TorchAoConfig(
25 ao_config,
26 modules_to_not_convert=["lm_head", "router"],
27)
28
29quantized_model = AutoModelForCausalLM.from_pretrained(
30 MODEL_ID,
31 dtype=torch.bfloat16,
32 device_map="cpu",
33 quantization_config=quantization_config,
34 trust_remote_code=True,
35)
36
37# Pass 2: quantize MoE expert weights that the TorchAoConfig pass skipped
38# because they live as nn.Parameter tensors, not nn.Linear modules.
39# Use per-row granularity on activations and weights for expert tensors.
40ao_config_experts = Int8DynamicActivationInt8WeightConfig(
41 version=2,
42 act_mapping_type=MappingType.SYMMETRIC,
43 granularity=(PerRow(dim=-1), PerRow(dim=1)),
44)
45
46# Match the MoE expert parameter tensors via their fully-qualified names.
47expert_fqn_config = FqnToConfig(
48 fqn_to_config=OrderedDict({
49 r"re:.*\.experts\.gate_up_proj$": ao_config_experts,
50 r"re:.*\.experts\.down_proj$": ao_config_experts,
51 })
52)
53
54quantize_(quantized_model, expert_fqn_config, filter_fn=None)
55
56quantized_model.save_pretrained(OUTPUT_DIR)
57
58tokenizer = AutoTokenizer.from_pretrained(MODEL_ID, trust_remote_code=True)
59tokenizer.save_pretrained(OUTPUT_DIR)
60
61# Smoke test
62inputs = tokenizer("What are we having for dinner?", return_tensors="pt")
63out = quantized_model.generate(**inputs, max_new_tokens=30, cache_implementation="static")
64print(tokenizer.decode(out[0], skip_special_tokens=True))[!NOTE]FqnToConfigwith regex-based FQN matching is supported intorchao >= 0.17. Older versions will silently leave the MoE expert weights in BF16.
1pip install --extra-index-url https://download.pytorch.org/whl/cpu \
2 --extra-index-url https://wheels.vllm.ai/cpu/ \
3 torch==2.11.0+cpu \
4 vllm==0.22.0 \
5 torchao==0.17.0 \
6 "lm-eval[vllm]==0.4.12" \
7 huggingface_hubconda install -c conda-forge gperftools=2.17.2 llvm-openmp=18.1.8 --no-deps -y1# TorchInductor + zentorch
2export TORCHINDUCTOR_FREEZING=1
3export TORCHINDUCTOR_AUTOGRAD_CACHE=0
4export VLLM_USE_AOT_COMPILE=0
5export ZENDNNL_MATMUL_ALGO=1
6export ZENTORCH_FUSED_MOE=1 # required for gpt-oss-20b (MoE)
7
8# Required CPU runtime libraries
9export LD_PRELOAD="<path to lib>/libtcmalloc_minimal.so.4:<path to lib>/libiomp5.so${LD_PRELOAD:+:$LD_PRELOAD}"find / -name 'libtcmalloc_minimal.so.4' and find / -name 'libiomp5.so', then substitute the resulting directory for <path to lib>.| Benchmark | BF16 Baseline | DA8W8 (this model) | Dynamic Quant Difference (baseline: BF16) |
|---|---|---|---|
| GSM8K (5-shot, exact-match flexible) | - | 88.17 | - |
1lm_eval \
2 --model vllm \
3 --model_args pretrained=amd/gpt-oss-20b-da8w8-torchao-v0.17.0,tokenizer=unsloth/gpt-oss-20b-BF16,dtype=bfloat16 \
4 --tasks gsm8k \
5 --batch_size auto \
6 --trust_remote_code \
7 --num_fewshot 5 \
8 --log_samples \
9 --gen_kwargs "max_gen_toks=2048" \
10 --apply_chat_template \
11 --output_path .[num_experts, in, out]) parameters; per-tensor scales were observed to be too coarse across experts.