Add files using upload-large-folder tool
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- .cache/torch/comm_lib_trace_rank_0 +0 -0
- .cache/torch/comm_lib_trace_rank_1 +0 -0
- .conda/aau_token +1 -0
- .conda/aau_token_host +1 -0
- LSAQ_CoreCode/lsaq_quant.py +170 -0
- LSAQ_CoreCode/main.ipynb +321 -0
- README.md +1 -0
- __pycache__/zscore.cpython-310.pyc +0 -0
- __pycache__/zscore.cpython-311.pyc +0 -0
- baselines/Llama-2-7b-hf_alpha_idx_10.json +34 -0
- baselines/Llama-2-7b-hf_alpha_idx_5.json +34 -0
- baselines/Llama-2-7b-hf_kurtosis_idx_10.json +34 -0
- baselines/Llama-2-7b-hf_kurtosis_idx_5.json +34 -0
- baselines/Llama-2-7b-hf_z_idx_10.json +34 -0
- baselines/Llama-2-7b-hf_z_idx_5.json +34 -0
- eval.sh +59 -0
- eval_coherence.sh +29 -0
- eval_fg.sh +89 -0
- eval_hd.sh +28 -0
- eval_layer_llama.sh +39 -0
- eval_layer_qwen.sh +39 -0
- eval_zd.sh +29 -0
- inference.py +19 -0
- layerwise-awq.py +322 -0
- llm-awq/README.md +292 -0
- llm-awq/awq/__pycache__/entry.cpython-311.pyc +0 -0
- llm-awq/awq/entry.py +357 -0
- llm-awq/awq/kernels/csrc/attention/README.md +8 -0
- llm-awq/awq/kernels/csrc/attention/cuda_bf16_fallbacks.cuh +257 -0
- llm-awq/awq/kernels/csrc/attention/cuda_bf16_wrapper.h +23 -0
- llm-awq/awq/kernels/csrc/attention/decoder_masked_multihead_attention.cu +154 -0
- llm-awq/awq/kernels/csrc/attention/decoder_masked_multihead_attention_utils.h +1795 -0
- llm-awq/awq/kernels/csrc/attention/ft_attention.cpp +185 -0
- llm-awq/awq/kernels/csrc/attention/ft_attention.h +16 -0
- llm-awq/awq/kernels/csrc/layernorm/layernorm.cu +131 -0
- llm-awq/awq/kernels/csrc/position_embedding/pos_encoding.h +9 -0
- llm-awq/awq/kernels/csrc/pybind.cpp +38 -0
- llm-awq/awq/kernels/csrc/quantization/gemv_cuda.cu +247 -0
- llm-awq/awq/kernels/setup.py +51 -0
- llm-awq/tinychat/models/falcon.py +304 -0
- llm-awq/tinychat/models/internvl3.py +383 -0
- llm-awq/tinychat/models/nvila/builder.py +291 -0
- llm-awq/tinychat/models/nvila/llava_arch.py +909 -0
- llm-awq/tinychat/models/qwen2.py +511 -0
- llm-awq/tinychat/models/vila_llama.py +109 -0
- llm-awq/tinychat/modules/fused_attn.py +634 -0
- llm-awq/tinychat/modules/fused_internencoder.py +237 -0
- llm-awq/tinychat/modules/fused_norm.py +46 -0
- llm-awq/tinychat/modules/fused_siglipdecoder.py +282 -0
- llm-awq/tinychat/modules/fused_vision_attn.py +272 -0
.cache/torch/comm_lib_trace_rank_0
ADDED
|
Binary file (118 Bytes). View file
|
|
|
.cache/torch/comm_lib_trace_rank_1
ADDED
|
Binary file (118 Bytes). View file
|
|
|
.conda/aau_token
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
YN_RyWTyaweE0R_BuNYxb-
|
.conda/aau_token_host
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
zHxE_XAQ
|
LSAQ_CoreCode/lsaq_quant.py
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import torch
|
| 3 |
+
import torch.nn as nn
|
| 4 |
+
import numpy as np
|
| 5 |
+
from transformers import AutoTokenizer, AutoModelForCausalLM
|
| 6 |
+
import tqdm
|
| 7 |
+
import json
|
| 8 |
+
import math
|
| 9 |
+
import torch.nn.functional as F
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
from datasets import load_dataset
|
| 13 |
+
|
| 14 |
+
@torch.no_grad()
|
| 15 |
+
def quantize_weight_per_channel_absmax(w, n_bits=8):
|
| 16 |
+
# w: (out_features, in_features)
|
| 17 |
+
scales = w.abs().max(dim=-1, keepdim=True)[0]
|
| 18 |
+
q_max = 2 ** (n_bits - 1) - 1
|
| 19 |
+
scales.clamp_(min=1e-5).div_(q_max)
|
| 20 |
+
w.div_(scales).round_().mul_(scales)
|
| 21 |
+
return w
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
@torch.no_grad()
|
| 25 |
+
def quantize_weight_per_tensor_absmax(w, n_bits=8):
|
| 26 |
+
# w: (out_features, in_features)
|
| 27 |
+
scales = w.abs().max()
|
| 28 |
+
q_max = 2 ** (n_bits - 1) - 1
|
| 29 |
+
scales.clamp_(min=1e-5).div_(q_max)
|
| 30 |
+
w.div_(scales).round_().mul_(scales)
|
| 31 |
+
return w
|
| 32 |
+
|
| 33 |
+
class W8A16Linear(nn.Module):
|
| 34 |
+
def __init__(
|
| 35 |
+
self,
|
| 36 |
+
# bit_width,
|
| 37 |
+
in_features,
|
| 38 |
+
out_features,
|
| 39 |
+
bias=True,
|
| 40 |
+
quantize_output=False,
|
| 41 |
+
):
|
| 42 |
+
super().__init__()
|
| 43 |
+
# self.bit_width = bit_width
|
| 44 |
+
self.in_features = in_features
|
| 45 |
+
self.out_features = out_features
|
| 46 |
+
|
| 47 |
+
self.register_buffer(
|
| 48 |
+
"weight",
|
| 49 |
+
torch.randn(
|
| 50 |
+
self.out_features,
|
| 51 |
+
self.in_features,
|
| 52 |
+
dtype=torch.float16,
|
| 53 |
+
requires_grad=False,
|
| 54 |
+
),
|
| 55 |
+
)
|
| 56 |
+
if bias:
|
| 57 |
+
self.register_buffer(
|
| 58 |
+
"bias",
|
| 59 |
+
torch.zeros(
|
| 60 |
+
(1, self.out_features), dtype=torch.float16, requires_grad=False
|
| 61 |
+
),
|
| 62 |
+
)
|
| 63 |
+
else:
|
| 64 |
+
self.register_buffer("bias", None)
|
| 65 |
+
|
| 66 |
+
def to(self, *args, **kwargs):
|
| 67 |
+
super(W8A16Linear, self).to(*args, **kwargs)
|
| 68 |
+
self.weight = self.weight.to(*args, **kwargs)
|
| 69 |
+
if self.bias is not None:
|
| 70 |
+
self.bias = self.bias.to(*args, **kwargs)
|
| 71 |
+
return self
|
| 72 |
+
|
| 73 |
+
@torch.no_grad()
|
| 74 |
+
def forward(self, x):
|
| 75 |
+
y = torch.functional.F.linear(x, self.weight, self.bias)
|
| 76 |
+
return y
|
| 77 |
+
|
| 78 |
+
@staticmethod
|
| 79 |
+
def from_float(
|
| 80 |
+
bit, module, weight_quant="per_channel", quantize_output=False
|
| 81 |
+
):
|
| 82 |
+
assert isinstance(module, torch.nn.Linear)
|
| 83 |
+
new_module = W8A16Linear(
|
| 84 |
+
# bit,
|
| 85 |
+
module.in_features,
|
| 86 |
+
module.out_features,
|
| 87 |
+
module.bias is not None,
|
| 88 |
+
quantize_output=quantize_output,
|
| 89 |
+
)
|
| 90 |
+
if weight_quant == "per_channel":
|
| 91 |
+
new_module.weight = quantize_weight_per_channel_absmax(module.weight, bit)
|
| 92 |
+
elif weight_quant == "per_tensor":
|
| 93 |
+
new_module.weight = quantize_weight_per_tensor_absmax(module.weight, bit)
|
| 94 |
+
else:
|
| 95 |
+
raise ValueError(f"Invalid weight_quant: {weight_quant}")
|
| 96 |
+
new_module.weight_quant_name = weight_quant
|
| 97 |
+
if module.bias is not None:
|
| 98 |
+
new_module.bias = module.bias
|
| 99 |
+
return new_module
|
| 100 |
+
|
| 101 |
+
def __repr__(self):
|
| 102 |
+
return f"W8A16Linear({self.in_features}, {self.out_features}, bias={self.bias is not None}, weight_quant={self.weight_quant_name})"
|
| 103 |
+
|
| 104 |
+
def quantize_llama_like(
|
| 105 |
+
model, mlp_quant, self_attn_quant, low_bit, weight_quant="per_channel", quantize_bmm_input=False
|
| 106 |
+
):
|
| 107 |
+
from transformers.models.llama.modeling_llama import (
|
| 108 |
+
LlamaAttention,
|
| 109 |
+
LlamaMLP,
|
| 110 |
+
)
|
| 111 |
+
|
| 112 |
+
for name, m in model.model.named_modules():
|
| 113 |
+
if isinstance(m, LlamaMLP):
|
| 114 |
+
if low_bit == 0:
|
| 115 |
+
continue
|
| 116 |
+
else:
|
| 117 |
+
if name in mlp_quant:
|
| 118 |
+
bit = low_bit
|
| 119 |
+
print(f'{name} {bit} bit quant ')
|
| 120 |
+
else:
|
| 121 |
+
if low_bit == 4:
|
| 122 |
+
bit = 8
|
| 123 |
+
print(f'{name} {bit} bit quant ')
|
| 124 |
+
elif low_bit == 8:
|
| 125 |
+
continue
|
| 126 |
+
|
| 127 |
+
m.gate_proj = W8A16Linear.from_float(
|
| 128 |
+
bit, m.gate_proj, weight_quant=weight_quant
|
| 129 |
+
)
|
| 130 |
+
m.up_proj = W8A16Linear.from_float(
|
| 131 |
+
bit, m.up_proj, weight_quant=weight_quant
|
| 132 |
+
)
|
| 133 |
+
m.down_proj = W8A16Linear.from_float(
|
| 134 |
+
bit, m.down_proj, weight_quant=weight_quant
|
| 135 |
+
)
|
| 136 |
+
elif isinstance(m, LlamaAttention):
|
| 137 |
+
if low_bit == 0:
|
| 138 |
+
continue
|
| 139 |
+
else:
|
| 140 |
+
if name in self_attn_quant:
|
| 141 |
+
bit = low_bit
|
| 142 |
+
else:
|
| 143 |
+
if low_bit == 4:
|
| 144 |
+
bit = 8
|
| 145 |
+
elif low_bit == 8:
|
| 146 |
+
continue
|
| 147 |
+
|
| 148 |
+
m.q_proj = W8A16Linear.from_float(
|
| 149 |
+
bit,
|
| 150 |
+
m.q_proj,
|
| 151 |
+
weight_quant=weight_quant,
|
| 152 |
+
quantize_output=quantize_bmm_input,
|
| 153 |
+
)
|
| 154 |
+
m.k_proj = W8A16Linear.from_float(
|
| 155 |
+
bit,
|
| 156 |
+
m.k_proj,
|
| 157 |
+
weight_quant=weight_quant,
|
| 158 |
+
quantize_output=quantize_bmm_input,
|
| 159 |
+
)
|
| 160 |
+
m.v_proj = W8A16Linear.from_float(
|
| 161 |
+
bit,
|
| 162 |
+
m.v_proj,
|
| 163 |
+
weight_quant=weight_quant,
|
| 164 |
+
quantize_output=quantize_bmm_input,
|
| 165 |
+
)
|
| 166 |
+
m.o_proj = W8A16Linear.from_float(
|
| 167 |
+
bit, m.o_proj, weight_quant=weight_quant
|
| 168 |
+
)
|
| 169 |
+
|
| 170 |
+
return model
|
LSAQ_CoreCode/main.ipynb
ADDED
|
@@ -0,0 +1,321 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"cells": [
|
| 3 |
+
{
|
| 4 |
+
"cell_type": "code",
|
| 5 |
+
"execution_count": null,
|
| 6 |
+
"metadata": {},
|
| 7 |
+
"outputs": [],
|
| 8 |
+
"source": [
|
| 9 |
+
"import os\n",
|
| 10 |
+
"import torch\n",
|
| 11 |
+
"import torch.nn as nn\n",
|
| 12 |
+
"import GPUtil\n",
|
| 13 |
+
"from transformers import AutoTokenizer, AutoModelForCausalLM\n",
|
| 14 |
+
"import tqdm\n",
|
| 15 |
+
"from functools import partial"
|
| 16 |
+
]
|
| 17 |
+
},
|
| 18 |
+
{
|
| 19 |
+
"cell_type": "markdown",
|
| 20 |
+
"metadata": {},
|
| 21 |
+
"source": [
|
| 22 |
+
"## Resource Detection"
|
| 23 |
+
]
|
| 24 |
+
},
|
| 25 |
+
{
|
| 26 |
+
"cell_type": "code",
|
| 27 |
+
"execution_count": null,
|
| 28 |
+
"metadata": {},
|
| 29 |
+
"outputs": [],
|
| 30 |
+
"source": [
|
| 31 |
+
"gpus = GPUtil.getGPUs()\n",
|
| 32 |
+
"free_memory = []\n",
|
| 33 |
+
"\n",
|
| 34 |
+
"for gpu in gpus:\n",
|
| 35 |
+
" free_memory.append(gpu.memoryFree)\n",
|
| 36 |
+
"\n",
|
| 37 |
+
"memory_sort = sorted(range(len(free_memory)), key=lambda i: free_memory[i])\n",
|
| 38 |
+
"\n",
|
| 39 |
+
"gpu_id = memory_sort[-1]\n",
|
| 40 |
+
"gpu_memory = free_memory[memory_sort[-1]]\n",
|
| 41 |
+
"\n",
|
| 42 |
+
"print(f'gpu_id:{gpu_id}; gpu_memory:{gpu_memory}')\n",
|
| 43 |
+
"\n",
|
| 44 |
+
"os.environ[\"CUDA_DEVICE_ORDER\"] = \"PCI_BUS_ID\"\n",
|
| 45 |
+
"os.environ[\"CUDA_VISIBLE_DEVICES\"] = str(gpu_id)"
|
| 46 |
+
]
|
| 47 |
+
},
|
| 48 |
+
{
|
| 49 |
+
"cell_type": "markdown",
|
| 50 |
+
"metadata": {},
|
| 51 |
+
"source": [
|
| 52 |
+
"## Model Selection"
|
| 53 |
+
]
|
| 54 |
+
},
|
| 55 |
+
{
|
| 56 |
+
"cell_type": "code",
|
| 57 |
+
"execution_count": null,
|
| 58 |
+
"metadata": {},
|
| 59 |
+
"outputs": [],
|
| 60 |
+
"source": [
|
| 61 |
+
"model_name = \"/data/LLMs/Llama-2-7b-hf\"\n",
|
| 62 |
+
"\n",
|
| 63 |
+
"tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)\n",
|
| 64 |
+
"model = AutoModelForCausalLM.from_pretrained(model_name, trust_remote_code=True, torch_dtype=torch.float16, device_map=\"auto\")"
|
| 65 |
+
]
|
| 66 |
+
},
|
| 67 |
+
{
|
| 68 |
+
"cell_type": "markdown",
|
| 69 |
+
"metadata": {},
|
| 70 |
+
"source": [
|
| 71 |
+
"## Layer Importance Detection"
|
| 72 |
+
]
|
| 73 |
+
},
|
| 74 |
+
{
|
| 75 |
+
"cell_type": "code",
|
| 76 |
+
"execution_count": null,
|
| 77 |
+
"metadata": {},
|
| 78 |
+
"outputs": [],
|
| 79 |
+
"source": [
|
| 80 |
+
"def encode(tok, text, padding=True, truncation=True, max_length=None):\n",
|
| 81 |
+
" # 将文本转换为输入 IDs\n",
|
| 82 |
+
" input_ids = [tok.bos_id] + tok.encode(text)\n",
|
| 83 |
+
"\n",
|
| 84 |
+
" # 生成注意力掩码\n",
|
| 85 |
+
" attention_mask = [1] * len(input_ids)\n",
|
| 86 |
+
"\n",
|
| 87 |
+
" # 如果进行了填充,则调整注意力掩码\n",
|
| 88 |
+
" if padding:\n",
|
| 89 |
+
" padding_length = max_length - len(input_ids)\n",
|
| 90 |
+
" attention_mask = [0] * padding_length + attention_mask\n",
|
| 91 |
+
" input_ids = [tok.eos_id] * padding_length + input_ids\n",
|
| 92 |
+
"\n",
|
| 93 |
+
" encoded_input = {\n",
|
| 94 |
+
" 'input_ids': input_ids,\n",
|
| 95 |
+
" 'attention_mask': attention_mask\n",
|
| 96 |
+
" }\n",
|
| 97 |
+
" return encoded_input\n",
|
| 98 |
+
"\n",
|
| 99 |
+
"def batch_encode_plus(tok, texts, max_length=None, return_tensors=None):\n",
|
| 100 |
+
" encoded_inputs = []\n",
|
| 101 |
+
"\n",
|
| 102 |
+
" # 循环处理每个文本\n",
|
| 103 |
+
" if max_length is None:\n",
|
| 104 |
+
" max_length = -1\n",
|
| 105 |
+
" for text in texts:\n",
|
| 106 |
+
" # if isinstance(text, list):\n",
|
| 107 |
+
" # text = text[0]\n",
|
| 108 |
+
" # print(text)\n",
|
| 109 |
+
" len_ = len([tok.bos_id] + tok.encode(text))\n",
|
| 110 |
+
" if len_ > max_length:\n",
|
| 111 |
+
" max_length = len_\n",
|
| 112 |
+
" for text in texts:\n",
|
| 113 |
+
" # if isinstance(text, list):\n",
|
| 114 |
+
" # text = text[0]\n",
|
| 115 |
+
" encoded_input = encode(tok, text, max_length = max_length)\n",
|
| 116 |
+
" encoded_inputs.append(encoded_input)\n",
|
| 117 |
+
"\n",
|
| 118 |
+
" # 合并结果\n",
|
| 119 |
+
" batch_encoded = {\n",
|
| 120 |
+
" 'input_ids': [encoded_input['input_ids'] for encoded_input in encoded_inputs],\n",
|
| 121 |
+
" 'attention_mask': [encoded_input['attention_mask'] for encoded_input in encoded_inputs]\n",
|
| 122 |
+
" }\n",
|
| 123 |
+
"\n",
|
| 124 |
+
" batch_encoded = {key: torch.tensor(val) for key, val in batch_encoded.items()}\n",
|
| 125 |
+
"\n",
|
| 126 |
+
" return batch_encoded"
|
| 127 |
+
]
|
| 128 |
+
},
|
| 129 |
+
{
|
| 130 |
+
"cell_type": "code",
|
| 131 |
+
"execution_count": null,
|
| 132 |
+
"metadata": {},
|
| 133 |
+
"outputs": [],
|
| 134 |
+
"source": [
|
| 135 |
+
"tokenizer.bos_token = tokenizer.eos_token\n",
|
| 136 |
+
"tokenizer.bos_id = tokenizer.bos_token_id\n",
|
| 137 |
+
"tokenizer.eos_id = tokenizer.eos_token_id\n",
|
| 138 |
+
"importances = [0 for i in range(len(model.model.layers))] # layer-wise importance scores"
|
| 139 |
+
]
|
| 140 |
+
},
|
| 141 |
+
{
|
| 142 |
+
"cell_type": "code",
|
| 143 |
+
"execution_count": null,
|
| 144 |
+
"metadata": {},
|
| 145 |
+
"outputs": [],
|
| 146 |
+
"source": [
|
| 147 |
+
"from datasets import load_dataset\n",
|
| 148 |
+
"\n",
|
| 149 |
+
"dataset = load_dataset(\"wikitext\", \"wikitext-2-raw-v1\", split=\"test\")"
|
| 150 |
+
]
|
| 151 |
+
},
|
| 152 |
+
{
|
| 153 |
+
"cell_type": "code",
|
| 154 |
+
"execution_count": null,
|
| 155 |
+
"metadata": {},
|
| 156 |
+
"outputs": [],
|
| 157 |
+
"source": [
|
| 158 |
+
"MAX_SEQ_LEN = 1024\n",
|
| 159 |
+
"batch_size = 1\n",
|
| 160 |
+
"dataset_size = 200"
|
| 161 |
+
]
|
| 162 |
+
},
|
| 163 |
+
{
|
| 164 |
+
"cell_type": "code",
|
| 165 |
+
"execution_count": null,
|
| 166 |
+
"metadata": {},
|
| 167 |
+
"outputs": [],
|
| 168 |
+
"source": [
|
| 169 |
+
"def jaccard_set(list1, list2):\n",
|
| 170 |
+
" \"\"\"Define Jaccard Similarity function for two sets\"\"\"\n",
|
| 171 |
+
" intersection = len(list(set(list1).intersection(list2)))\n",
|
| 172 |
+
" union = (len(list1) + len(list2)) - intersection\n",
|
| 173 |
+
" return float(intersection) / union"
|
| 174 |
+
]
|
| 175 |
+
},
|
| 176 |
+
{
|
| 177 |
+
"cell_type": "code",
|
| 178 |
+
"execution_count": null,
|
| 179 |
+
"metadata": {},
|
| 180 |
+
"outputs": [],
|
| 181 |
+
"source": [
|
| 182 |
+
"import numpy as np\n",
|
| 183 |
+
"\n",
|
| 184 |
+
"k = 20\n",
|
| 185 |
+
"\n",
|
| 186 |
+
"for i in tqdm.tqdm(range(0, dataset_size, batch_size), total = dataset_size / batch_size):\n",
|
| 187 |
+
" \n",
|
| 188 |
+
" prompts = dataset['text'][i:i + batch_size]\n",
|
| 189 |
+
" max_seq_len = MAX_SEQ_LEN\n",
|
| 190 |
+
" stride = 256\n",
|
| 191 |
+
" max_gen_len = 0\n",
|
| 192 |
+
"\n",
|
| 193 |
+
"\n",
|
| 194 |
+
" prompt_tokens = batch_encode_plus(\n",
|
| 195 |
+
" tokenizer,\n",
|
| 196 |
+
" prompts,\n",
|
| 197 |
+
" return_tensors='pt'\n",
|
| 198 |
+
" )\n",
|
| 199 |
+
" input_ids = prompt_tokens['input_ids']\n",
|
| 200 |
+
" attn_mask = prompt_tokens['attention_mask']\n",
|
| 201 |
+
" max_prompt_len = max(len(t) for t in input_ids)\n",
|
| 202 |
+
" all_jac_sim = [0 for i in range(len(model.model.layers))] \n",
|
| 203 |
+
" E = model.get_input_embeddings().weight.detach()\n",
|
| 204 |
+
" \n",
|
| 205 |
+
" # authors use a sliding window of size 1024 with a shift of 256\n",
|
| 206 |
+
" for start in range(0, max_prompt_len, stride):\n",
|
| 207 |
+
" seq_ids = (attn_mask.sum(dim=-1) > start).nonzero().squeeze()\n",
|
| 208 |
+
" seq_ids = seq_ids.unsqueeze(0) if seq_ids.dim() == 0 else seq_ids # ensure 2d\n",
|
| 209 |
+
" inputs = input_ids[seq_ids, start:start+max_seq_len]\n",
|
| 210 |
+
" attn = attn_mask[seq_ids, start:start+max_seq_len]\n",
|
| 211 |
+
"\n",
|
| 212 |
+
" if max_gen_len == 0:\n",
|
| 213 |
+
" outputs = model(\n",
|
| 214 |
+
" input_ids=inputs.to(\"cuda\"),\n",
|
| 215 |
+
" attention_mask=attn.to(\"cuda\"),\n",
|
| 216 |
+
" output_hidden_states=True,\n",
|
| 217 |
+
" )\n",
|
| 218 |
+
" else:\n",
|
| 219 |
+
" outputs = model.generate(\n",
|
| 220 |
+
" input_ids=inputs.to(\"cuda\"),\n",
|
| 221 |
+
" attention_mask=attn.to(\"cuda\"),\n",
|
| 222 |
+
" max_new_tokens=max_gen_len, \n",
|
| 223 |
+
" output_hidden_states=True,\n",
|
| 224 |
+
" return_dict_in_generate=True,\n",
|
| 225 |
+
" )\n",
|
| 226 |
+
"\n",
|
| 227 |
+
" hiddens = outputs.hidden_states\n",
|
| 228 |
+
"\n",
|
| 229 |
+
" for i in range(len(hiddens) - 1):\n",
|
| 230 |
+
" in_hidden = hiddens[i][:,-1,:]\n",
|
| 231 |
+
" out_hidden = hiddens[i+1][:,-1,:]\n",
|
| 232 |
+
"\n",
|
| 233 |
+
" in_projs = in_hidden @ E.T\n",
|
| 234 |
+
" out_projs = out_hidden @ E.T\n",
|
| 235 |
+
"\n",
|
| 236 |
+
" in_projs = in_projs.detach().cpu().numpy()\n",
|
| 237 |
+
" ot_projs = out_projs.detach().cpu().numpy()\n",
|
| 238 |
+
"\n",
|
| 239 |
+
" in_ind = np.argsort(-in_projs)\n",
|
| 240 |
+
" ot_ind = np.argsort(-ot_projs)\n",
|
| 241 |
+
"\n",
|
| 242 |
+
" in_topks = [tokenizer.decode(i) for i in in_ind[0][:k]]\n",
|
| 243 |
+
" ot_topks = [tokenizer.decode(i) for i in ot_ind[0][:k]]\n",
|
| 244 |
+
"\n",
|
| 245 |
+
" all_jac_sim[i] += jaccard_set(in_topks, ot_topks)\n",
|
| 246 |
+
"\n",
|
| 247 |
+
" \n",
|
| 248 |
+
" importances = [x + y for x, y in zip(importances, all_jac_sim)]\n"
|
| 249 |
+
]
|
| 250 |
+
},
|
| 251 |
+
{
|
| 252 |
+
"cell_type": "code",
|
| 253 |
+
"execution_count": null,
|
| 254 |
+
"metadata": {},
|
| 255 |
+
"outputs": [],
|
| 256 |
+
"source": [
|
| 257 |
+
"import math\n",
|
| 258 |
+
"def normalize(lst, range_min=0, range_max=1):\n",
|
| 259 |
+
" min_val = min(lst)\n",
|
| 260 |
+
" max_val = max(lst)\n",
|
| 261 |
+
" normalized = [(range_max - range_min) * (x - min_val) / (max_val - min_val) + range_min for x in lst]\n",
|
| 262 |
+
" return normalized\n",
|
| 263 |
+
"\n",
|
| 264 |
+
"filtered_values = [0 if math.isinf(value) else value for value in importances] \n",
|
| 265 |
+
"normalized_lst = normalize(filtered_values)\n",
|
| 266 |
+
"\n",
|
| 267 |
+
"sorted_indices = sorted(range(len(normalized_lst)), key=lambda i: normalized_lst[i])\n",
|
| 268 |
+
"reversed_list = list(reversed(sorted_indices))"
|
| 269 |
+
]
|
| 270 |
+
},
|
| 271 |
+
{
|
| 272 |
+
"cell_type": "markdown",
|
| 273 |
+
"metadata": {},
|
| 274 |
+
"source": [
|
| 275 |
+
"## Quantize"
|
| 276 |
+
]
|
| 277 |
+
},
|
| 278 |
+
{
|
| 279 |
+
"cell_type": "code",
|
| 280 |
+
"execution_count": null,
|
| 281 |
+
"metadata": {},
|
| 282 |
+
"outputs": [],
|
| 283 |
+
"source": [
|
| 284 |
+
"from lsaq_quant import quantize_llama_like\n",
|
| 285 |
+
"\n",
|
| 286 |
+
"num_of_layer2quant = 8\n",
|
| 287 |
+
"bit = 8\n",
|
| 288 |
+
"\n",
|
| 289 |
+
"layer_to_quant = reversed_list[0:num_of_layer2quant]\n",
|
| 290 |
+
"\n",
|
| 291 |
+
"mlp_quant = [f'layers.{item}.mlp' for item in layer_to_quant]\n",
|
| 292 |
+
"self_attn_quant = [f'layers.{item}.self_attn' for item in layer_to_quant]\n",
|
| 293 |
+
"\n",
|
| 294 |
+
"print(f'quanting ... ')\n",
|
| 295 |
+
"model_lsaq = quantize_llama_like(model, mlp_quant, self_attn_quant, bit)\n",
|
| 296 |
+
"print(f'quanted')"
|
| 297 |
+
]
|
| 298 |
+
}
|
| 299 |
+
],
|
| 300 |
+
"metadata": {
|
| 301 |
+
"kernelspec": {
|
| 302 |
+
"display_name": "smoothquant",
|
| 303 |
+
"language": "python",
|
| 304 |
+
"name": "python3"
|
| 305 |
+
},
|
| 306 |
+
"language_info": {
|
| 307 |
+
"codemirror_mode": {
|
| 308 |
+
"name": "ipython",
|
| 309 |
+
"version": 3
|
| 310 |
+
},
|
| 311 |
+
"file_extension": ".py",
|
| 312 |
+
"mimetype": "text/x-python",
|
| 313 |
+
"name": "python",
|
| 314 |
+
"nbconvert_exporter": "python",
|
| 315 |
+
"pygments_lexer": "ipython3",
|
| 316 |
+
"version": "3.8.19"
|
| 317 |
+
}
|
| 318 |
+
},
|
| 319 |
+
"nbformat": 4,
|
| 320 |
+
"nbformat_minor": 2
|
| 321 |
+
}
|
README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
# quantization
|
__pycache__/zscore.cpython-310.pyc
ADDED
|
Binary file (1.93 kB). View file
|
|
|
__pycache__/zscore.cpython-311.pyc
ADDED
|
Binary file (2.85 kB). View file
|
|
|
baselines/Llama-2-7b-hf_alpha_idx_10.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
4,
|
| 3 |
+
4,
|
| 4 |
+
4,
|
| 5 |
+
4,
|
| 6 |
+
4,
|
| 7 |
+
4,
|
| 8 |
+
4,
|
| 9 |
+
4,
|
| 10 |
+
4,
|
| 11 |
+
4,
|
| 12 |
+
4,
|
| 13 |
+
4,
|
| 14 |
+
4,
|
| 15 |
+
4,
|
| 16 |
+
4,
|
| 17 |
+
4,
|
| 18 |
+
4,
|
| 19 |
+
4,
|
| 20 |
+
4,
|
| 21 |
+
4,
|
| 22 |
+
2,
|
| 23 |
+
2,
|
| 24 |
+
2,
|
| 25 |
+
2,
|
| 26 |
+
2,
|
| 27 |
+
2,
|
| 28 |
+
4,
|
| 29 |
+
2,
|
| 30 |
+
2,
|
| 31 |
+
2,
|
| 32 |
+
2,
|
| 33 |
+
4
|
| 34 |
+
]
|
baselines/Llama-2-7b-hf_alpha_idx_5.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
4,
|
| 3 |
+
4,
|
| 4 |
+
4,
|
| 5 |
+
4,
|
| 6 |
+
4,
|
| 7 |
+
4,
|
| 8 |
+
4,
|
| 9 |
+
4,
|
| 10 |
+
4,
|
| 11 |
+
4,
|
| 12 |
+
4,
|
| 13 |
+
4,
|
| 14 |
+
4,
|
| 15 |
+
4,
|
| 16 |
+
4,
|
| 17 |
+
4,
|
| 18 |
+
4,
|
| 19 |
+
4,
|
| 20 |
+
4,
|
| 21 |
+
4,
|
| 22 |
+
2,
|
| 23 |
+
2,
|
| 24 |
+
2,
|
| 25 |
+
4,
|
| 26 |
+
2,
|
| 27 |
+
4,
|
| 28 |
+
4,
|
| 29 |
+
4,
|
| 30 |
+
4,
|
| 31 |
+
4,
|
| 32 |
+
2,
|
| 33 |
+
4
|
| 34 |
+
]
|
baselines/Llama-2-7b-hf_kurtosis_idx_10.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
4,
|
| 3 |
+
4,
|
| 4 |
+
4,
|
| 5 |
+
4,
|
| 6 |
+
4,
|
| 7 |
+
4,
|
| 8 |
+
4,
|
| 9 |
+
4,
|
| 10 |
+
4,
|
| 11 |
+
4,
|
| 12 |
+
4,
|
| 13 |
+
4,
|
| 14 |
+
4,
|
| 15 |
+
4,
|
| 16 |
+
2,
|
| 17 |
+
2,
|
| 18 |
+
4,
|
| 19 |
+
2,
|
| 20 |
+
2,
|
| 21 |
+
2,
|
| 22 |
+
4,
|
| 23 |
+
2,
|
| 24 |
+
4,
|
| 25 |
+
2,
|
| 26 |
+
4,
|
| 27 |
+
2,
|
| 28 |
+
4,
|
| 29 |
+
2,
|
| 30 |
+
2,
|
| 31 |
+
4,
|
| 32 |
+
4,
|
| 33 |
+
4
|
| 34 |
+
]
|
baselines/Llama-2-7b-hf_kurtosis_idx_5.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
4,
|
| 3 |
+
4,
|
| 4 |
+
4,
|
| 5 |
+
4,
|
| 6 |
+
4,
|
| 7 |
+
4,
|
| 8 |
+
4,
|
| 9 |
+
4,
|
| 10 |
+
4,
|
| 11 |
+
4,
|
| 12 |
+
4,
|
| 13 |
+
4,
|
| 14 |
+
4,
|
| 15 |
+
4,
|
| 16 |
+
4,
|
| 17 |
+
4,
|
| 18 |
+
4,
|
| 19 |
+
4,
|
| 20 |
+
2,
|
| 21 |
+
4,
|
| 22 |
+
4,
|
| 23 |
+
4,
|
| 24 |
+
4,
|
| 25 |
+
2,
|
| 26 |
+
4,
|
| 27 |
+
2,
|
| 28 |
+
4,
|
| 29 |
+
2,
|
| 30 |
+
2,
|
| 31 |
+
4,
|
| 32 |
+
4,
|
| 33 |
+
4
|
| 34 |
+
]
|
baselines/Llama-2-7b-hf_z_idx_10.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
4,
|
| 3 |
+
4,
|
| 4 |
+
4,
|
| 5 |
+
2,
|
| 6 |
+
2,
|
| 7 |
+
2,
|
| 8 |
+
4,
|
| 9 |
+
2,
|
| 10 |
+
4,
|
| 11 |
+
2,
|
| 12 |
+
2,
|
| 13 |
+
4,
|
| 14 |
+
2,
|
| 15 |
+
4,
|
| 16 |
+
4,
|
| 17 |
+
4,
|
| 18 |
+
4,
|
| 19 |
+
4,
|
| 20 |
+
4,
|
| 21 |
+
4,
|
| 22 |
+
4,
|
| 23 |
+
2,
|
| 24 |
+
4,
|
| 25 |
+
4,
|
| 26 |
+
4,
|
| 27 |
+
2,
|
| 28 |
+
4,
|
| 29 |
+
2,
|
| 30 |
+
4,
|
| 31 |
+
4,
|
| 32 |
+
4,
|
| 33 |
+
4
|
| 34 |
+
]
|
baselines/Llama-2-7b-hf_z_idx_5.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
[
|
| 2 |
+
4,
|
| 3 |
+
4,
|
| 4 |
+
4,
|
| 5 |
+
4,
|
| 6 |
+
4,
|
| 7 |
+
2,
|
| 8 |
+
4,
|
| 9 |
+
4,
|
| 10 |
+
4,
|
| 11 |
+
4,
|
| 12 |
+
4,
|
| 13 |
+
4,
|
| 14 |
+
2,
|
| 15 |
+
4,
|
| 16 |
+
4,
|
| 17 |
+
4,
|
| 18 |
+
4,
|
| 19 |
+
4,
|
| 20 |
+
4,
|
| 21 |
+
4,
|
| 22 |
+
4,
|
| 23 |
+
2,
|
| 24 |
+
4,
|
| 25 |
+
4,
|
| 26 |
+
4,
|
| 27 |
+
2,
|
| 28 |
+
4,
|
| 29 |
+
2,
|
| 30 |
+
4,
|
| 31 |
+
4,
|
| 32 |
+
4,
|
| 33 |
+
4
|
| 34 |
+
]
|
eval.sh
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export HTTP_PROXY=http://sys-proxy-rd-relay.byted.org:8118
|
| 2 |
+
export http_proxy=http://sys-proxy-rd-relay.byted.org:8118
|
| 3 |
+
export https_proxy=http://sys-proxy-rd-relay.byted.org:8118
|
| 4 |
+
export no_proxy="$no_proxy,.byteintl.net"
|
| 5 |
+
export HF_ENDPOINT=https://hf-mirror.com
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
cd quantization_metric/
|
| 9 |
+
model_id=/mnt/bn/life-mllm/users/cxr/quantization/models/Qwen/Qwen2.5-14B
|
| 10 |
+
model_name=$(basename "$model_id")
|
| 11 |
+
cuda_id=4
|
| 12 |
+
|
| 13 |
+
model=/mnt/bn/life-mllm/users/cxr/quantization/models/${model_name}-quantization-layer-mlp
|
| 14 |
+
# output_dir=Alpha_values_mlp
|
| 15 |
+
# bit_layers_dir=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/bit_layers
|
| 16 |
+
# result_dir=/mnt/bn/life-mllm/users/cxr/quantization/lm-evaluation-harness/results
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
start=$(date +%s.%N)
|
| 21 |
+
# rm -rf $model
|
| 22 |
+
|
| 23 |
+
modes=("mlp")
|
| 24 |
+
for mode in ${modes[@]}; do
|
| 25 |
+
for idx in {32..47}; do
|
| 26 |
+
echo $mode $idx
|
| 27 |
+
cd ../quantization_metric
|
| 28 |
+
python -u main.py --bit_layer_idx $idx --save_dir ${model} --mode $mode --model_id $model_id --cuda_id $cuda_id
|
| 29 |
+
cd ../lm-evaluation-harness
|
| 30 |
+
bash run_scripts/eval_base_qwen2_5_14b.sh ${model} ${mode}_${idx}
|
| 31 |
+
rm -rf ${model}
|
| 32 |
+
end=$(date +%s.%N)
|
| 33 |
+
runtime=$(awk "BEGIN {print $end - $start}")
|
| 34 |
+
echo "Execution time: $runtime seconds"
|
| 35 |
+
|
| 36 |
+
done
|
| 37 |
+
done
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
model=/mnt/bn/life-mllm/users/cxr/quantization/models/${model_name}-quantization-layer
|
| 41 |
+
|
| 42 |
+
start=$(date +%s.%N)
|
| 43 |
+
# rm -rf $model
|
| 44 |
+
|
| 45 |
+
modes=("self_attn")
|
| 46 |
+
for mode in ${modes[@]}; do
|
| 47 |
+
for idx in {32..47}; do
|
| 48 |
+
echo $mode $idx
|
| 49 |
+
cd ../quantization_metric
|
| 50 |
+
python -u main.py --bit_layer_idx $idx --save_dir ${model} --mode $mode --model_id $model_id --cuda_id $cuda_id
|
| 51 |
+
cd ../lm-evaluation-harness
|
| 52 |
+
bash run_scripts/eval_base_qwen2_5_14b.sh ${model} ${mode}_${idx}
|
| 53 |
+
rm -rf ${model}
|
| 54 |
+
end=$(date +%s.%N)
|
| 55 |
+
runtime=$(awk "BEGIN {print $end - $start}")
|
| 56 |
+
echo "Execution time: $runtime seconds"
|
| 57 |
+
|
| 58 |
+
done
|
| 59 |
+
done
|
eval_coherence.sh
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export HTTP_PROXY=http://sys-proxy-rd-relay.byted.org:8118
|
| 2 |
+
export http_proxy=http://sys-proxy-rd-relay.byted.org:8118
|
| 3 |
+
export https_proxy=http://sys-proxy-rd-relay.byted.org:8118
|
| 4 |
+
export no_proxy="$no_proxy,.byteintl.net"
|
| 5 |
+
export HF_ENDPOINT=https://hf-mirror.com
|
| 6 |
+
|
| 7 |
+
cd quantization_metric/
|
| 8 |
+
model=../models/patch/Llama-2-7b-hf-quantization
|
| 9 |
+
# output_dir=Alpha_values_mlp
|
| 10 |
+
tasks=piqa,winogrande,arc_easy,arc_challenge,hellaswag,boolq
|
| 11 |
+
# bit_layers_dir=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/bit_layers
|
| 12 |
+
# result_dir=/mnt/bn/life-mllm/users/cxr/quantization/lm-evaluation-harness/results
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
start=$(date +%s.%N)
|
| 16 |
+
# rm -rf $model
|
| 17 |
+
|
| 18 |
+
file=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/metrics/coherence/coherence_self_attn_Llama-2-7b-hf.json
|
| 19 |
+
echo "$file"
|
| 20 |
+
cd ../quantization_metric
|
| 21 |
+
configure_id=$(basename $file .json)
|
| 22 |
+
python -u main_low.py --bit_layers $file --save_dir ${model} --k 5 --reverse False
|
| 23 |
+
cd ../lm-evaluation-harness
|
| 24 |
+
bash run_scripts/eval.sh ${configure_id} ${model} ${tasks}
|
| 25 |
+
rm -rf ${model}
|
| 26 |
+
end=$(date +%s.%N)
|
| 27 |
+
runtime=$(awk "BEGIN {print $end - $start}")
|
| 28 |
+
echo "Execution time: $runtime seconds"
|
| 29 |
+
|
eval_fg.sh
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export HTTP_PROXY=http://sys-proxy-rd-relay.byted.org:8118
|
| 2 |
+
export http_proxy=http://sys-proxy-rd-relay.byted.org:8118
|
| 3 |
+
export https_proxy=http://sys-proxy-rd-relay.byted.org:8118
|
| 4 |
+
export no_proxy="$no_proxy,.byteintl.net"
|
| 5 |
+
export HF_ENDPOINT=https://hf-mirror.com
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
cd quantization_metric/
|
| 9 |
+
model_id=/mnt/bn/life-mllm/users/cxr/quantization/models/Qwen/Qwen2.5-7B
|
| 10 |
+
model_name=$(basename "$model_id")
|
| 11 |
+
|
| 12 |
+
model=/mnt/bn/life-mllm/users/cxr/quantization/models/${model_name}-quantization-fg
|
| 13 |
+
# output_dir=Alpha_values_mlp
|
| 14 |
+
# bit_layers_dir=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/bit_layers
|
| 15 |
+
# result_dir=/mnt/bn/life-mllm/users/cxr/quantization/lm-evaluation-harness/results
|
| 16 |
+
|
| 17 |
+
start=$(date +%s.%N)
|
| 18 |
+
# rm -rf $model
|
| 19 |
+
cd ../quantization_metric
|
| 20 |
+
# fg1
|
| 21 |
+
# self_attn_layer_to_quant="4 1 2 8 23"
|
| 22 |
+
# mlp_layer_to_quant="27 16 19 17 25"
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
# save_fg=fg2
|
| 26 |
+
# self_attn_layer_to_quant="23 22 25 24 26"
|
| 27 |
+
# mlp_layer_to_quant="27 16 19 17 25"
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
# save_fg=fg3
|
| 31 |
+
# self_attn_layer_to_quant="23 22 25 24 26"
|
| 32 |
+
# mlp_layer_to_quant="27 16 19"
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
# save_fg=fg4
|
| 37 |
+
# self_attn_layer_to_quant="23 22 25 24 26"
|
| 38 |
+
# mlp_layer_to_quant="27"
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
# save_fg=fg5
|
| 42 |
+
# self_attn_layer_to_quant="27 16 19 17 25"
|
| 43 |
+
# mlp_layer_to_quant="27 16 19 17 25"
|
| 44 |
+
|
| 45 |
+
# save_fg=baseline_BI
|
| 46 |
+
# self_attn_layer_to_quant="16 17 15 14 13"
|
| 47 |
+
# mlp_layer_to_quant="16 17 15 14 13"
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
save_fg=f6
|
| 51 |
+
self_attn_layer_to_quant="4 1 2 8 23 22 25 5 24 7 26 6 20 12 19 17 21 11 10 9 18"
|
| 52 |
+
mlp_layer_to_quant="27 16 19"
|
| 53 |
+
|
| 54 |
+
python -u main_fg.py --cuda_id 6 --save_dir ${model} --model_id $model_id --self_attn_layer_to_quant "${self_attn_layer_to_quant}" --mlp_layer_to_quant "${mlp_layer_to_quant}"
|
| 55 |
+
cd ../lm-evaluation-harness
|
| 56 |
+
bash run_scripts/eval_base_fg.sh ${model} ${save_fg}
|
| 57 |
+
rm -rf ${model}
|
| 58 |
+
end=$(date +%s.%N)
|
| 59 |
+
runtime=$(awk "BEGIN {print $end - $start}")
|
| 60 |
+
echo "Execution time: $runtime seconds"
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
model_id=/mnt/bn/life-mllm/users/cxr/quantization/models/meta-llama/Llama-3.1-8B
|
| 65 |
+
model_name=$(basename "$model_id")
|
| 66 |
+
|
| 67 |
+
model=/mnt/bn/life-mllm/users/cxr/quantization/models/${model_name}-quantization-fg
|
| 68 |
+
# output_dir=Alpha_values_mlp
|
| 69 |
+
# bit_layers_dir=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/bit_layers
|
| 70 |
+
# result_dir=/mnt/bn/life-mllm/users/cxr/quantization/lm-evaluation-harness/results
|
| 71 |
+
|
| 72 |
+
start=$(date +%s.%N)
|
| 73 |
+
# rm -rf $model
|
| 74 |
+
cd ../quantization_metric
|
| 75 |
+
# save_fg=baseline_BI
|
| 76 |
+
# self_attn_layer_to_quant="24 25 23 26 27"
|
| 77 |
+
# mlp_layer_to_quant="24 25 23 26 27"
|
| 78 |
+
save_fg=fg6
|
| 79 |
+
self_attn_layer_to_quant="29 23 24 30 18 28 26 20 16 27 25 17 19 21"
|
| 80 |
+
mlp_layer_to_quant="26 20 22"
|
| 81 |
+
|
| 82 |
+
python -u main_fg.py --cuda_id 6 --save_dir ${model} --model_id $model_id --self_attn_layer_to_quant "${self_attn_layer_to_quant}" --mlp_layer_to_quant "${mlp_layer_to_quant}"
|
| 83 |
+
cd ../lm-evaluation-harness
|
| 84 |
+
bash run_scripts/eval_base_fg.sh ${model} ${save_fg}
|
| 85 |
+
rm -rf ${model}
|
| 86 |
+
end=$(date +%s.%N)
|
| 87 |
+
runtime=$(awk "BEGIN {print $end - $start}")
|
| 88 |
+
echo "Execution time: $runtime seconds"
|
| 89 |
+
|
eval_hd.sh
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export HTTP_PROXY=http://sys-proxy-rd-relay.byted.org:8118
|
| 2 |
+
export http_proxy=http://sys-proxy-rd-relay.byted.org:8118
|
| 3 |
+
export https_proxy=http://sys-proxy-rd-relay.byted.org:8118
|
| 4 |
+
export no_proxy="$no_proxy,.byteintl.net"
|
| 5 |
+
export HF_ENDPOINT=https://hf-mirror.com
|
| 6 |
+
|
| 7 |
+
cd quantization_metric/
|
| 8 |
+
model=../models/patch/Llama-2-7b-hf-quantization
|
| 9 |
+
# output_dir=Alpha_values_mlp
|
| 10 |
+
tasks=piqa,winogrande,arc_easy,arc_challenge,hellaswag,boolq
|
| 11 |
+
# bit_layers_dir=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/bit_layers
|
| 12 |
+
# result_dir=/mnt/bn/life-mllm/users/cxr/quantization/lm-evaluation-harness/results
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
start=$(date +%s.%N)
|
| 16 |
+
# rm -rf $model
|
| 17 |
+
|
| 18 |
+
file=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/metrics/head_diversity/head_diversity_self_attn_Llama-2-7b-hf.json
|
| 19 |
+
echo "$file"
|
| 20 |
+
cd ../quantization_metric
|
| 21 |
+
configure_id=$(basename $file .json)
|
| 22 |
+
python -u main_low.py --bit_layers $file --save_dir ${model} --k 5 --reverse False
|
| 23 |
+
cd ../lm-evaluation-harness
|
| 24 |
+
bash run_scripts/eval.sh ${configure_id} ${model} ${tasks}
|
| 25 |
+
rm -rf ${model}
|
| 26 |
+
end=$(date +%s.%N)
|
| 27 |
+
runtime=$(awk "BEGIN {print $end - $start}")
|
| 28 |
+
echo "Execution time: $runtime seconds"
|
eval_layer_llama.sh
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export HTTP_PROXY=http://sys-proxy-rd-relay.byted.org:8118
|
| 2 |
+
export http_proxy=http://sys-proxy-rd-relay.byted.org:8118
|
| 3 |
+
export https_proxy=http://sys-proxy-rd-relay.byted.org:8118
|
| 4 |
+
export no_proxy="$no_proxy,.byteintl.net"
|
| 5 |
+
export HF_ENDPOINT=https://hf-mirror.com
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
cd quantization_metric/
|
| 9 |
+
cuda_id=0
|
| 10 |
+
model_id="/mnt/bn/life-mllm/users/cxr/quantization/models/meta-llama/Llama-3.1-8B"
|
| 11 |
+
model_name=$(basename "$model_id")
|
| 12 |
+
|
| 13 |
+
model=/mnt/bn/life-mllm/users/cxr/quantization/models/${model_name}-quantization-layer
|
| 14 |
+
# output_dir=Alpha_values_mlp
|
| 15 |
+
# bit_layers_dir=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/bit_layers
|
| 16 |
+
# result_dir=/mnt/bn/life-mllm/users/cxr/quantization/lm-evaluation-harness/results
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
start=$(date +%s.%N)
|
| 21 |
+
# rm -rf $model
|
| 22 |
+
|
| 23 |
+
modes=("self_attn" "mlp")
|
| 24 |
+
for mode in ${modes[@]}; do
|
| 25 |
+
for idx in {-1..31}; do
|
| 26 |
+
echo $mode $idx
|
| 27 |
+
cd ../quantization_metric
|
| 28 |
+
python -u main.py --bit_layer_idx $idx --save_dir ${model} --mode $mode --model_id $model_id --cuda_id $cuda_id
|
| 29 |
+
cd ../lm-evaluation-harness
|
| 30 |
+
bash run_scripts/eval_base_qwen2_5_7b.sh ${model} ${mode}_${idx} $cuda_id
|
| 31 |
+
rm -rf ${model}
|
| 32 |
+
end=$(date +%s.%N)
|
| 33 |
+
runtime=$(awk "BEGIN {print $end - $start}")
|
| 34 |
+
echo "Execution time: $runtime seconds"
|
| 35 |
+
|
| 36 |
+
done
|
| 37 |
+
done
|
| 38 |
+
|
| 39 |
+
|
eval_layer_qwen.sh
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export HTTP_PROXY=http://sys-proxy-rd-relay.byted.org:8118
|
| 2 |
+
export http_proxy=http://sys-proxy-rd-relay.byted.org:8118
|
| 3 |
+
export https_proxy=http://sys-proxy-rd-relay.byted.org:8118
|
| 4 |
+
export no_proxy="$no_proxy,.byteintl.net"
|
| 5 |
+
export HF_ENDPOINT=https://hf-mirror.com
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
cd quantization_metric/
|
| 9 |
+
cuda_id=1
|
| 10 |
+
model_id=/mnt/bn/life-mllm/users/cxr/quantization/models/Qwen/Qwen2.5-7B
|
| 11 |
+
model_name=$(basename "$model_id")
|
| 12 |
+
|
| 13 |
+
model=/mnt/bn/life-mllm/users/cxr/quantization/models/${model_name}-quantization-layer
|
| 14 |
+
# output_dir=Alpha_values_mlp
|
| 15 |
+
# bit_layers_dir=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/bit_layers
|
| 16 |
+
# result_dir=/mnt/bn/life-mllm/users/cxr/quantization/lm-evaluation-harness/results
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
start=$(date +%s.%N)
|
| 21 |
+
# rm -rf $model
|
| 22 |
+
|
| 23 |
+
modes=("self_attn" "mlp")
|
| 24 |
+
for mode in ${modes[@]}; do
|
| 25 |
+
for idx in {-1..27}; do
|
| 26 |
+
echo $mode $idx
|
| 27 |
+
cd ../quantization_metric
|
| 28 |
+
python -u main.py --bit_layer_idx $idx --save_dir ${model} --mode $mode --model_id $model_id --cuda_id $cuda_id
|
| 29 |
+
cd ../lm-evaluation-harness
|
| 30 |
+
bash run_scripts/eval_base_qwen2_5_7b.sh ${model} ${mode}_${idx} $cuda_id
|
| 31 |
+
rm -rf ${model}
|
| 32 |
+
end=$(date +%s.%N)
|
| 33 |
+
runtime=$(awk "BEGIN {print $end - $start}")
|
| 34 |
+
echo "Execution time: $runtime seconds"
|
| 35 |
+
|
| 36 |
+
done
|
| 37 |
+
done
|
| 38 |
+
|
| 39 |
+
|
eval_zd.sh
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
export HTTP_PROXY=http://sys-proxy-rd-relay.byted.org:8118
|
| 2 |
+
export http_proxy=http://sys-proxy-rd-relay.byted.org:8118
|
| 3 |
+
export https_proxy=http://sys-proxy-rd-relay.byted.org:8118
|
| 4 |
+
export no_proxy="$no_proxy,.byteintl.net"
|
| 5 |
+
export HF_ENDPOINT=https://hf-mirror.com
|
| 6 |
+
|
| 7 |
+
cd quantization_metric/
|
| 8 |
+
model=../models/patch/Llama-2-7b-hf-quantization-zd
|
| 9 |
+
# output_dir=Alpha_values_mlp
|
| 10 |
+
tasks=piqa,winogrande,arc_easy,arc_challenge,hellaswag,boolq
|
| 11 |
+
# bit_layers_dir=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/bit_layers
|
| 12 |
+
# result_dir=/mnt/bn/life-mllm/users/cxr/quantization/lm-evaluation-harness/results
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
start=$(date +%s.%N)
|
| 16 |
+
# rm -rf $model
|
| 17 |
+
|
| 18 |
+
# file=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/metrics/ZD/ZD_mlp_Llama-2-7b-hf.json
|
| 19 |
+
file=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/metrics/ZD/ZD_self_attn_Llama-2-7b-hf.json
|
| 20 |
+
echo "$file"
|
| 21 |
+
cd ../quantization_metric
|
| 22 |
+
configure_id=$(basename $file .json)
|
| 23 |
+
python -u main_low.py --bit_layers $file --save_dir ${model} --k 5
|
| 24 |
+
cd ../lm-evaluation-harness
|
| 25 |
+
bash run_scripts/eval.sh ${configure_id} ${model} ${tasks}
|
| 26 |
+
rm -rf ${model}
|
| 27 |
+
end=$(date +%s.%N)
|
| 28 |
+
runtime=$(awk "BEGIN {print $end - $start}")
|
| 29 |
+
echo "Execution time: $runtime seconds"
|
inference.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
|
| 2 |
+
a= {"results": {
|
| 3 |
+
"arc_easy": {
|
| 4 |
+
"alias": "arc_easy",
|
| 5 |
+
"acc,none": 0.6902356902356902,
|
| 6 |
+
"acc_stderr,none": 0.00948817285190372,
|
| 7 |
+
"acc_norm,none": 0.6422558922558923,
|
| 8 |
+
"acc_norm_stderr,none": 0.00983577275734336
|
| 9 |
+
},
|
| 10 |
+
"arc_easy": {
|
| 11 |
+
"alias": "arc_easy",
|
| 12 |
+
"acc,none": 0.6902356902356902,
|
| 13 |
+
"acc_stderr,none": 0.00948817285190372,
|
| 14 |
+
"acc_norm,none": 0.6422558922558923,
|
| 15 |
+
"acc_norm_stderr,none": 0.00983577275734336
|
| 16 |
+
}
|
| 17 |
+
}
|
| 18 |
+
}
|
| 19 |
+
print(len(a['results']))
|
layerwise-awq.py
ADDED
|
@@ -0,0 +1,322 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- encoding:utf-8 -*-
|
| 2 |
+
@torch.no_grad()
|
| 3 |
+
def run_awq(
|
| 4 |
+
model,
|
| 5 |
+
enc,
|
| 6 |
+
w_bit,
|
| 7 |
+
q_config,
|
| 8 |
+
n_samples=512,
|
| 9 |
+
seqlen=512,
|
| 10 |
+
auto_scale=True,
|
| 11 |
+
mse_range=True,
|
| 12 |
+
calib_data="pileval", # data for calibration
|
| 13 |
+
skip_first: int = 0, # number of initial layers to keep in full precision
|
| 14 |
+
first_n: int = 0, # number of initial layers to apply first quant
|
| 15 |
+
w_bit_first: int | None = None,
|
| 16 |
+
w_bit_rest: int | None = None,
|
| 17 |
+
# --- mixed-precision strategy --------------------------------------------------
|
| 18 |
+
strategy: str = "layer", # "layer" (default): original solve layer-by-layer; "auto": structured mixed-precision
|
| 19 |
+
m_auto: int | None = None, # number of high-bit layers when strategy == "auto"; defaults to 25% of L
|
| 20 |
+
hi_bit: int = 4,
|
| 21 |
+
lo_bit: int = 2,
|
| 22 |
+
alpha: float = 1 / 3,
|
| 23 |
+
beta: float = 1 / 3,
|
| 24 |
+
gamma: float = 1 / 3,
|
| 25 |
+
k_energy: int = 32,
|
| 26 |
+
metrics_csv: str | None = None, # optional explicit path to metrics CSV (delta_ppl,erank_diff,topk_energy_diff)
|
| 27 |
+
):
|
| 28 |
+
from ..utils.calib_data import get_calib_dataset
|
| 29 |
+
from ..utils.module import append_str_prefix, get_op_name
|
| 30 |
+
|
| 31 |
+
if "bigcode" in str(model.__class__).lower():
|
| 32 |
+
# otherwise attention_mask will always be on cpu.
|
| 33 |
+
model.transformer.bias = model.transformer.bias.to("cuda")
|
| 34 |
+
|
| 35 |
+
layers = get_blocks(model)
|
| 36 |
+
|
| 37 |
+
samples = get_calib_dataset(
|
| 38 |
+
data=calib_data, tokenizer=enc, n_samples=n_samples, block_size=seqlen
|
| 39 |
+
)
|
| 40 |
+
samples = torch.cat(samples, dim=0)
|
| 41 |
+
|
| 42 |
+
inps = []
|
| 43 |
+
layer_kwargs = {}
|
| 44 |
+
|
| 45 |
+
layers[0] = layers[0].cuda()
|
| 46 |
+
move_embed(model, "cuda")
|
| 47 |
+
|
| 48 |
+
# get input and kwargs to layer 0
|
| 49 |
+
# with_kwargs is only supported in PyTorch 2.0
|
| 50 |
+
# use this Catcher hack for now
|
| 51 |
+
class Catcher(nn.Module):
|
| 52 |
+
def __init__(self, module):
|
| 53 |
+
super().__init__()
|
| 54 |
+
self.module = module
|
| 55 |
+
|
| 56 |
+
def forward(self, inp, **kwargs):
|
| 57 |
+
inps.append(inp)
|
| 58 |
+
layer_kwargs.update(kwargs)
|
| 59 |
+
raise ValueError # early exit to break later inference
|
| 60 |
+
|
| 61 |
+
# patch layer 0 to catch input and kwargs
|
| 62 |
+
layers[0] = Catcher(layers[0])
|
| 63 |
+
try:
|
| 64 |
+
if model.__class__.__name__ == "LlavaLlamaModel":
|
| 65 |
+
model.llm(samples.to(next(model.parameters()).device))
|
| 66 |
+
elif model.__class__.__name__ == "InternVL3":
|
| 67 |
+
model.language_model(samples.to(next(model.parameters()).device))
|
| 68 |
+
else:
|
| 69 |
+
model(samples.to(next(model.parameters()).device))
|
| 70 |
+
except ValueError: # work with early exit
|
| 71 |
+
pass
|
| 72 |
+
del samples
|
| 73 |
+
layers[0] = layers[0].module # restore
|
| 74 |
+
inps = inps[0]
|
| 75 |
+
|
| 76 |
+
layers[0] = layers[0].cpu()
|
| 77 |
+
move_embed(model, "cpu")
|
| 78 |
+
|
| 79 |
+
gc.collect()
|
| 80 |
+
torch.cuda.empty_cache()
|
| 81 |
+
|
| 82 |
+
awq_results = {
|
| 83 |
+
"scale": [],
|
| 84 |
+
"clip": [],
|
| 85 |
+
}
|
| 86 |
+
|
| 87 |
+
# ---------------------------------------------------------------------------
|
| 88 |
+
# Determine per-layer bit-widths according to the requested *strategy*
|
| 89 |
+
# ---------------------------------------------------------------------------
|
| 90 |
+
|
| 91 |
+
if strategy.lower() == "auto":
|
| 92 |
+
# -------------------------------------------------------------------
|
| 93 |
+
# Use qpRANK pre-computed diagnostics to decide per-layer precision.
|
| 94 |
+
# Users may place the JSON files (drop_layer_ppl.json, diff_erank_values.json)
|
| 95 |
+
# under the project root (default path) or supply env QPRANK_METRICS_DIR.
|
| 96 |
+
# -------------------------------------------------------------------
|
| 97 |
+
|
| 98 |
+
import json, os, math, csv
|
| 99 |
+
|
| 100 |
+
def _load_metrics_from_csv(csv_path: str):
|
| 101 |
+
"""Return delta_ppl, erank_diff, topk_energy_diff lists from a csv file."""
|
| 102 |
+
delta_ppl, erank, topk = [], [], []
|
| 103 |
+
with open(csv_path, "r", encoding="utf-8") as f:
|
| 104 |
+
reader = csv.DictReader(f)
|
| 105 |
+
for row in reader:
|
| 106 |
+
delta_ppl.append(float(row.get("delta_ppl", 0)))
|
| 107 |
+
erank.append(abs(float(row.get("erank_diff", 0))))
|
| 108 |
+
topk_val = row.get("topk_energy_diff")
|
| 109 |
+
if topk_val is not None and topk_val != "":
|
| 110 |
+
topk.append(float(topk_val))
|
| 111 |
+
# Ensure all same length
|
| 112 |
+
assert len(delta_ppl) == len(erank), "CSV length mismatch"
|
| 113 |
+
if len(topk) != len(delta_ppl):
|
| 114 |
+
topk = [0.0] * len(delta_ppl)
|
| 115 |
+
return delta_ppl, erank, topk
|
| 116 |
+
|
| 117 |
+
delta_ppl: List[float]
|
| 118 |
+
delta_r: List[float]
|
| 119 |
+
delta_e: List[float]
|
| 120 |
+
|
| 121 |
+
# Priority 1: explicit CSV path
|
| 122 |
+
if metrics_csv is not None and os.path.isfile(metrics_csv):
|
| 123 |
+
delta_ppl, delta_r, delta_e = _load_metrics_from_csv(metrics_csv)
|
| 124 |
+
else:
|
| 125 |
+
# Priority 2: auto-detect inside QPRANK directory structure
|
| 126 |
+
base_dir = os.getenv("QPRANK_METRICS_DIR", os.path.expanduser("~/qpRANK/src"))
|
| 127 |
+
|
| 128 |
+
# Derive a crude model identifier from config
|
| 129 |
+
cfg_name = getattr(model, "config", None)
|
| 130 |
+
model_id = (
|
| 131 |
+
getattr(cfg_name, "_name_or_path", "model").replace("/", "_")
|
| 132 |
+
if cfg_name is not None
|
| 133 |
+
else "model"
|
| 134 |
+
)
|
| 135 |
+
|
| 136 |
+
# Traverse to find a metrics_long.csv matching pattern
|
| 137 |
+
candidate_csv = None
|
| 138 |
+
for root, dirs, files in os.walk(base_dir):
|
| 139 |
+
if "metrics_long.csv" in files and model_id in root:
|
| 140 |
+
candidate_csv = os.path.join(root, "metrics_long.csv")
|
| 141 |
+
break
|
| 142 |
+
|
| 143 |
+
if candidate_csv and os.path.isfile(candidate_csv):
|
| 144 |
+
delta_ppl, delta_r, delta_e = _load_metrics_from_csv(candidate_csv)
|
| 145 |
+
else:
|
| 146 |
+
# Fallback to old JSON files (legacy)
|
| 147 |
+
metrics_dir = os.getenv("QPRANK_METRICS_DIR", os.path.expanduser("~/qpRANK"))
|
| 148 |
+
ppl_path = os.path.join(metrics_dir, "drop_layer_ppl.json")
|
| 149 |
+
erank_path = os.path.join(metrics_dir, "diff_erank_values.json")
|
| 150 |
+
|
| 151 |
+
if not (os.path.isfile(ppl_path) and os.path.isfile(erank_path)):
|
| 152 |
+
raise FileNotFoundError(
|
| 153 |
+
"Cannot locate per-layer metric files for auto strategy. Provide metrics_csv path or set QPRANK_METRICS_DIR appropriately."
|
| 154 |
+
)
|
| 155 |
+
|
| 156 |
+
delta_ppl = json.load(open(ppl_path, "r"))["delta_ppl"]
|
| 157 |
+
erank_json = json.load(open(erank_path, "r"))
|
| 158 |
+
|
| 159 |
+
keys = [k for k in ("q", "k", "v") if k in erank_json]
|
| 160 |
+
delta_r = [
|
| 161 |
+
sum(erank_json[k][i] for k in keys) / len(keys)
|
| 162 |
+
for i in range(len(delta_ppl))
|
| 163 |
+
]
|
| 164 |
+
|
| 165 |
+
delta_e = erank_json.get("topk_energy_diff", [0.0] * len(delta_ppl))
|
| 166 |
+
#! layer 的数量
|
| 167 |
+
L_total = len(delta_ppl)
|
| 168 |
+
|
| 169 |
+
# Normalise
|
| 170 |
+
def _norm(arr):
|
| 171 |
+
m = max(arr) if max(arr) > 0 else 1.0
|
| 172 |
+
return [x / m for x in arr]
|
| 173 |
+
|
| 174 |
+
ppl_hat = _norm(delta_ppl)
|
| 175 |
+
r_hat = _norm(delta_r)
|
| 176 |
+
e_hat = _norm(delta_e)
|
| 177 |
+
|
| 178 |
+
scores = [
|
| 179 |
+
alpha * ppl_hat[i] + beta * r_hat[i] + gamma * e_hat[i]
|
| 180 |
+
for i in range(L_total)
|
| 181 |
+
]
|
| 182 |
+
|
| 183 |
+
#! 1/4 的 layer
|
| 184 |
+
if m_auto is None:
|
| 185 |
+
m_auto = max(1, L_total // 4)
|
| 186 |
+
|
| 187 |
+
idx_sorted = sorted(range(L_total), key=lambda i: scores[i], reverse=True)
|
| 188 |
+
#! 前 1/4 的 layer 用 high bit, 其他的用 low bit
|
| 189 |
+
hi_set = set(idx_sorted[:m_auto])
|
| 190 |
+
|
| 191 |
+
#! 每个 layer 的 bit 数量的分配
|
| 192 |
+
#! 我们也是在这边修改成得到我们的 layer 分配就好了
|
| 193 |
+
bits_per_layer = [hi_bit if i in hi_set else lo_bit for i in range(L_total)]
|
| 194 |
+
|
| 195 |
+
# ---- verbose print & log ----
|
| 196 |
+
try:
|
| 197 |
+
import logging
|
| 198 |
+
_logger = logging.getLogger(__name__)
|
| 199 |
+
except ImportError:
|
| 200 |
+
_logger = None
|
| 201 |
+
|
| 202 |
+
print("[AUTO] Per-layer bit-width allocation (index:bit):")
|
| 203 |
+
mapping_str = ", ".join(f"{idx}:{bits_per_layer[idx]}b" for idx in range(L_total))
|
| 204 |
+
print(mapping_str)
|
| 205 |
+
|
| 206 |
+
if _logger is not None:
|
| 207 |
+
_logger.info("AUTO bit-width allocation: " + mapping_str)
|
| 208 |
+
|
| 209 |
+
print(f"[AUTO] Layers @ {hi_bit}-bit: {sorted(list(hi_set))}")
|
| 210 |
+
print(f"[AUTO] Layers @ {lo_bit}-bit: {sorted([i for i in range(L_total) if i not in hi_set])}")
|
| 211 |
+
|
| 212 |
+
if _logger is not None:
|
| 213 |
+
_logger.info(f"Layers_{hi_bit}bit: {sorted(list(hi_set))}")
|
| 214 |
+
_logger.info(f"Layers_{lo_bit}bit: {[i for i in range(L_total) if i not in hi_set]}")
|
| 215 |
+
|
| 216 |
+
else:
|
| 217 |
+
# Fallback to original scheme (uniform or head/tail mixed precision).
|
| 218 |
+
bits_per_layer = None # will be decided on the fly as before
|
| 219 |
+
|
| 220 |
+
# solve layer by layer
|
| 221 |
+
for i in tqdm.tqdm(range(len(layers)), desc="Running AWQ..."):
|
| 222 |
+
# print(f"Layer {i} of {len(layers)-1}")
|
| 223 |
+
layer = layers[i]
|
| 224 |
+
|
| 225 |
+
# Flag: whether to apply quantization to this layer
|
| 226 |
+
#! 他们也指定了超参数从第几层开始量化
|
| 227 |
+
quantize_this = i >= skip_first
|
| 228 |
+
|
| 229 |
+
# Determine bit-width for this layer
|
| 230 |
+
if strategy.lower() == "auto" and bits_per_layer is not None:
|
| 231 |
+
current_w_bit = bits_per_layer[i]
|
| 232 |
+
if i == 0:
|
| 233 |
+
# show a brief summary once for user awareness
|
| 234 |
+
print(
|
| 235 |
+
f"[AUTO] Using structured mixed-precision: {sum(b == hi_bit for b in bits_per_layer)} layers @ {hi_bit}-bit, {sum(b == lo_bit for b in bits_per_layer)} layers @ {lo_bit}-bit."
|
| 236 |
+
)
|
| 237 |
+
else:
|
| 238 |
+
# original rule-based selection
|
| 239 |
+
if i < first_n:
|
| 240 |
+
current_w_bit = w_bit_first if w_bit_first is not None else w_bit
|
| 241 |
+
print(
|
| 242 |
+
f"Layer {i} is quantizing with {current_w_bit} bits. (when this sentence isnt printed, it is quantizing with {w_bit_rest} bits)"
|
| 243 |
+
)
|
| 244 |
+
else:
|
| 245 |
+
current_w_bit = w_bit_rest if w_bit_rest is not None else w_bit
|
| 246 |
+
|
| 247 |
+
|
| 248 |
+
#! 从这边往后就和原来的代码一样
|
| 249 |
+
layer = layer.cuda()
|
| 250 |
+
named_linears = get_named_linears(layer)
|
| 251 |
+
|
| 252 |
+
# firstly, get input features of all linear layers
|
| 253 |
+
def cache_input_hook(m, x, y, name, feat_dict):
|
| 254 |
+
x = x[0]
|
| 255 |
+
x = x.detach().cpu()
|
| 256 |
+
feat_dict[name].append(x)
|
| 257 |
+
|
| 258 |
+
input_feat = defaultdict(list)
|
| 259 |
+
handles = []
|
| 260 |
+
for name in named_linears:
|
| 261 |
+
handles.append(
|
| 262 |
+
named_linears[name].register_forward_hook(
|
| 263 |
+
functools.partial(cache_input_hook, name=name, feat_dict=input_feat)
|
| 264 |
+
)
|
| 265 |
+
)
|
| 266 |
+
inps = inps.to(next(layer.parameters()).device) # in case multi-gpu
|
| 267 |
+
# get output as next layer's input
|
| 268 |
+
inps = layer(inps, **layer_kwargs)[0]
|
| 269 |
+
for h in handles:
|
| 270 |
+
h.remove()
|
| 271 |
+
# now solve for scaling and clipping
|
| 272 |
+
input_feat = {k: torch.cat(v, dim=0) for k, v in input_feat.items()}
|
| 273 |
+
|
| 274 |
+
# Clear GPU memory
|
| 275 |
+
torch.cuda.empty_cache()
|
| 276 |
+
|
| 277 |
+
if (
|
| 278 |
+
auto_scale
|
| 279 |
+
): # if it applies, we should also modify the input_feat with scales
|
| 280 |
+
scales_list = auto_scale_block(
|
| 281 |
+
layer,
|
| 282 |
+
layer_kwargs,
|
| 283 |
+
w_bit=current_w_bit, #! 改成 current_w_bit 就可以
|
| 284 |
+
q_config=q_config,
|
| 285 |
+
input_feat=input_feat,
|
| 286 |
+
)
|
| 287 |
+
# apply_scale(layer, scales_list, input_feat_dict=input_feat)
|
| 288 |
+
apply_scale(layers[i], scales_list, input_feat_dict=input_feat)
|
| 289 |
+
# append prefix to make names global
|
| 290 |
+
awq_results["scale"] += append_str_prefix(
|
| 291 |
+
scales_list, get_op_name(model, layer) + "."
|
| 292 |
+
)
|
| 293 |
+
|
| 294 |
+
# Clear GPU memory
|
| 295 |
+
torch.cuda.empty_cache()
|
| 296 |
+
# for line in torch.cuda.memory_summary().splitlines():
|
| 297 |
+
# if "Allocated" in line:
|
| 298 |
+
# print(line)
|
| 299 |
+
|
| 300 |
+
if mse_range:
|
| 301 |
+
clip_list = auto_clip_block(
|
| 302 |
+
layer,
|
| 303 |
+
w_bit=current_w_bit, #! 改成 current_w_bit 就可以
|
| 304 |
+
q_config=q_config,
|
| 305 |
+
input_feat=input_feat,
|
| 306 |
+
)
|
| 307 |
+
apply_clip(layer, clip_list)
|
| 308 |
+
# append prefix to make names global
|
| 309 |
+
awq_results["clip"] += append_str_prefix(
|
| 310 |
+
clip_list, get_op_name(model, layer) + "."
|
| 311 |
+
)
|
| 312 |
+
|
| 313 |
+
layer = layer.cpu()
|
| 314 |
+
# Haotian: check activation replacement
|
| 315 |
+
del input_feat
|
| 316 |
+
gc.collect()
|
| 317 |
+
torch.cuda.empty_cache()
|
| 318 |
+
# for line in torch.cuda.memory_summary().splitlines():
|
| 319 |
+
# if "Allocated" in line:
|
| 320 |
+
# print(line)
|
| 321 |
+
|
| 322 |
+
return awq_results
|
llm-awq/README.md
ADDED
|
@@ -0,0 +1,292 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration
|
| 2 |
+
[[Paper](https://arxiv.org/abs/2306.00978)][[Website](https://hanlab.mit.edu/projects/awq)]
|
| 3 |
+
|
| 4 |
+
**Efficient and accurate** low-bit weight quantization (INT3/4) for LLMs, supporting **instruction-tuned** models and **multi-modal** LMs.
|
| 5 |
+
|
| 6 |
+

|
| 7 |
+
|
| 8 |
+
The current release supports:
|
| 9 |
+
|
| 10 |
+
- AWQ search for accurate quantization.
|
| 11 |
+
- Pre-computed AWQ model zoo for LLMs (Llama-1/2/3, OPT, CodeLlama, StarCoder, Vicuna, VILA, LLaVA; load to generate quantized weights).
|
| 12 |
+
- Memory-efficient 4-bit Linear in PyTorch.
|
| 13 |
+
- Efficient CUDA kernel implementation for fast inference (support context and decoding stage).
|
| 14 |
+
- Examples on 4-bit inference of an instruction-tuned model (Vicuna) and **multi-modal LM** (VILA).
|
| 15 |
+
- Chunk prefilling for faster prefilling in multi-round Q&A setting.
|
| 16 |
+
- State-of-the-art prefilling speed of LLMs/VLMs on edge devices: [TinyChat 2.0](./tinychat).
|
| 17 |
+
|
| 18 |
+
**Thanks to AWQ, TinyChat can deliver more efficient responses with LLM/VLM chatbots through 4-bit inference.**
|
| 19 |
+
|
| 20 |
+
* TinyChat with LLaMA-3-8b on RTX 4090 (2.7x faster than FP16):
|
| 21 |
+
|
| 22 |
+

|
| 23 |
+
|
| 24 |
+
* TinyChat with LLaMA-3-8b on Jetson Orin (2.9x faster than FP16):
|
| 25 |
+
|
| 26 |
+

|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
**TinyChat also supports inference with vision language models (e.g., VILA, LLaVA). In the following examples, W4A16 quantized models from VILA family are launched with TinyChat.**
|
| 30 |
+
|
| 31 |
+
* TinyChat with NVILA-8B on RTX 4090 (single-image inputs):
|
| 32 |
+
|
| 33 |
+

|
| 34 |
+
|
| 35 |
+
* TinyChat with NVILA-8B on RTX 4090 (multi-image inputs):
|
| 36 |
+
|
| 37 |
+

|
| 38 |
+
|
| 39 |
+
<!-- Check out [TinyChat](tinychat), which delievers **30 tokens/second** inference performance (**3.2x faster** than FP16) for the **Llama2** chatbot on the resource-constrained NVIDIA Jetson Orin! -->
|
| 40 |
+
|
| 41 |
+
* TinyChat with video reasoning:
|
| 42 |
+
|
| 43 |
+
https://github.com/user-attachments/assets/b68a7a0d-5175-4030-985b-5ae0ae94f874
|
| 44 |
+
|
| 45 |
+
**Prompt:** What might be the next step according to the video?
|
| 46 |
+
|
| 47 |
+
**Answer:** The next step in the video could be to place the shaped dough onto a baking sheet and let it rise before baking.
|
| 48 |
+
|
| 49 |
+
**Online demo:** https://vila.hanlab.ai
|
| 50 |
+
|
| 51 |
+
Check out [TinyChat](tinychat), which offers a turn-key solution for **on-device inference** of LLMs and VLMs on **resource-constrained edge platforms**. With TinyChat, it is now possible to efficiently run **large** models on **small** and **low-power** devices even without Internet connection!
|
| 52 |
+
|
| 53 |
+
|
| 54 |
+
## News
|
| 55 |
+
- [2025/04] 🔥 AWQ now supports DeepSeek-R1-Distilled models. Try our example [here](https://github.com/mit-han-lab/llm-awq/blob/main/scripts/DeepSeek_R1_Distill_example.sh)!
|
| 56 |
+
- [2025/02] AWQ now supports BF16 precision. See example [here](https://github.com/mit-han-lab/llm-awq/blob/main/scripts/qwen_example.sh).
|
| 57 |
+
- [2024/10] 🔥⚡ Explore advancements in [TinyChat 2.0](./tinychat), the latest version with significant advancements in prefilling speed of Edge LLMs and VLMs, **1.5-1.7x** faster than the previous version of TinyChat. Please refer to the [README](./tinychat/README.md) and [blog](https://hanlab.mit.edu/blog/tinychat20) for more details.
|
| 58 |
+
- [2024/05] 🏆 AWQ receives the **Best Paper Award** at **MLSys 2024**. 🎉
|
| 59 |
+
- [2024/05] 🔥 The **VILA-1.5** model family which features **video understanding** is now supported in AWQ and TinyChat. Check out out online demo powered by TinyChat [here](https://vila.hanlab.ai). Example is [here](scripts/vila15_example.sh).
|
| 60 |
+
- [2024/05] 🔥 [AMD](https://community.amd.com/t5/ai/reduce-memory-footprint-and-improve-performance-running-llms-on/ba-p/686157) adopts AWQ to improve LLM serving efficiency.
|
| 61 |
+
- [2024/04] 🔥 We released AWQ and TinyChat support for The **Llama-3** model family! Check out our example [here](scripts/llama3_example.sh).
|
| 62 |
+
- [2024/02] 🔥 AWQ has been accepted to **MLSys 2024**!
|
| 63 |
+
- [2024/02] 🔥 We supported [VILA Vision Languague Models](https://arxiv.org/abs/2312.07533) in AWQ & TinyChat! Check our latest demos with multi-image inputs!
|
| 64 |
+
- [2024/02] 🔥 We released new version of quantized GEMM/GEMV kernels in [**TinyChat**](tinychat), leading to **38 tokens/second** inference speed on NVIDIA Jetson Orin!
|
| 65 |
+
- [2024/01] 🔥 AWQ has been integrated by [Google Vertex AI](https://console.cloud.google.com/vertex-ai/publishers/meta/model-garden/llama-2-quantized)!
|
| 66 |
+
- [2023/11] 🔥 AWQ has been integrated by [Amazon Sagemaker Containers](https://aws.amazon.com/blogs/machine-learning/boost-inference-performance-for-llms-with-new-amazon-sagemaker-containers/)!
|
| 67 |
+
- [2023/11] 🔥 We added AWQ support and pre-computed search results for CodeLlama, StarCoder, StableCode models. Checkout our model zoo [here](https://huggingface.co/datasets/mit-han-lab/awq-model-zoo)!
|
| 68 |
+
- [2023/11] 🔥 AWQ is now integrated natively in Hugging Face transformers through `from_pretrained`. You can either load quantized models from the Hub or your own HF quantized models.
|
| 69 |
+
- [2023/10] AWQ is integrated into NVIDIA [TensorRT-LLM](https://github.com/NVIDIA/TensorRT-LLM/)
|
| 70 |
+
- [2023/09] AWQ is integrated into [Intel Neural Compressor](https://github.com/intel/neural-compressor), [FastChat](https://github.com/lm-sys/FastChat/blob/main/docs/awq.md), [vLLM](https://github.com/vllm-project/vllm/blob/main/vllm/model_executor/layers/quantization/awq.py), [HuggingFace TGI](https://github.com/huggingface/text-generation-inference/pull/1054), and [LMDeploy](https://github.com/InternLM/lmdeploy).
|
| 71 |
+
- [2023/09] ⚡ Check out our latest [**TinyChat**](tinychat), which is ~2x faster than the first release on Orin!
|
| 72 |
+
- [2023/09] ⚡ Check out [**AutoAWQ**](https://github.com/casper-hansen/AutoAWQ), a third-party implementation to make AWQ easier to expand to new models, improve inference speed, and integrate into Huggingface.
|
| 73 |
+
- [2023/07] 🔥 We released **TinyChat**, an efficient and lightweight chatbot interface based on AWQ. TinyChat enables efficient LLM inference on both cloud and edge GPUs. Llama-2-chat models are supported! Check out our implementation [here](tinychat).
|
| 74 |
+
- [2023/07] 🔥 We added AWQ support and pre-computed search results for Llama-2 models (7B & 13B). Checkout our model zoo [here](https://huggingface.co/datasets/mit-han-lab/awq-model-zoo)!
|
| 75 |
+
- [2023/07] We extended the support for more LLM models including MPT, Falcon, and BLOOM.
|
| 76 |
+
|
| 77 |
+
## Contents
|
| 78 |
+
|
| 79 |
+
- [AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration](#awq-activation-aware-weight-quantization-for-llm-compression-and-acceleration)
|
| 80 |
+
- [News](#news)
|
| 81 |
+
- [Contents](#contents)
|
| 82 |
+
- [Helpful Links](#helpful-links)
|
| 83 |
+
- [Install](#install)
|
| 84 |
+
- [AWQ Model Zoo](#awq-model-zoo)
|
| 85 |
+
- [Examples](#examples)
|
| 86 |
+
- [Usage](#usage)
|
| 87 |
+
- [Results on Visual Language Models](#results-on-visual-language-models)
|
| 88 |
+
- [Reference](#reference)
|
| 89 |
+
- [Related Projects](#related-projects)
|
| 90 |
+
|
| 91 |
+
## Helpful Links
|
| 92 |
+
|
| 93 |
+
- [VILA online demo](vila.hanlab.ai): Visual Language Models efficiently supported by AWQ & TinyChat.
|
| 94 |
+
- [LLM on the Edge](https://github.com/mit-han-lab/llm-awq/tree/nv_laptop?tab=readme-ov-file#install): AWQ and TinyChat support edge GPUs such as NVIDIA Jetson Orin.
|
| 95 |
+
- [VLMs on Laptop](https://github.com/mit-han-lab/llm-awq/tree/nv_laptop?tab=readme-ov-file#run-vila-on-laptop): Follow the instructions to deploy VLMs on NVIDIA Laptops with TinyChat.
|
| 96 |
+
- [Gradio Server](https://github.com/mit-han-lab/llm-awq/tree/nv_laptop/tinychat/serve#gradio-demo-vila-with-tinychat): Try to build your own VLM online demo with AWQ and TinyChat!
|
| 97 |
+
- [QServe](https://github.com/mit-han-lab/qserve): 🔥 **[New]** Efficient and accurate serving system for large-scale LLM inference.
|
| 98 |
+
|
| 99 |
+
## Install
|
| 100 |
+
|
| 101 |
+
1. Clone this repository and navigate to AWQ folder
|
| 102 |
+
```
|
| 103 |
+
git clone https://github.com/mit-han-lab/llm-awq
|
| 104 |
+
cd llm-awq
|
| 105 |
+
```
|
| 106 |
+
|
| 107 |
+
2. Install Package
|
| 108 |
+
```
|
| 109 |
+
conda create -n awq python=3.10 -y
|
| 110 |
+
conda activate awq
|
| 111 |
+
pip install --upgrade pip # enable PEP 660 support
|
| 112 |
+
pip install -e .
|
| 113 |
+
```
|
| 114 |
+
|
| 115 |
+
* For **edge devices** like Orin, before running the commands above, please:
|
| 116 |
+
|
| 117 |
+
1. Modify [pyproject.toml](pyproject.toml) by commenting out [this line](https://github.com/mit-han-lab/llm-awq/blob/3fce69061682fdd528824e5da3d03a8a8b545f2a/pyproject.toml#L17).
|
| 118 |
+
2. Manually install precompiled PyTorch binaries (>=2.0.0) from [NVIDIA](https://forums.developer.nvidia.com/t/pytorch-for-jetson/72048). You also need to install torchvision from this website when running NVILA.
|
| 119 |
+
3. Set the appropriate Python version for conda environment (e.g., `conda create -n awq python=3.8 -y` for JetPack 5).
|
| 120 |
+
|
| 121 |
+
3. Install efficient W4A16 (4-bit weight, 16-bit activation) CUDA kernel and optimized FP16 kernels (e.g. layernorm, positional encodings).
|
| 122 |
+
```
|
| 123 |
+
cd awq/kernels
|
| 124 |
+
python setup.py install
|
| 125 |
+
```
|
| 126 |
+
|
| 127 |
+
4. Install Flash Attention
|
| 128 |
+
```
|
| 129 |
+
pip install flash-attn --no-build-isolation
|
| 130 |
+
```
|
| 131 |
+
|
| 132 |
+
We recommend starting an interactive python CLI interface and run `import flash_attn` to check whether FlashAttention-2 is installed successfully. If not, we recommend downloading pre-built wheels from [here](https://github.com/Dao-AILab/flash-attention/releases/tag/v2.5.8). Please notice:
|
| 133 |
+
|
| 134 |
+
- PyTorch version needs to exactly match with the version specified in the `.whl` name;
|
| 135 |
+
- Check out both `cxx11abiTRUE` and `cxx11abiFALSE` wheels if one of them does not work;
|
| 136 |
+
- It's recommended to match CUDA version specified in the `.whl` filename, but minor mismatches (e.g. 12.1 vs 12.2, or even 11.8 vs 12.2) usually do not matter.
|
| 137 |
+
|
| 138 |
+
|
| 139 |
+
5. [Optional] In order to run AWQ and TinyChat with NVILA model family, please install VILA:
|
| 140 |
+
|
| 141 |
+
```bash
|
| 142 |
+
git clone https://github.com/NVlabs/VILA.git
|
| 143 |
+
cd VILA
|
| 144 |
+
pip install -e .
|
| 145 |
+
```
|
| 146 |
+
|
| 147 |
+
## AWQ Model Zoo
|
| 148 |
+
|
| 149 |
+
We provide pre-computed AWQ search results for multiple model families, including LLaMA, OPT, Vicuna, and LLaVA. To get the pre-computed AWQ search results, run:
|
| 150 |
+
|
| 151 |
+
```bash
|
| 152 |
+
# git lfs install # install git lfs if not already
|
| 153 |
+
git clone https://huggingface.co/datasets/mit-han-lab/awq-model-zoo awq_cache
|
| 154 |
+
```
|
| 155 |
+
|
| 156 |
+
The detailed support list:
|
| 157 |
+
|
| 158 |
+
| Models | Sizes | INT4-g128 | INT3-g128 |
|
| 159 |
+
| ------ | --------------------------- | --------- | --------- |
|
| 160 |
+
| [DeepSeek-R1-Distill](/scripts/DeepSeek_R1_Distill_example.sh) | 1.5B/7B/8B | ✅ | |
|
| 161 |
+
| [Qwen-2.5](/scripts/qwen_example.sh) | 7B/72B | ✅ | |
|
| 162 |
+
| [NVILA](/scripts/nvila_example.sh) | 3B/8B | ✅ | |
|
| 163 |
+
| [VILA-1.5](/scripts/vila15_example.sh) | 3B/8B/13B/40B | ✅ | ✅ |
|
| 164 |
+
| [Llama3](/scripts/llama_example.sh) | 8B/70B | ✅ | ✅ |
|
| 165 |
+
| [VILA](/scripts/vila_example.sh) | 7B/13B | ✅ | |
|
| 166 |
+
| [Llama2](/scripts/llama_example.sh) | 7B/13B/70B | ✅ | ✅ |
|
| 167 |
+
| [LLaMA](/scripts/llama2_example.sh) | 7B/13B/30B/65B | ✅ | ✅ |
|
| 168 |
+
| [OPT](/scripts/opt_example.sh) | 125m/1.3B/2.7B/6.7B/13B/30B | ✅ | ✅ |
|
| 169 |
+
| [CodeLlama](/scripts/codellama_example.sh) | 7B/13B/34B | ✅ | ✅ |
|
| 170 |
+
| [StarCoder](/scripts/starcoder_example.sh) | 15.5B | ✅ | ✅ |
|
| 171 |
+
| [Vicuna-v1.1](/scripts/vicuna_example.sh) | 7B/13B | ✅ | |
|
| 172 |
+
| [LLaVA-v0](/scripts/llava_example.sh) | 13B | ✅ | |
|
| 173 |
+
|
| 174 |
+
Note: We only list models that we have prepare the [AWQ searching results](https://huggingface.co/datasets/mit-han-lab/awq-model-zoo/tree/main) in the table above. AWQ also supports models such as LLaVA-v1.5 7B, and you may need to run the [AWQ search](#usage) on your own to quantize these models. For our latest VLM NVILA, quantized weights are available [here](https://huggingface.co/Efficient-Large-Model/NVILA-AWQ).
|
| 175 |
+
|
| 176 |
+
## Examples
|
| 177 |
+
|
| 178 |
+
AWQ can be easily applied to various LMs thanks to its good generalization, including instruction-tuned models and multi-modal LMs. It provides an easy-to-use tool to reduce the serving cost of LLMs.
|
| 179 |
+
|
| 180 |
+
Here we provide two examples of AWQ application: Vicuna-7B (chatbot) and LLaVA-13B (visual reasoning) under `./examples` directory. AWQ can easily reduce the GPU memory of model serving and speed up token generation. It provides accurate quantization, providing reasoning outputs. You should be able to observe **memory savings** when running the models with 4-bit weights.
|
| 181 |
+
|
| 182 |
+
Note that we perform AWQ using only textual calibration data, depsite we are running on multi-modal input. Please refer to `./examples` for details.
|
| 183 |
+
|
| 184 |
+

|
| 185 |
+
|
| 186 |
+
## Usage
|
| 187 |
+
|
| 188 |
+
We provide several sample script to run AWQ (please refer to `./scripts`). We use Llama3-8B as an example.
|
| 189 |
+
|
| 190 |
+
1. Perform AWQ search and save search results (we already did it for you):
|
| 191 |
+
```bash
|
| 192 |
+
python -m awq.entry --model_path /PATH/TO/LLAMA3/llama3-8b \
|
| 193 |
+
--w_bit 4 --q_group_size 128 \
|
| 194 |
+
--run_awq --dump_awq awq_cache/llama3-8b-w4-g128.pt
|
| 195 |
+
```
|
| 196 |
+
|
| 197 |
+
2. Evaluate the AWQ quantized model on WikiText-2 (simulated pseudo quantization)
|
| 198 |
+
```bash
|
| 199 |
+
python -m awq.entry --model_path /PATH/TO/LLAMA3/llama3-8b \
|
| 200 |
+
--tasks wikitext \
|
| 201 |
+
--w_bit 4 --q_group_size 128 \
|
| 202 |
+
--load_awq awq_cache/llama3-8b-w4-g128.pt \
|
| 203 |
+
--q_backend fake
|
| 204 |
+
```
|
| 205 |
+
|
| 206 |
+
3. Generate real quantized weights (INT4)
|
| 207 |
+
```bash
|
| 208 |
+
mkdir quant_cache
|
| 209 |
+
python -m awq.entry --model_path /PATH/TO/LLAMA3/llama3-8b \
|
| 210 |
+
--w_bit 4 --q_group_size 128 \
|
| 211 |
+
--load_awq awq_cache/llama3-8b-w4-g128.pt \
|
| 212 |
+
--q_backend real --dump_quant quant_cache/llama3-8b-w4-g128-awq.pt
|
| 213 |
+
```
|
| 214 |
+
|
| 215 |
+
4. Load and evaluate the real quantized model (now you can see smaller gpu memory usage)
|
| 216 |
+
```bash
|
| 217 |
+
python -m awq.entry --model_path /PATH/TO/LLAMA3/llama3-8b \
|
| 218 |
+
--tasks wikitext \
|
| 219 |
+
--w_bit 4 --q_group_size 128 \
|
| 220 |
+
--load_quant quant_cache/llama3-8b-w4-g128-awq.pt
|
| 221 |
+
```
|
| 222 |
+
## Results on Visual Language Models
|
| 223 |
+
|
| 224 |
+
AWQ also seamlessly supports large multi-modal models (LMMs). Please refer to [TinyChat](./tinychat/README.md) for more details.
|
| 225 |
+
|
| 226 |
+
|
| 227 |
+
<!-- AWQ also seamlessly supports large multi-modal models (LMMs). We demonstrate the results on the recent [VILA-1.5](https://github.com/Efficient-Large-Model/VILA) model family. -->
|
| 228 |
+
|
| 229 |
+
<!--
|
| 230 |
+
| VILA-1.5-3B | VQA-v2 | GQA | VizWiz | ScienceQA | TextVQA | POPE | MME | MMBench | MMBench-CN | SEED |
|
| 231 |
+
| ----------- |:-----------------:|:-----------------:|:-------:|:-----------------:|:-----------------:|:-------:|:-------:|:-----------------:|:-------------:|:-------:|
|
| 232 |
+
| FP16 | 80.4 | 61.5 | 53.5 | 69.0 | 60.4 | 85.9 | 1442.4 | 63.4 | 52.7 | 60.9 |
|
| 233 |
+
| AWQ-INT4 | 80.0 | 61.1 | 53.8 | 67.8 | 60.4 | 85.9 | 1437.3 | 63.3 | 51.4 | 59.8 |
|
| 234 |
+
|
| 235 |
+
| VILA-1.5-8B | VQA-v2 | GQA | VizWiz | ScienceQA | TextVQA | POPE | MME | MMBench | MMBench-CN | SEED |
|
| 236 |
+
| ----------- |:-----------------:|:-----------------:|:-------:|:-----------------:|:-----------------:|:-------:|:-------:|:-----------------:|:-------------:|:-------:|
|
| 237 |
+
| FP16 | 80.9 | 61.9 | 58.7 | 79.9 | 66.3 | 84.4 | 1577.01 | 72.3 | 66.2 | 64.2 |
|
| 238 |
+
| AWQ-INT4 | 80.3 | 61.7 | 59.3 | 79.0 | 65.4 | 82.9 | 1593.65 | 71.0 | 64.9 | 64.0 |
|
| 239 |
+
|
| 240 |
+
| VILA-1.5-13B | VQA-v2 | GQA | VizWiz | ScienceQA | TextVQA | POPE | MME | MMBench | MMBench-CN | SEED |
|
| 241 |
+
| ----------- |:-----------------:|:-----------------:|:-------:|:-----------------:|:-----------------:|:-------:|:-------:|:-----------------:|:-------------:|:-------:|
|
| 242 |
+
| FP16 | 82.8 | 64.3 | 62.6 | 80.1 | 65.0 | 86.3 | 1569.55 | 74.9 | 66.3 | 65.1 |
|
| 243 |
+
| AWQ-INT4 | 82.7 | 64.5 | 63.3 | 79.7 | 64.7 | 86.7 | 1531.35 | 74.7 | 66.7 | 65.1 |
|
| 244 |
+
|
| 245 |
+
|
| 246 |
+
| VILA-1.5-40B | VQA-v2 | GQA | VizWiz | ScienceQA | TextVQA | POPE | MME | MMBench | MMBench-CN | SEED |
|
| 247 |
+
| ----------- |:-----------------:|:-----------------:|:-------:|:-----------------:|:-----------------:|:-------:|:-------:|:-----------------:|:-------------:|:-------:|
|
| 248 |
+
| FP16 | 84.3 | 64.6 | 62.2 | 87.2 | 73.6 | 87.3 | 1726.82 | 82.4 | 80.2 | 69.1 |
|
| 249 |
+
| AWQ-INT4 | 84.1 | 64.4 | 61.3 | 86.7 | 73.2 | 88.2 | 1714.79 | 83.2 | 79.6 | 68.9 |
|
| 250 |
+
|
| 251 |
+
|
| 252 |
+
## Inference speed ( Token/sec )
|
| 253 |
+
|
| 254 |
+
| $~~~~~~$ | Precision | A100 | 4090 | Orin |
|
| 255 |
+
| ---------------------- | --------- | ----- | ----- | ---- |
|
| 256 |
+
| VILA1.5-3B | fp16 | 104.6 | 137.6 | 25.4 |
|
| 257 |
+
| VILA1.5-3B-AWQ | int4 | 182.8 | 215.5 | 42.5 |
|
| 258 |
+
| VILA1.5-3B-S2 | fp16 | 104.3 | 137.2 | 24.6 |
|
| 259 |
+
| VILA1.5-3B-S2-AWQ | int4 | 180.2 | 219.3 | 40.1 |
|
| 260 |
+
| Llama-3-VILA1.5-8B | fp16 | 74.9 | 57.4 | 10.2 |
|
| 261 |
+
| Llama-3-VILA1.5-8B-AWQ | int4 | 168.9 | 150.2 | 28.7 |
|
| 262 |
+
| VILA1.5-13B | fp16 | 50.9 | OOM | 6.1 |
|
| 263 |
+
| VILA1.5-13B-AWQ | int4 | 115.9 | 105.7 | 20.6 |
|
| 264 |
+
| VILA1.5-40B | fp16 | OOM | OOM | -- |
|
| 265 |
+
| VILA1.5-40B-AWQ | int4 | 57.0 | OOM | -- | -->
|
| 266 |
+
|
| 267 |
+
|
| 268 |
+
## Reference
|
| 269 |
+
|
| 270 |
+
If you find AWQ useful or relevant to your research, please kindly cite our paper:
|
| 271 |
+
|
| 272 |
+
```
|
| 273 |
+
@inproceedings{lin2023awq,
|
| 274 |
+
title={AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration},
|
| 275 |
+
author={Lin, Ji and Tang, Jiaming and Tang, Haotian and Yang, Shang and Chen, Wei-Ming and Wang, Wei-Chen and Xiao, Guangxuan and Dang, Xingyu and Gan, Chuang and Han, Song},
|
| 276 |
+
booktitle={MLSys},
|
| 277 |
+
year={2024}
|
| 278 |
+
}
|
| 279 |
+
```
|
| 280 |
+
|
| 281 |
+
## Related Projects
|
| 282 |
+
|
| 283 |
+
[SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models](https://github.com/mit-han-lab/smoothquant)
|
| 284 |
+
|
| 285 |
+
[GPTQ: Accurate Post-training Compression for Generative Pretrained Transformers](https://arxiv.org/abs/2210.17323)
|
| 286 |
+
|
| 287 |
+
[Vicuna and FastChat](https://github.com/lm-sys/FastChat#readme)
|
| 288 |
+
|
| 289 |
+
[LLaVA: Large Language and Vision Assistant](https://github.com/haotian-liu/LLaVA)
|
| 290 |
+
|
| 291 |
+
[VILA: On Pre-training for Visual Language Models](https://github.com/Efficient-Large-Model/VILA)
|
| 292 |
+
|
llm-awq/awq/__pycache__/entry.cpython-311.pyc
ADDED
|
Binary file (18.3 kB). View file
|
|
|
llm-awq/awq/entry.py
ADDED
|
@@ -0,0 +1,357 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from lm_eval import evaluator, tasks
|
| 2 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer, AutoConfig
|
| 3 |
+
import torch
|
| 4 |
+
import argparse
|
| 5 |
+
import os
|
| 6 |
+
import json
|
| 7 |
+
from accelerate import (
|
| 8 |
+
init_empty_weights,
|
| 9 |
+
infer_auto_device_map,
|
| 10 |
+
dispatch_model,
|
| 11 |
+
load_checkpoint_in_model,
|
| 12 |
+
)
|
| 13 |
+
from accelerate.utils.modeling import get_balanced_memory
|
| 14 |
+
from awq.utils.parallel import auto_parallel
|
| 15 |
+
from awq.quantize.pre_quant import run_awq, apply_awq
|
| 16 |
+
from awq.quantize.quantizer import (
|
| 17 |
+
pseudo_quantize_model_weight,
|
| 18 |
+
real_quantize_model_weight,
|
| 19 |
+
)
|
| 20 |
+
from awq.utils.lm_eval_adaptor import LMEvalAdaptor
|
| 21 |
+
from awq.utils.utils import simple_dispatch_model
|
| 22 |
+
from datasets import load_dataset
|
| 23 |
+
from torch import nn
|
| 24 |
+
import tqdm
|
| 25 |
+
|
| 26 |
+
parser = argparse.ArgumentParser()
|
| 27 |
+
parser.add_argument("--model_path", type=str, help="path of the hf model")
|
| 28 |
+
parser.add_argument("--dtype", type=str, default="float16", choices=["float16", "bfloat16"])
|
| 29 |
+
parser.add_argument("--batch_size", type=int, default=1, help="batch size")
|
| 30 |
+
parser.add_argument("--tasks", default=None, type=str)
|
| 31 |
+
parser.add_argument("--output_path", default=None, type=str)
|
| 32 |
+
parser.add_argument("--num_fewshot", type=int, default=0)
|
| 33 |
+
# model config
|
| 34 |
+
parser.add_argument("--parallel", action="store_true", help="enable model parallelism")
|
| 35 |
+
# max memory to offload larger models to CPU
|
| 36 |
+
parser.add_argument(
|
| 37 |
+
"--max_memory",
|
| 38 |
+
type=str,
|
| 39 |
+
nargs="*",
|
| 40 |
+
help="List of device_id:max_memory pairs to be parsed into a dictionary; "
|
| 41 |
+
+ "Example: 0:10GiB 1:10GiB cpu:30GiB; "
|
| 42 |
+
+ "mode details here: "
|
| 43 |
+
+ "https://huggingface.co/docs/accelerate/usage_guides/big_modeling",
|
| 44 |
+
)
|
| 45 |
+
parser.add_argument(
|
| 46 |
+
"--auto_parallel",
|
| 47 |
+
action="store_true",
|
| 48 |
+
help="automatically set parallel and batch_size",
|
| 49 |
+
)
|
| 50 |
+
# quantization config
|
| 51 |
+
parser.add_argument("--w_bit", type=int, default=None)
|
| 52 |
+
parser.add_argument("--q_group_size", type=int, default=-1)
|
| 53 |
+
parser.add_argument("--no_zero_point", action="store_true", help="disable zero_point")
|
| 54 |
+
parser.add_argument("--q_backend", type=str, default="fake", choices=["fake", "real"])
|
| 55 |
+
# save/load real quantized weights
|
| 56 |
+
parser.add_argument("--dump_quant", type=str, default=None, help="save quantized model")
|
| 57 |
+
parser.add_argument(
|
| 58 |
+
"--dump_fake", type=str, default=None, help="save fake-quantized model"
|
| 59 |
+
)
|
| 60 |
+
parser.add_argument("--load_quant", type=str, default=None, help="load quantized model")
|
| 61 |
+
# apply/save/load awq
|
| 62 |
+
parser.add_argument("--run_awq", action="store_true", help="perform awq search process")
|
| 63 |
+
parser.add_argument(
|
| 64 |
+
"--dump_awq", type=str, default=None, help="save the awq search results"
|
| 65 |
+
)
|
| 66 |
+
parser.add_argument(
|
| 67 |
+
"--load_awq", type=str, default=None, help="load the awq search results"
|
| 68 |
+
)
|
| 69 |
+
parser.add_argument(
|
| 70 |
+
"--vila-15",
|
| 71 |
+
action="store_true",
|
| 72 |
+
help="quantizing vila 1.5",
|
| 73 |
+
)
|
| 74 |
+
parser.add_argument(
|
| 75 |
+
"--vila-20",
|
| 76 |
+
action="store_true",
|
| 77 |
+
help="quantizing or smoothing vila 2.0 (NVILA)",
|
| 78 |
+
)
|
| 79 |
+
parser.add_argument(
|
| 80 |
+
"--smooth_scale",
|
| 81 |
+
action="store_true",
|
| 82 |
+
help="generate the act scale of visiontower",
|
| 83 |
+
)
|
| 84 |
+
parser.add_argument(
|
| 85 |
+
"--media_path",
|
| 86 |
+
type=str,
|
| 87 |
+
nargs="+",
|
| 88 |
+
help="The input video to get act scale for visiontower",
|
| 89 |
+
)
|
| 90 |
+
parser.add_argument(
|
| 91 |
+
"--act_scale_path",
|
| 92 |
+
type=str,
|
| 93 |
+
default=None,
|
| 94 |
+
help="Path to save act scale",
|
| 95 |
+
)
|
| 96 |
+
args = parser.parse_args()
|
| 97 |
+
assert (
|
| 98 |
+
args.act_scale_path is not None and len(args.media_path) > 0
|
| 99 |
+
) or not args.smooth_scale
|
| 100 |
+
vila_10_quant_mode = (
|
| 101 |
+
("llava" in args.model_path.lower() or "vila" in args.model_path.lower())
|
| 102 |
+
and not args.vila_15
|
| 103 |
+
and not args.vila_20
|
| 104 |
+
)
|
| 105 |
+
|
| 106 |
+
max_memory = [v.split(":") for v in (args.max_memory or [])]
|
| 107 |
+
max_memory = {(int(k) if k.isdigit() else k): v for k, v in max_memory}
|
| 108 |
+
|
| 109 |
+
if args.auto_parallel:
|
| 110 |
+
gpu_list = auto_parallel(args)
|
| 111 |
+
|
| 112 |
+
# get quantization config (apart from w_bit)
|
| 113 |
+
q_config = {
|
| 114 |
+
"zero_point": not args.no_zero_point, # by default True
|
| 115 |
+
"q_group_size": args.q_group_size, # whether to use group quantization
|
| 116 |
+
}
|
| 117 |
+
print("Quantization config:", q_config)
|
| 118 |
+
|
| 119 |
+
# build model and tokenizer
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
def build_model_and_enc(model_path, dtype):
|
| 123 |
+
torch_dtype = torch.float16 if dtype == "float16" else torch.bfloat16
|
| 124 |
+
if not os.path.exists(model_path): # look into ssd
|
| 125 |
+
raise FileNotFoundError(f"{model_path} not found!")
|
| 126 |
+
print(f"* Building model {model_path}")
|
| 127 |
+
|
| 128 |
+
# all hf model
|
| 129 |
+
if vila_10_quant_mode:
|
| 130 |
+
from llava.model.builder import load_pretrained_model
|
| 131 |
+
from llava.mm_utils import get_model_name_from_path
|
| 132 |
+
|
| 133 |
+
enc, model, image_processor, context_len = load_pretrained_model(
|
| 134 |
+
model_path=model_path,
|
| 135 |
+
model_base=None,
|
| 136 |
+
model_name=get_model_name_from_path(model_path),
|
| 137 |
+
device="cpu",
|
| 138 |
+
**{"use_cache": False},
|
| 139 |
+
)
|
| 140 |
+
else:
|
| 141 |
+
config = AutoConfig.from_pretrained(model_path, trust_remote_code=True)
|
| 142 |
+
# Note (Haotian): To avoid OOM after huggingface transformers 4.36.2
|
| 143 |
+
config.use_cache = False
|
| 144 |
+
if "mpt" in config.__class__.__name__.lower():
|
| 145 |
+
enc = AutoTokenizer.from_pretrained(
|
| 146 |
+
config.tokenizer_name, trust_remote_code=True
|
| 147 |
+
)
|
| 148 |
+
else:
|
| 149 |
+
enc = AutoTokenizer.from_pretrained(
|
| 150 |
+
model_path, use_fast=False, trust_remote_code=True
|
| 151 |
+
)
|
| 152 |
+
|
| 153 |
+
if args.load_quant: # directly load quantized weights
|
| 154 |
+
print("Loading pre-computed quantized weights...")
|
| 155 |
+
with init_empty_weights():
|
| 156 |
+
model = AutoModelForCausalLM.from_config(
|
| 157 |
+
config=config, torch_dtype=torch_dtype, trust_remote_code=True
|
| 158 |
+
)
|
| 159 |
+
real_quantize_model_weight(
|
| 160 |
+
model, w_bit=args.w_bit, q_config=q_config, init_only=True
|
| 161 |
+
)
|
| 162 |
+
|
| 163 |
+
model.tie_weights()
|
| 164 |
+
|
| 165 |
+
# Infer device map
|
| 166 |
+
kwargs = {"max_memory": max_memory} if len(max_memory) else {}
|
| 167 |
+
device_map = infer_auto_device_map(
|
| 168 |
+
model,
|
| 169 |
+
no_split_module_classes=[
|
| 170 |
+
"OPTDecoderLayer",
|
| 171 |
+
"LlamaDecoderLayer",
|
| 172 |
+
"BloomBlock",
|
| 173 |
+
"MPTBlock",
|
| 174 |
+
"DecoderLayer",
|
| 175 |
+
],
|
| 176 |
+
**kwargs,
|
| 177 |
+
)
|
| 178 |
+
# Load checkpoint in the model
|
| 179 |
+
load_checkpoint_in_model(
|
| 180 |
+
model,
|
| 181 |
+
checkpoint=args.load_quant,
|
| 182 |
+
device_map=device_map,
|
| 183 |
+
offload_state_dict=True,
|
| 184 |
+
)
|
| 185 |
+
# Dispatch model
|
| 186 |
+
model = simple_dispatch_model(model, device_map=device_map)
|
| 187 |
+
|
| 188 |
+
model.eval()
|
| 189 |
+
else: # fp16 to quantized
|
| 190 |
+
args.run_awq &= not args.load_awq # if load_awq, no need to run awq
|
| 191 |
+
# Init model on CPU:
|
| 192 |
+
kwargs = {"torch_dtype": torch_dtype, "low_cpu_mem_usage": True}
|
| 193 |
+
if not vila_10_quant_mode:
|
| 194 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 195 |
+
model_path, config=config, trust_remote_code=True, **kwargs
|
| 196 |
+
)
|
| 197 |
+
|
| 198 |
+
model.eval()
|
| 199 |
+
|
| 200 |
+
if args.run_awq:
|
| 201 |
+
assert args.dump_awq, "Please save the awq results with --dump_awq"
|
| 202 |
+
|
| 203 |
+
awq_results = run_awq(
|
| 204 |
+
model,
|
| 205 |
+
enc,
|
| 206 |
+
w_bit=args.w_bit,
|
| 207 |
+
q_config=q_config,
|
| 208 |
+
n_samples=128,
|
| 209 |
+
seqlen=512,
|
| 210 |
+
)
|
| 211 |
+
if args.dump_awq:
|
| 212 |
+
dirpath = os.path.dirname(args.dump_awq)
|
| 213 |
+
os.makedirs(dirpath, exist_ok=True)
|
| 214 |
+
|
| 215 |
+
torch.save(awq_results, args.dump_awq)
|
| 216 |
+
print("AWQ results saved at", args.dump_awq)
|
| 217 |
+
|
| 218 |
+
exit(0)
|
| 219 |
+
|
| 220 |
+
if args.load_awq:
|
| 221 |
+
print("Loading pre-computed AWQ results from", args.load_awq)
|
| 222 |
+
awq_results = torch.load(args.load_awq, map_location="cpu")
|
| 223 |
+
apply_awq(model, awq_results)
|
| 224 |
+
|
| 225 |
+
# weight quantization
|
| 226 |
+
if args.w_bit is not None:
|
| 227 |
+
if args.q_backend == "fake":
|
| 228 |
+
assert (
|
| 229 |
+
args.dump_quant is None
|
| 230 |
+
), "Need to use real quantization to dump quantized weights"
|
| 231 |
+
pseudo_quantize_model_weight(model, w_bit=args.w_bit, q_config=q_config)
|
| 232 |
+
if args.dump_fake:
|
| 233 |
+
model.save_pretrained(args.dump_fake)
|
| 234 |
+
print("Pseudo-quantized models saved at", args.dump_fake)
|
| 235 |
+
elif args.q_backend == "real": # real quantization
|
| 236 |
+
real_quantize_model_weight(model, w_bit=args.w_bit, q_config=q_config)
|
| 237 |
+
if args.dump_quant:
|
| 238 |
+
if not args.dump_quant.endswith("v2.pt"):
|
| 239 |
+
print("[Info] Auto-change the dump_quant file name to *v2.pt")
|
| 240 |
+
args.dump_quant = args.dump_quant.replace(".pt", "-v2.pt")
|
| 241 |
+
dirpath = os.path.dirname(args.dump_quant)
|
| 242 |
+
os.makedirs(dirpath, exist_ok=True)
|
| 243 |
+
|
| 244 |
+
print(f"Saving the quantized model at {args.dump_quant}...")
|
| 245 |
+
torch.save(model.cpu().state_dict(), args.dump_quant)
|
| 246 |
+
exit(0)
|
| 247 |
+
else:
|
| 248 |
+
raise NotImplementedError
|
| 249 |
+
|
| 250 |
+
# Move the model to GPU (as much as possible) for LM evaluation
|
| 251 |
+
kwargs = {
|
| 252 |
+
"max_memory": get_balanced_memory(
|
| 253 |
+
model, max_memory if len(max_memory) > 0 else None
|
| 254 |
+
)
|
| 255 |
+
}
|
| 256 |
+
device_map = infer_auto_device_map(
|
| 257 |
+
model,
|
| 258 |
+
# TODO: can we remove this?
|
| 259 |
+
no_split_module_classes=[
|
| 260 |
+
"OPTDecoderLayer",
|
| 261 |
+
"LlamaDecoderLayer",
|
| 262 |
+
"BloomBlock",
|
| 263 |
+
"MPTBlock",
|
| 264 |
+
"DecoderLayer",
|
| 265 |
+
],
|
| 266 |
+
**kwargs,
|
| 267 |
+
)
|
| 268 |
+
model = dispatch_model(model, device_map=device_map)
|
| 269 |
+
|
| 270 |
+
return model, enc
|
| 271 |
+
|
| 272 |
+
|
| 273 |
+
def main():
|
| 274 |
+
if args.output_path is not None and os.path.exists(args.output_path):
|
| 275 |
+
# print(f"Results {args.output_path} already generated. Exit.")
|
| 276 |
+
print(f"Results {args.output_path} already generated. Overwrite.")
|
| 277 |
+
# exit()
|
| 278 |
+
|
| 279 |
+
# a hack here to auto set model group
|
| 280 |
+
if args.smooth_scale and args.vila_20:
|
| 281 |
+
if os.path.exists(args.act_scale_path):
|
| 282 |
+
print(f"Found existing Smooth Scales {args.act_scale_path}, skip.")
|
| 283 |
+
else:
|
| 284 |
+
from awq.quantize import get_smooth_scale
|
| 285 |
+
|
| 286 |
+
act_scale = get_smooth_scale(args.model_path, args.media_path)
|
| 287 |
+
os.makedirs(os.path.dirname(args.act_scale_path), exist_ok=True)
|
| 288 |
+
torch.save(act_scale, args.act_scale_path)
|
| 289 |
+
print("Save act scales at " + str(args.act_scale_path))
|
| 290 |
+
args.model_path = args.model_path + "/llm"
|
| 291 |
+
if args.dump_awq is None and args.dump_quant is None:
|
| 292 |
+
exit()
|
| 293 |
+
|
| 294 |
+
if args.dump_awq and os.path.exists(args.dump_awq):
|
| 295 |
+
print(f"Found existing AWQ results {args.dump_awq}, exit.")
|
| 296 |
+
exit()
|
| 297 |
+
model, enc = build_model_and_enc(args.model_path, args.dtype)
|
| 298 |
+
|
| 299 |
+
if args.tasks is not None:
|
| 300 |
+
# https://github.com/IST-DASLab/gptq/blob/2d65066eeb06a5c9ff5184d8cebdf33662c67faf/llama.py#L206
|
| 301 |
+
if args.tasks == "wikitext":
|
| 302 |
+
testenc = load_dataset("wikitext", "wikitext-2-raw-v1", split="test")
|
| 303 |
+
testenc = enc("\n\n".join(testenc["text"]), return_tensors="pt")
|
| 304 |
+
model.seqlen = 2048
|
| 305 |
+
testenc = testenc.input_ids.to(model.device)
|
| 306 |
+
nsamples = testenc.numel() // model.seqlen
|
| 307 |
+
model = model.eval()
|
| 308 |
+
nlls = []
|
| 309 |
+
for i in tqdm.tqdm(range(nsamples), desc="evaluating..."):
|
| 310 |
+
batch = testenc[:, (i * model.seqlen) : ((i + 1) * model.seqlen)].to(
|
| 311 |
+
model.device
|
| 312 |
+
)
|
| 313 |
+
with torch.no_grad():
|
| 314 |
+
lm_logits = model(batch).logits
|
| 315 |
+
shift_logits = lm_logits[:, :-1, :].contiguous().float()
|
| 316 |
+
shift_labels = testenc[
|
| 317 |
+
:, (i * model.seqlen) : ((i + 1) * model.seqlen)
|
| 318 |
+
][:, 1:]
|
| 319 |
+
loss_fct = nn.CrossEntropyLoss()
|
| 320 |
+
loss = loss_fct(
|
| 321 |
+
shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1)
|
| 322 |
+
)
|
| 323 |
+
neg_log_likelihood = loss.float() * model.seqlen
|
| 324 |
+
nlls.append(neg_log_likelihood)
|
| 325 |
+
|
| 326 |
+
ppl = torch.exp(torch.stack(nlls).sum() / (nsamples * model.seqlen))
|
| 327 |
+
print(ppl.item())
|
| 328 |
+
|
| 329 |
+
results = {"ppl": ppl.item()}
|
| 330 |
+
if args.output_path is not None:
|
| 331 |
+
os.makedirs(os.path.dirname(args.output_path), exist_ok=True)
|
| 332 |
+
with open(args.output_path, "w") as f:
|
| 333 |
+
json.dump(results, f, indent=2)
|
| 334 |
+
else:
|
| 335 |
+
task_names = args.tasks.split(",")
|
| 336 |
+
|
| 337 |
+
lm_eval_model = LMEvalAdaptor(args.model_path, model, enc, args.batch_size)
|
| 338 |
+
results = evaluator.simple_evaluate(
|
| 339 |
+
model=lm_eval_model,
|
| 340 |
+
tasks=task_names,
|
| 341 |
+
batch_size=args.batch_size,
|
| 342 |
+
no_cache=True,
|
| 343 |
+
num_fewshot=args.num_fewshot,
|
| 344 |
+
)
|
| 345 |
+
|
| 346 |
+
print(evaluator.make_table(results))
|
| 347 |
+
|
| 348 |
+
if args.output_path is not None:
|
| 349 |
+
os.makedirs(os.path.dirname(args.output_path), exist_ok=True)
|
| 350 |
+
# otherwise cannot save
|
| 351 |
+
results["config"]["model"] = args.model_path
|
| 352 |
+
with open(args.output_path, "w") as f:
|
| 353 |
+
json.dump(results, f, indent=2)
|
| 354 |
+
|
| 355 |
+
|
| 356 |
+
if __name__ == "__main__":
|
| 357 |
+
main()
|
llm-awq/awq/kernels/csrc/attention/README.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Attention kernel from FasterTransformer
|
| 2 |
+
|
| 3 |
+
This CUDA extension wraps the single-query attention [kernel](https://github.com/NVIDIA/FasterTransformer/blob/release/v5.2.1_tag/src/fastertransformer/kernels/decoder_masked_multihead_attention/decoder_masked_multihead_attention_template.hpp) from
|
| 4 |
+
FasterTransformer v5.2.1 for benchmarking purpose.
|
| 5 |
+
|
| 6 |
+
```sh
|
| 7 |
+
cd csrc/ft_attention && pip install .
|
| 8 |
+
```
|
llm-awq/awq/kernels/csrc/attention/cuda_bf16_fallbacks.cuh
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Downloaded from from FasterTransformer v5.2.1
|
| 2 |
+
// https://github.com/NVIDIA/FasterTransformer/blob/release/v5.2.1_tag/src/fastertransformer/utils/cuda_bf16_fallbacks.cuh
|
| 3 |
+
/*
|
| 4 |
+
* Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved.
|
| 5 |
+
*
|
| 6 |
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
| 7 |
+
* you may not use this file except in compliance with the License.
|
| 8 |
+
* You may obtain a copy of the License at
|
| 9 |
+
*
|
| 10 |
+
* http://www.apache.org/licenses/LICENSE-2.0
|
| 11 |
+
*
|
| 12 |
+
* Unless required by applicable law or agreed to in writing, software
|
| 13 |
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
| 14 |
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 15 |
+
* See the License for the specific language governing permissions and
|
| 16 |
+
* limitations under the License.
|
| 17 |
+
*/
|
| 18 |
+
|
| 19 |
+
#pragma once
|
| 20 |
+
|
| 21 |
+
#include "cuda_bf16_wrapper.h"
|
| 22 |
+
#include <cuda_fp16.h>
|
| 23 |
+
|
| 24 |
+
namespace fastertransformer {
|
| 25 |
+
|
| 26 |
+
#ifdef ENABLE_BF16
|
| 27 |
+
inline __device__ float2 bf1622float2(const __nv_bfloat162 val) {
|
| 28 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
|
| 29 |
+
float2 f_val;
|
| 30 |
+
f_val.x = __low2float(val);
|
| 31 |
+
f_val.y = __high2float(val);
|
| 32 |
+
return f_val;
|
| 33 |
+
#else
|
| 34 |
+
return __bfloat1622float2(val);
|
| 35 |
+
#endif
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
inline __device__ int16_t bf1622int16(__nv_bfloat162 val) {
|
| 39 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
|
| 40 |
+
float2 f_val;
|
| 41 |
+
f_val.x = max(min(__low2float(val), 127.f), -128.f);
|
| 42 |
+
f_val.y = max(min(__high2float(val), 127.f), -128.f);
|
| 43 |
+
union { int8_t int8[2]; int16_t int16; };
|
| 44 |
+
int8[0] = static_cast<int8_t>(static_cast<short>(f_val.x));
|
| 45 |
+
int8[1] = static_cast<int8_t>(static_cast<short>(f_val.y));
|
| 46 |
+
return int16;
|
| 47 |
+
#else
|
| 48 |
+
val = __hmin2(val, make_bfloat162(127., 127.));
|
| 49 |
+
val = __hmax2(val, make_bfloat162(-128., -128.));
|
| 50 |
+
union { int8_t int8[2]; int16_t int16; };
|
| 51 |
+
int8[0] = static_cast<int8_t>(static_cast<short>(val.x));
|
| 52 |
+
int8[1] = static_cast<int8_t>(static_cast<short>(val.y));
|
| 53 |
+
return int16;
|
| 54 |
+
#endif
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
inline __device__ __nv_bfloat162 float22bf162(const float2 val) {
|
| 58 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
|
| 59 |
+
return __floats2bfloat162_rn(val.x, val.y);
|
| 60 |
+
#else
|
| 61 |
+
return __float22bfloat162_rn(val);
|
| 62 |
+
#endif
|
| 63 |
+
}
|
| 64 |
+
|
| 65 |
+
inline __device__ __nv_bfloat162 bf162bf162(const __nv_bfloat16 val) {
|
| 66 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
|
| 67 |
+
__nv_bfloat162 val2;
|
| 68 |
+
val2.x = val;
|
| 69 |
+
val2.y = val;
|
| 70 |
+
return val2;
|
| 71 |
+
#else
|
| 72 |
+
return __bfloat162bfloat162(val);
|
| 73 |
+
#endif
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
inline __device__ __nv_bfloat162 bf16hadd2(const __nv_bfloat162 x, const __nv_bfloat162 y) {
|
| 77 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
|
| 78 |
+
float fxl, fxh, fyl, fyh;
|
| 79 |
+
fxl = __low2float(x);
|
| 80 |
+
fxh = __high2float(x);
|
| 81 |
+
fyl = __low2float(y);
|
| 82 |
+
fyh = __high2float(y);
|
| 83 |
+
return __floats2bfloat162_rn(fxl + fyl, fxh + fyh);
|
| 84 |
+
#else
|
| 85 |
+
return __hadd2(x, y);
|
| 86 |
+
#endif
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
inline __device__ __nv_bfloat16 bf16hadd(const __nv_bfloat16 x, const __nv_bfloat16 y) {
|
| 90 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
|
| 91 |
+
return __float2bfloat16( __bfloat162float(x) + __bfloat162float(y) );
|
| 92 |
+
#else
|
| 93 |
+
return __hadd(x, y);
|
| 94 |
+
#endif
|
| 95 |
+
}
|
| 96 |
+
|
| 97 |
+
inline __device__ __nv_bfloat162 bf16hsub2(const __nv_bfloat162 x, const __nv_bfloat162 y) {
|
| 98 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
|
| 99 |
+
float fxl, fxh, fyl, fyh;
|
| 100 |
+
fxl = __low2float(x);
|
| 101 |
+
fxh = __high2float(x);
|
| 102 |
+
fyl = __low2float(y);
|
| 103 |
+
fyh = __high2float(y);
|
| 104 |
+
return __floats2bfloat162_rn(fxl - fyl, fxh - fyh);
|
| 105 |
+
#else
|
| 106 |
+
return __hsub2(x, y);
|
| 107 |
+
#endif
|
| 108 |
+
}
|
| 109 |
+
|
| 110 |
+
inline __device__ __nv_bfloat16 bf16hsub(const __nv_bfloat16 x, const __nv_bfloat16 y) {
|
| 111 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
|
| 112 |
+
return __float2bfloat16( __bfloat162float(x) - __bfloat162float(y) );
|
| 113 |
+
#else
|
| 114 |
+
return __hsub(x, y);
|
| 115 |
+
#endif
|
| 116 |
+
}
|
| 117 |
+
|
| 118 |
+
inline __device__ __nv_bfloat162 bf16hmul2(const __nv_bfloat162 x, const __nv_bfloat162 y) {
|
| 119 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
|
| 120 |
+
float fxl, fxh, fyl, fyh;
|
| 121 |
+
fxl = __low2float(x);
|
| 122 |
+
fxh = __high2float(x);
|
| 123 |
+
fyl = __low2float(y);
|
| 124 |
+
fyh = __high2float(y);
|
| 125 |
+
return __floats2bfloat162_rn(fxl * fyl, fxh * fyh);
|
| 126 |
+
#else
|
| 127 |
+
return __hmul2(x, y);
|
| 128 |
+
#endif
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
inline __device__ __nv_bfloat16 bf16hmul(const __nv_bfloat16 x, const __nv_bfloat16 y) {
|
| 132 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
|
| 133 |
+
return __float2bfloat16( __bfloat162float(x) * __bfloat162float(y) );
|
| 134 |
+
#else
|
| 135 |
+
return __hmul(x, y);
|
| 136 |
+
#endif
|
| 137 |
+
}
|
| 138 |
+
|
| 139 |
+
inline __device__ __nv_bfloat162 bf16hfma2(const __nv_bfloat162 x, const __nv_bfloat162 y, const __nv_bfloat162 z) {
|
| 140 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
|
| 141 |
+
float fxl, fxh, fyl, fyh, fzl, fzh;
|
| 142 |
+
fxl = __low2float(x);
|
| 143 |
+
fxh = __high2float(x);
|
| 144 |
+
fyl = __low2float(y);
|
| 145 |
+
fyh = __high2float(y);
|
| 146 |
+
fzl = __low2float(z);
|
| 147 |
+
fzh = __high2float(z);
|
| 148 |
+
return __floats2bfloat162_rn(fxl * fyl + fzl, fxh * fyh + fzh);
|
| 149 |
+
#else
|
| 150 |
+
return __hfma2(x, y, z);
|
| 151 |
+
#endif
|
| 152 |
+
}
|
| 153 |
+
|
| 154 |
+
inline __device__ __nv_bfloat16 bf16hfma(const __nv_bfloat16 x, const __nv_bfloat16 y, const __nv_bfloat16 z) {
|
| 155 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
|
| 156 |
+
return __float2bfloat16( __bfloat162float(x) * __bfloat162float(y) + __bfloat162float(z));
|
| 157 |
+
#else
|
| 158 |
+
return __hfma(x, y, z);
|
| 159 |
+
#endif
|
| 160 |
+
}
|
| 161 |
+
|
| 162 |
+
inline __device__ __nv_bfloat162 bf16exp2(const __nv_bfloat162 x) {
|
| 163 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
|
| 164 |
+
float fxl, fxh;
|
| 165 |
+
fxl = __low2float(x);
|
| 166 |
+
fxh = __high2float(x);;
|
| 167 |
+
return __floats2bfloat162_rn(expf(fxl), expf(fxh));
|
| 168 |
+
#else
|
| 169 |
+
return h2exp(x);
|
| 170 |
+
#endif
|
| 171 |
+
}
|
| 172 |
+
|
| 173 |
+
#if defined(__CUDA_ARCH__) && (__CUDA_ARCH__ < 800)
|
| 174 |
+
inline __device__ __nv_bfloat162 operator*(const __nv_bfloat162 x, const __nv_bfloat162 y) { return bf16hmul2(x, y); };
|
| 175 |
+
inline __device__ __nv_bfloat162 operator+(const __nv_bfloat162 x, const __nv_bfloat162 y) { return bf16hadd2(x, y); };
|
| 176 |
+
|
| 177 |
+
inline __device__ __nv_bfloat162 make_bfloat162(const __nv_bfloat16 x, const __nv_bfloat16 y)
|
| 178 |
+
{
|
| 179 |
+
__nv_bfloat162 t; t.x = x; t.y = y; return t;
|
| 180 |
+
}
|
| 181 |
+
|
| 182 |
+
#endif
|
| 183 |
+
|
| 184 |
+
inline __device__ __nv_bfloat16 bf16hadd(__nv_bfloat16 a, __nv_bfloat16 b, __nv_bfloat16 c) {
|
| 185 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
|
| 186 |
+
return __float2bfloat16(__bfloat162float(a) + __bfloat162float(b) + __bfloat162float(c));
|
| 187 |
+
#else
|
| 188 |
+
return a + b + c;
|
| 189 |
+
#endif
|
| 190 |
+
}
|
| 191 |
+
|
| 192 |
+
inline __device__ __nv_bfloat16 bf16hadd(__nv_bfloat16 a, __nv_bfloat16 b, __nv_bfloat16 c, __nv_bfloat16 d) {
|
| 193 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
|
| 194 |
+
return __float2bfloat16(__bfloat162float(a) + __bfloat162float(b) + __bfloat162float(c) + __bfloat162float(d));
|
| 195 |
+
#else
|
| 196 |
+
return (__nv_bfloat16)((float)a + (float)b + (float)c + (float)d);
|
| 197 |
+
#endif
|
| 198 |
+
}
|
| 199 |
+
|
| 200 |
+
inline __device__ __nv_bfloat162 bf16hadd2(__nv_bfloat162 a, __nv_bfloat162 b, __nv_bfloat162 c) {
|
| 201 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
|
| 202 |
+
float fal, fah, fbl, fbh, fcl, fch;
|
| 203 |
+
fal = __low2float(a);
|
| 204 |
+
fah = __high2float(a);
|
| 205 |
+
fbl = __low2float(b);
|
| 206 |
+
fbh = __high2float(b);
|
| 207 |
+
fcl = __low2float(c);
|
| 208 |
+
fch = __high2float(c);
|
| 209 |
+
return __floats2bfloat162_rn(fal + fbl + fcl, fah + fbh + fch);
|
| 210 |
+
#else
|
| 211 |
+
return a + b + c;
|
| 212 |
+
#endif
|
| 213 |
+
}
|
| 214 |
+
|
| 215 |
+
inline __device__ __nv_bfloat16 bf16hmul(__nv_bfloat16 a, __nv_bfloat16 b, __nv_bfloat16 c) {
|
| 216 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
|
| 217 |
+
return __float2bfloat16(__bfloat162float(a) * __bfloat162float(b) * __bfloat162float(c));
|
| 218 |
+
#else
|
| 219 |
+
return a * b * c;
|
| 220 |
+
#endif
|
| 221 |
+
}
|
| 222 |
+
|
| 223 |
+
inline __device__ __nv_bfloat162 bf16hmul2(__nv_bfloat162 a, __nv_bfloat162 b, __nv_bfloat162 c) {
|
| 224 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
|
| 225 |
+
float fal, fah, fbl, fbh, fcl, fch;
|
| 226 |
+
fal = __low2float(a);
|
| 227 |
+
fah = __high2float(a);
|
| 228 |
+
fbl = __low2float(b);
|
| 229 |
+
fbh = __high2float(b);
|
| 230 |
+
fcl = __low2float(c);
|
| 231 |
+
fch = __high2float(c);
|
| 232 |
+
return __floats2bfloat162_rn(fal * fbl * fcl, fah * fbh * fch);
|
| 233 |
+
#else
|
| 234 |
+
return a * b * c;
|
| 235 |
+
#endif
|
| 236 |
+
}
|
| 237 |
+
|
| 238 |
+
inline __device__ __nv_bfloat162 bf16hfma2(__nv_bfloat162 a, __nv_bfloat162 b, __nv_bfloat162 c, __nv_bfloat162 d) {
|
| 239 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
|
| 240 |
+
float fal, fah, fbl, fbh, fcl, fch, fdl, fdh;
|
| 241 |
+
fal = __low2float(a);
|
| 242 |
+
fah = __high2float(a);
|
| 243 |
+
fbl = __low2float(b);
|
| 244 |
+
fbh = __high2float(b);
|
| 245 |
+
fcl = __low2float(c);
|
| 246 |
+
fch = __high2float(c);
|
| 247 |
+
fdl = __low2float(d);
|
| 248 |
+
fdh = __high2float(d);
|
| 249 |
+
return __floats2bfloat162_rn(fal * fbl * fcl + fdl, fah * fbh * fch + fdh);
|
| 250 |
+
#else
|
| 251 |
+
return a * b * c + d;
|
| 252 |
+
#endif
|
| 253 |
+
}
|
| 254 |
+
|
| 255 |
+
#endif // ENABLE_BF16
|
| 256 |
+
|
| 257 |
+
} // namespace fastertransformer
|
llm-awq/awq/kernels/csrc/attention/cuda_bf16_wrapper.h
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Downloaded from from FasterTransformer v5.2.1
|
| 2 |
+
// https://github.com/NVIDIA/FasterTransformer/blob/release/v5.2.1_tag/src/fastertransformer/utils/cuda_bf16_wrapper.h
|
| 3 |
+
/*
|
| 4 |
+
* Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved.
|
| 5 |
+
*
|
| 6 |
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
| 7 |
+
* you may not use this file except in compliance with the License.
|
| 8 |
+
* You may obtain a copy of the License at
|
| 9 |
+
*
|
| 10 |
+
* http://www.apache.org/licenses/LICENSE-2.0
|
| 11 |
+
*
|
| 12 |
+
* Unless required by applicable law or agreed to in writing, software
|
| 13 |
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
| 14 |
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 15 |
+
* See the License for the specific language governing permissions and
|
| 16 |
+
* limitations under the License.
|
| 17 |
+
*/
|
| 18 |
+
|
| 19 |
+
#pragma once
|
| 20 |
+
|
| 21 |
+
#ifdef ENABLE_BF16
|
| 22 |
+
#include <cuda_bf16.h>
|
| 23 |
+
#endif
|
llm-awq/awq/kernels/csrc/attention/decoder_masked_multihead_attention.cu
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Adapted from from FasterTransformer v5.2.1
|
| 2 |
+
// https://github.com/NVIDIA/FasterTransformer/blob/release/v5.2.1_tag/src/fastertransformer/kernels/decoder_masked_multihead_attention/decoder_masked_multihead_attention_128.cu
|
| 3 |
+
/*
|
| 4 |
+
* Copyright (c) 2020-2022, NVIDIA CORPORATION. All rights reserved.
|
| 5 |
+
*
|
| 6 |
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
| 7 |
+
* you may not use this file except in compliance with the License.
|
| 8 |
+
* You may obtain a copy of the License at
|
| 9 |
+
*
|
| 10 |
+
* http://www.apache.org/licenses/LICENSE-2.0
|
| 11 |
+
*
|
| 12 |
+
* Unless required by applicable law or agreed to in writing, software
|
| 13 |
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
| 14 |
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 15 |
+
* See the License for the specific language governing permissions and
|
| 16 |
+
* limitations under the License.
|
| 17 |
+
*/
|
| 18 |
+
|
| 19 |
+
#include "decoder_masked_multihead_attention.h"
|
| 20 |
+
#include "decoder_masked_multihead_attention_utils.h"
|
| 21 |
+
#include "cuda_bf16_wrapper.h"
|
| 22 |
+
#include <assert.h>
|
| 23 |
+
#include <float.h>
|
| 24 |
+
#include <type_traits>
|
| 25 |
+
|
| 26 |
+
#include "decoder_masked_multihead_attention_template.hpp"
|
| 27 |
+
|
| 28 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 29 |
+
|
| 30 |
+
#define MMHA_LAUNCH_KERNEL(T, Dh, Dh_MAX, THDS_PER_KEY, THDS_PER_VALUE, THDS_PER_BLOCK, DO_CROSS_ATTENTION, stream) \
|
| 31 |
+
size_t smem_sz = mmha::smem_size_in_bytes<T, DO_CROSS_ATTENTION>(params, THDS_PER_VALUE, THDS_PER_BLOCK); \
|
| 32 |
+
auto kernel = mmha::masked_multihead_attention_kernel<T, Dh, Dh_MAX, THDS_PER_KEY, THDS_PER_VALUE, \
|
| 33 |
+
THDS_PER_BLOCK, DO_CROSS_ATTENTION>; \
|
| 34 |
+
if (smem_sz >= 48 * 1024) { \
|
| 35 |
+
cudaFuncSetAttribute(kernel, cudaFuncAttributeMaxDynamicSharedMemorySize, smem_sz); \
|
| 36 |
+
} \
|
| 37 |
+
dim3 grid(params.num_heads, params.batch_size); \
|
| 38 |
+
kernel<<<grid, THDS_PER_BLOCK, smem_sz, stream>>>(params)
|
| 39 |
+
|
| 40 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 41 |
+
|
| 42 |
+
// !!! Specialize the launcher for Cross attention
|
| 43 |
+
template<typename T, int Dh, int Dh_MAX, typename KERNEL_PARAMS_TYPE>
|
| 44 |
+
void mmha_launch_kernel(const KERNEL_PARAMS_TYPE& params, const cudaStream_t& stream)
|
| 45 |
+
{
|
| 46 |
+
constexpr int THREADS_PER_VALUE = Dh_MAX * sizeof(T) / 16;
|
| 47 |
+
constexpr bool DO_CROSS_ATTENTION = std::is_same<KERNEL_PARAMS_TYPE, Cross_multihead_attention_params<T>>::value;
|
| 48 |
+
int tlength = (DO_CROSS_ATTENTION) ? params.memory_max_len : params.timestep;
|
| 49 |
+
// printf("tlength, CROSS_ATTENTION = %d, %d\n", tlength, DO_CROSS_ATTENTION);
|
| 50 |
+
if (tlength < 32) {
|
| 51 |
+
MMHA_LAUNCH_KERNEL(T, Dh, Dh_MAX, 4, THREADS_PER_VALUE, 64, DO_CROSS_ATTENTION, stream);
|
| 52 |
+
}
|
| 53 |
+
else if (tlength < 2048) {
|
| 54 |
+
MMHA_LAUNCH_KERNEL(T, Dh, Dh_MAX, 2, THREADS_PER_VALUE, 128, DO_CROSS_ATTENTION, stream);
|
| 55 |
+
}
|
| 56 |
+
else {
|
| 57 |
+
MMHA_LAUNCH_KERNEL(T, Dh, Dh_MAX, 1, THREADS_PER_VALUE, 256, DO_CROSS_ATTENTION, stream);
|
| 58 |
+
}
|
| 59 |
+
}
|
| 60 |
+
|
| 61 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 62 |
+
|
| 63 |
+
#undef MMHA_LAUNCH_KERNEL
|
| 64 |
+
|
| 65 |
+
template<typename T, typename KERNEL_PARAMS_TYPE>
|
| 66 |
+
void multihead_attention_(const KERNEL_PARAMS_TYPE& params, const cudaStream_t& stream)
|
| 67 |
+
{
|
| 68 |
+
switch (params.hidden_size_per_head) {
|
| 69 |
+
case 32:
|
| 70 |
+
mmha_launch_kernel<T, 32, 32, KERNEL_PARAMS_TYPE>(params, stream);
|
| 71 |
+
break;
|
| 72 |
+
case 48:
|
| 73 |
+
mmha_launch_kernel<T, 48, 64, KERNEL_PARAMS_TYPE>(params, stream);
|
| 74 |
+
break;
|
| 75 |
+
case 64:
|
| 76 |
+
mmha_launch_kernel<T, 64, 64, KERNEL_PARAMS_TYPE>(params, stream);
|
| 77 |
+
break;
|
| 78 |
+
case 80:
|
| 79 |
+
mmha_launch_kernel<T, 80, 128, KERNEL_PARAMS_TYPE>(params, stream);
|
| 80 |
+
break;
|
| 81 |
+
case 96:
|
| 82 |
+
mmha_launch_kernel<T, 96, 128, KERNEL_PARAMS_TYPE>(params, stream);
|
| 83 |
+
break;
|
| 84 |
+
case 112:
|
| 85 |
+
mmha_launch_kernel<T, 112, 128, KERNEL_PARAMS_TYPE>(params, stream);
|
| 86 |
+
break;
|
| 87 |
+
case 128:
|
| 88 |
+
mmha_launch_kernel<T, 128, 128, KERNEL_PARAMS_TYPE>(params, stream);
|
| 89 |
+
break;
|
| 90 |
+
case 160:
|
| 91 |
+
mmha_launch_kernel<T, 160, 256, KERNEL_PARAMS_TYPE>(params, stream);
|
| 92 |
+
break;
|
| 93 |
+
case 192:
|
| 94 |
+
mmha_launch_kernel<T, 192, 256, KERNEL_PARAMS_TYPE>(params, stream);
|
| 95 |
+
break;
|
| 96 |
+
case 224:
|
| 97 |
+
mmha_launch_kernel<T, 224, 256, KERNEL_PARAMS_TYPE>(params, stream);
|
| 98 |
+
break;
|
| 99 |
+
case 256:
|
| 100 |
+
mmha_launch_kernel<T, 256, 256, KERNEL_PARAMS_TYPE>(params, stream);
|
| 101 |
+
break;
|
| 102 |
+
default:
|
| 103 |
+
assert(false);
|
| 104 |
+
}
|
| 105 |
+
}
|
| 106 |
+
|
| 107 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 108 |
+
|
| 109 |
+
void masked_multihead_attention(const Masked_multihead_attention_params<float>& params, const cudaStream_t& stream)
|
| 110 |
+
{
|
| 111 |
+
multihead_attention_<float, Masked_multihead_attention_params<float>>(params, stream);
|
| 112 |
+
}
|
| 113 |
+
|
| 114 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 115 |
+
|
| 116 |
+
void masked_multihead_attention(const Masked_multihead_attention_params<uint16_t>& params, const cudaStream_t& stream)
|
| 117 |
+
{
|
| 118 |
+
multihead_attention_<uint16_t, Masked_multihead_attention_params<uint16_t>>(params, stream);
|
| 119 |
+
}
|
| 120 |
+
|
| 121 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 122 |
+
|
| 123 |
+
#ifdef ENABLE_BF16
|
| 124 |
+
void masked_multihead_attention(const Masked_multihead_attention_params<__nv_bfloat16>& params,
|
| 125 |
+
const cudaStream_t& stream)
|
| 126 |
+
{
|
| 127 |
+
multihead_attention_<__nv_bfloat16, Masked_multihead_attention_params<__nv_bfloat16>>(params, stream);
|
| 128 |
+
}
|
| 129 |
+
#endif
|
| 130 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 131 |
+
|
| 132 |
+
void cross_multihead_attention(const Cross_multihead_attention_params<float>& params, const cudaStream_t& stream)
|
| 133 |
+
{
|
| 134 |
+
multihead_attention_<float, Cross_multihead_attention_params<float>>(params, stream);
|
| 135 |
+
}
|
| 136 |
+
|
| 137 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 138 |
+
|
| 139 |
+
void cross_multihead_attention(const Cross_multihead_attention_params<uint16_t>& params, const cudaStream_t& stream)
|
| 140 |
+
{
|
| 141 |
+
multihead_attention_<uint16_t, Cross_multihead_attention_params<uint16_t>>(params, stream);
|
| 142 |
+
}
|
| 143 |
+
|
| 144 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 145 |
+
|
| 146 |
+
#ifdef ENABLE_BF16
|
| 147 |
+
void cross_multihead_attention(const Cross_multihead_attention_params<__nv_bfloat16>& params,
|
| 148 |
+
const cudaStream_t& stream)
|
| 149 |
+
{
|
| 150 |
+
multihead_attention_<__nv_bfloat16, Cross_multihead_attention_params<__nv_bfloat16>>(params, stream);
|
| 151 |
+
}
|
| 152 |
+
#endif
|
| 153 |
+
|
| 154 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
llm-awq/awq/kernels/csrc/attention/decoder_masked_multihead_attention_utils.h
ADDED
|
@@ -0,0 +1,1795 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Downloaded from from FasterTransformer v5.2.1
|
| 2 |
+
// https://github.com/NVIDIA/FasterTransformer/blob/release/v5.2.1_tag/src/fastertransformer/kernels/decoder_masked_multihead_attention_utils.h
|
| 3 |
+
/*
|
| 4 |
+
* Copyright (c) 2020-2022, NVIDIA CORPORATION. All rights reserved.
|
| 5 |
+
*
|
| 6 |
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
| 7 |
+
* you may not use this file except in compliance with the License.
|
| 8 |
+
* You may obtain a copy of the License at
|
| 9 |
+
*
|
| 10 |
+
* http://www.apache.org/licenses/LICENSE-2.0
|
| 11 |
+
*
|
| 12 |
+
* Unless required by applicable law or agreed to in writing, software
|
| 13 |
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
| 14 |
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 15 |
+
* See the License for the specific language governing permissions and
|
| 16 |
+
* limitations under the License.
|
| 17 |
+
*/
|
| 18 |
+
|
| 19 |
+
#pragma once
|
| 20 |
+
|
| 21 |
+
#include "cuda_bf16_wrapper.h"
|
| 22 |
+
#include "cuda_bf16_fallbacks.cuh"
|
| 23 |
+
#include <stdint.h>
|
| 24 |
+
|
| 25 |
+
using namespace fastertransformer;
|
| 26 |
+
|
| 27 |
+
namespace mmha {
|
| 28 |
+
|
| 29 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 30 |
+
|
| 31 |
+
struct Float8_ {
|
| 32 |
+
float2 x;
|
| 33 |
+
float2 y;
|
| 34 |
+
float2 z;
|
| 35 |
+
float2 w;
|
| 36 |
+
};
|
| 37 |
+
|
| 38 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 39 |
+
|
| 40 |
+
struct Float4_ {
|
| 41 |
+
float2 x;
|
| 42 |
+
float2 y;
|
| 43 |
+
};
|
| 44 |
+
|
| 45 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 46 |
+
|
| 47 |
+
#ifdef ENABLE_BF16
|
| 48 |
+
struct bf16_4_t {
|
| 49 |
+
__nv_bfloat162 x;
|
| 50 |
+
__nv_bfloat162 y;
|
| 51 |
+
};
|
| 52 |
+
|
| 53 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 54 |
+
|
| 55 |
+
struct bf16_8_t {
|
| 56 |
+
__nv_bfloat162 x;
|
| 57 |
+
__nv_bfloat162 y;
|
| 58 |
+
__nv_bfloat162 z;
|
| 59 |
+
__nv_bfloat162 w;
|
| 60 |
+
};
|
| 61 |
+
#endif
|
| 62 |
+
|
| 63 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 64 |
+
|
| 65 |
+
template<typename T>
|
| 66 |
+
struct num_elems;
|
| 67 |
+
template<>
|
| 68 |
+
struct num_elems<float> {
|
| 69 |
+
static constexpr int value = 1;
|
| 70 |
+
};
|
| 71 |
+
template<>
|
| 72 |
+
struct num_elems<float2> {
|
| 73 |
+
static constexpr int value = 2;
|
| 74 |
+
};
|
| 75 |
+
template<>
|
| 76 |
+
struct num_elems<float4> {
|
| 77 |
+
static constexpr int value = 4;
|
| 78 |
+
};
|
| 79 |
+
template<>
|
| 80 |
+
struct num_elems<Float4_> {
|
| 81 |
+
static constexpr int value = 4;
|
| 82 |
+
};
|
| 83 |
+
template<>
|
| 84 |
+
struct num_elems<Float8_> {
|
| 85 |
+
static constexpr int value = 8;
|
| 86 |
+
};
|
| 87 |
+
|
| 88 |
+
template<>
|
| 89 |
+
struct num_elems<uint32_t> {
|
| 90 |
+
static constexpr int value = 2;
|
| 91 |
+
};
|
| 92 |
+
template<>
|
| 93 |
+
struct num_elems<uint2> {
|
| 94 |
+
static constexpr int value = 4;
|
| 95 |
+
};
|
| 96 |
+
template<>
|
| 97 |
+
struct num_elems<uint4> {
|
| 98 |
+
static constexpr int value = 8;
|
| 99 |
+
};
|
| 100 |
+
|
| 101 |
+
#ifdef ENABLE_BF16
|
| 102 |
+
template<>
|
| 103 |
+
struct num_elems<__nv_bfloat162> {
|
| 104 |
+
static constexpr int value = 2;
|
| 105 |
+
};
|
| 106 |
+
template<>
|
| 107 |
+
struct num_elems<bf16_4_t> {
|
| 108 |
+
static constexpr int value = 4;
|
| 109 |
+
};
|
| 110 |
+
template<>
|
| 111 |
+
struct num_elems<bf16_8_t> {
|
| 112 |
+
static constexpr int value = 8;
|
| 113 |
+
};
|
| 114 |
+
#endif
|
| 115 |
+
|
| 116 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 117 |
+
|
| 118 |
+
template<typename T, int N>
|
| 119 |
+
struct packed_type;
|
| 120 |
+
template<typename T>
|
| 121 |
+
struct packed_type<T, 1> {
|
| 122 |
+
using type = T;
|
| 123 |
+
};
|
| 124 |
+
template<>
|
| 125 |
+
struct packed_type<int8_t, 2> {
|
| 126 |
+
using type = int16_t;
|
| 127 |
+
};
|
| 128 |
+
template<>
|
| 129 |
+
struct packed_type<int8_t, 4> {
|
| 130 |
+
using type = int32_t;
|
| 131 |
+
};
|
| 132 |
+
template<>
|
| 133 |
+
struct packed_type<int8_t, 8> {
|
| 134 |
+
using type = int64_t;
|
| 135 |
+
};
|
| 136 |
+
|
| 137 |
+
template<>
|
| 138 |
+
struct packed_type<float, 2> {
|
| 139 |
+
using type = float2;
|
| 140 |
+
};
|
| 141 |
+
template<>
|
| 142 |
+
struct packed_type<float, 4> {
|
| 143 |
+
using type = float4;
|
| 144 |
+
};
|
| 145 |
+
template<>
|
| 146 |
+
struct packed_type<float, 8> {
|
| 147 |
+
using type = Float8_;
|
| 148 |
+
};
|
| 149 |
+
|
| 150 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 151 |
+
|
| 152 |
+
inline __device__ float add(float a, float b)
|
| 153 |
+
{
|
| 154 |
+
return a + b;
|
| 155 |
+
}
|
| 156 |
+
|
| 157 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 158 |
+
|
| 159 |
+
inline __device__ float2 add(float2 a, float2 b)
|
| 160 |
+
{
|
| 161 |
+
float2 c;
|
| 162 |
+
c.x = add(a.x, b.x);
|
| 163 |
+
c.y = add(a.y, b.y);
|
| 164 |
+
return c;
|
| 165 |
+
}
|
| 166 |
+
|
| 167 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 168 |
+
|
| 169 |
+
inline __device__ float4 add(float4 a, float4 b)
|
| 170 |
+
{
|
| 171 |
+
float4 c;
|
| 172 |
+
c.x = add(a.x, b.x);
|
| 173 |
+
c.y = add(a.y, b.y);
|
| 174 |
+
c.z = add(a.z, b.z);
|
| 175 |
+
c.w = add(a.w, b.w);
|
| 176 |
+
return c;
|
| 177 |
+
}
|
| 178 |
+
|
| 179 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 180 |
+
|
| 181 |
+
#ifdef ENABLE_BF16
|
| 182 |
+
inline __device__ __nv_bfloat16 add(__nv_bfloat16 a, __nv_bfloat16 b)
|
| 183 |
+
{
|
| 184 |
+
return a + b;
|
| 185 |
+
}
|
| 186 |
+
|
| 187 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 188 |
+
|
| 189 |
+
inline __device__ __nv_bfloat162 add(__nv_bfloat162 a, __nv_bfloat162 b)
|
| 190 |
+
{
|
| 191 |
+
return bf16hadd2(a, b);
|
| 192 |
+
}
|
| 193 |
+
|
| 194 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 195 |
+
|
| 196 |
+
inline __device__ bf16_4_t add(bf16_4_t a, bf16_4_t b)
|
| 197 |
+
{
|
| 198 |
+
bf16_4_t c;
|
| 199 |
+
c.x = add(a.x, b.x);
|
| 200 |
+
c.y = add(a.y, b.y);
|
| 201 |
+
return c;
|
| 202 |
+
}
|
| 203 |
+
|
| 204 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 205 |
+
|
| 206 |
+
inline __device__ bf16_8_t add(bf16_8_t a, bf16_8_t b)
|
| 207 |
+
{
|
| 208 |
+
bf16_8_t c;
|
| 209 |
+
c.x = add(a.x, b.x);
|
| 210 |
+
c.y = add(a.y, b.y);
|
| 211 |
+
c.z = add(a.z, b.z);
|
| 212 |
+
c.w = add(a.w, b.w);
|
| 213 |
+
return c;
|
| 214 |
+
}
|
| 215 |
+
#endif // ENABLE_BF16
|
| 216 |
+
|
| 217 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 218 |
+
|
| 219 |
+
inline __device__ uint16_t add(uint16_t a, uint16_t b)
|
| 220 |
+
{
|
| 221 |
+
uint16_t c;
|
| 222 |
+
asm volatile("add.f16 %0, %1, %2;\n" : "=h"(c) : "h"(a), "h"(b));
|
| 223 |
+
return c;
|
| 224 |
+
}
|
| 225 |
+
|
| 226 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 227 |
+
|
| 228 |
+
inline __device__ uint32_t add(uint32_t a, uint32_t b)
|
| 229 |
+
{
|
| 230 |
+
uint32_t c;
|
| 231 |
+
asm volatile("add.f16x2 %0, %1, %2;\n" : "=r"(c) : "r"(a), "r"(b));
|
| 232 |
+
return c;
|
| 233 |
+
}
|
| 234 |
+
|
| 235 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 236 |
+
|
| 237 |
+
inline __device__ uint2 add(uint2 a, uint2 b)
|
| 238 |
+
{
|
| 239 |
+
uint2 c;
|
| 240 |
+
c.x = add(a.x, b.x);
|
| 241 |
+
c.y = add(a.y, b.y);
|
| 242 |
+
return c;
|
| 243 |
+
}
|
| 244 |
+
|
| 245 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 246 |
+
|
| 247 |
+
inline __device__ uint4 add(uint4 a, uint4 b)
|
| 248 |
+
{
|
| 249 |
+
uint4 c;
|
| 250 |
+
c.x = add(a.x, b.x);
|
| 251 |
+
c.y = add(a.y, b.y);
|
| 252 |
+
c.z = add(a.z, b.z);
|
| 253 |
+
c.w = add(a.w, b.w);
|
| 254 |
+
return c;
|
| 255 |
+
}
|
| 256 |
+
|
| 257 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 258 |
+
|
| 259 |
+
inline __device__ uint16_t float_to_half(float f)
|
| 260 |
+
{
|
| 261 |
+
union {
|
| 262 |
+
uint32_t u32;
|
| 263 |
+
uint16_t u16[2];
|
| 264 |
+
} tmp;
|
| 265 |
+
#if 0 && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 800 // Is it better?
|
| 266 |
+
float zero = 0.f;
|
| 267 |
+
asm volatile("cvt.rn.f16x2.f32 %0, %1, %2;\n" : "=r"(tmp.u32) : "f"(zero), "f"(f));
|
| 268 |
+
#else
|
| 269 |
+
asm volatile("cvt.rn.f16.f32 %0, %1;\n" : "=h"(tmp.u16[0]) : "f"(f));
|
| 270 |
+
#endif
|
| 271 |
+
return tmp.u16[0];
|
| 272 |
+
}
|
| 273 |
+
|
| 274 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 275 |
+
|
| 276 |
+
inline __device__ uint32_t float2_to_half2(float2 f)
|
| 277 |
+
{
|
| 278 |
+
union {
|
| 279 |
+
uint32_t u32;
|
| 280 |
+
uint16_t u16[2];
|
| 281 |
+
} tmp;
|
| 282 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 800
|
| 283 |
+
asm volatile("cvt.rn.f16x2.f32 %0, %1, %2;\n" : "=r"(tmp.u32) : "f"(f.y), "f"(f.x));
|
| 284 |
+
#else
|
| 285 |
+
asm volatile("cvt.rn.f16.f32 %0, %1;\n" : "=h"(tmp.u16[0]) : "f"(f.x));
|
| 286 |
+
asm volatile("cvt.rn.f16.f32 %0, %1;\n" : "=h"(tmp.u16[1]) : "f"(f.y));
|
| 287 |
+
#endif
|
| 288 |
+
return tmp.u32;
|
| 289 |
+
}
|
| 290 |
+
|
| 291 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 292 |
+
|
| 293 |
+
inline __device__ float half_to_float(uint16_t h)
|
| 294 |
+
{
|
| 295 |
+
float f;
|
| 296 |
+
asm volatile("cvt.f32.f16 %0, %1;\n" : "=f"(f) : "h"(h));
|
| 297 |
+
return f;
|
| 298 |
+
}
|
| 299 |
+
|
| 300 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 301 |
+
|
| 302 |
+
inline __device__ float2 half2_to_float2(uint32_t v)
|
| 303 |
+
{
|
| 304 |
+
uint16_t lo, hi;
|
| 305 |
+
asm volatile("mov.b32 {%0, %1}, %2;\n" : "=h"(lo), "=h"(hi) : "r"(v));
|
| 306 |
+
return make_float2(half_to_float(lo), half_to_float(hi));
|
| 307 |
+
}
|
| 308 |
+
|
| 309 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 310 |
+
|
| 311 |
+
inline __device__ float add(float a, uint16_t b)
|
| 312 |
+
{
|
| 313 |
+
return a + half_to_float(b);
|
| 314 |
+
}
|
| 315 |
+
|
| 316 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 317 |
+
|
| 318 |
+
#ifdef ENABLE_BF16
|
| 319 |
+
inline __device__ float add(float a, __nv_bfloat16 b)
|
| 320 |
+
{
|
| 321 |
+
return a + __bfloat162float(b);
|
| 322 |
+
}
|
| 323 |
+
#endif
|
| 324 |
+
|
| 325 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 326 |
+
|
| 327 |
+
inline __device__ float2 add(uint32_t a, float2 fb)
|
| 328 |
+
{
|
| 329 |
+
float2 fa = half2_to_float2(a);
|
| 330 |
+
return add(fa, fb);
|
| 331 |
+
}
|
| 332 |
+
|
| 333 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 334 |
+
|
| 335 |
+
inline __device__ Float4_ add(uint2 a, Float4_ fb)
|
| 336 |
+
{
|
| 337 |
+
Float4_ fc;
|
| 338 |
+
fc.x = add(a.x, fb.x);
|
| 339 |
+
fc.y = add(a.y, fb.y);
|
| 340 |
+
return fc;
|
| 341 |
+
}
|
| 342 |
+
|
| 343 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 344 |
+
|
| 345 |
+
inline __device__ Float8_ add(uint4 a, Float8_ fb)
|
| 346 |
+
{
|
| 347 |
+
Float8_ fc;
|
| 348 |
+
fc.x = add(a.x, fb.x);
|
| 349 |
+
fc.y = add(a.y, fb.y);
|
| 350 |
+
fc.z = add(a.z, fb.z);
|
| 351 |
+
fc.w = add(a.w, fb.w);
|
| 352 |
+
return fc;
|
| 353 |
+
}
|
| 354 |
+
|
| 355 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 356 |
+
|
| 357 |
+
inline __device__ uint32_t h0_h0(uint16_t a)
|
| 358 |
+
{
|
| 359 |
+
uint32_t b;
|
| 360 |
+
asm volatile("mov.b32 %0, {%1, %1};" : "=r"(b) : "h"(a));
|
| 361 |
+
return b;
|
| 362 |
+
}
|
| 363 |
+
|
| 364 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 365 |
+
|
| 366 |
+
inline __device__ float fma(float a, float b, float c)
|
| 367 |
+
{
|
| 368 |
+
return a * b + c;
|
| 369 |
+
}
|
| 370 |
+
|
| 371 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 372 |
+
|
| 373 |
+
inline __device__ float2 fma(float2 a, float2 b, float2 c)
|
| 374 |
+
{
|
| 375 |
+
float2 d;
|
| 376 |
+
d.x = fma(a.x, b.x, c.x);
|
| 377 |
+
d.y = fma(a.y, b.y, c.y);
|
| 378 |
+
return d;
|
| 379 |
+
}
|
| 380 |
+
|
| 381 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 382 |
+
|
| 383 |
+
inline __device__ float2 fma(float a, float2 b, float2 c)
|
| 384 |
+
{
|
| 385 |
+
float2 d;
|
| 386 |
+
d.x = fma(a, b.x, c.x);
|
| 387 |
+
d.y = fma(a, b.y, c.y);
|
| 388 |
+
return d;
|
| 389 |
+
}
|
| 390 |
+
|
| 391 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 392 |
+
|
| 393 |
+
inline __device__ float4 fma(float4 a, float4 b, float4 c)
|
| 394 |
+
{
|
| 395 |
+
float4 d;
|
| 396 |
+
d.x = fma(a.x, b.x, c.x);
|
| 397 |
+
d.y = fma(a.y, b.y, c.y);
|
| 398 |
+
d.z = fma(a.z, b.z, c.z);
|
| 399 |
+
d.w = fma(a.w, b.w, c.w);
|
| 400 |
+
return d;
|
| 401 |
+
}
|
| 402 |
+
|
| 403 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 404 |
+
|
| 405 |
+
inline __device__ float4 fma(float a, float4 b, float4 c)
|
| 406 |
+
{
|
| 407 |
+
float4 d;
|
| 408 |
+
d.x = fma(a, b.x, c.x);
|
| 409 |
+
d.y = fma(a, b.y, c.y);
|
| 410 |
+
d.z = fma(a, b.z, c.z);
|
| 411 |
+
d.w = fma(a, b.w, c.w);
|
| 412 |
+
return d;
|
| 413 |
+
}
|
| 414 |
+
|
| 415 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 416 |
+
|
| 417 |
+
inline __device__ Float4_ fma(float a, Float4_ b, Float4_ c)
|
| 418 |
+
{
|
| 419 |
+
Float4_ d;
|
| 420 |
+
d.x = fma(a, b.x, c.x);
|
| 421 |
+
d.y = fma(a, b.y, c.y);
|
| 422 |
+
return d;
|
| 423 |
+
}
|
| 424 |
+
|
| 425 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 426 |
+
|
| 427 |
+
inline __device__ Float8_ fma(float a, Float8_ b, Float8_ c)
|
| 428 |
+
{
|
| 429 |
+
Float8_ d;
|
| 430 |
+
d.x = fma(a, b.x, c.x);
|
| 431 |
+
d.y = fma(a, b.y, c.y);
|
| 432 |
+
d.z = fma(a, b.z, c.z);
|
| 433 |
+
d.w = fma(a, b.w, c.w);
|
| 434 |
+
return d;
|
| 435 |
+
}
|
| 436 |
+
|
| 437 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 438 |
+
|
| 439 |
+
#ifdef ENABLE_BF16
|
| 440 |
+
inline __device__ float2 add(__nv_bfloat162 a, float2 fb)
|
| 441 |
+
{
|
| 442 |
+
float2 fa = bf1622float2(a);
|
| 443 |
+
return add(fa, fb);
|
| 444 |
+
}
|
| 445 |
+
|
| 446 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 447 |
+
|
| 448 |
+
inline __device__ Float4_ add(bf16_4_t a, Float4_ fb)
|
| 449 |
+
{
|
| 450 |
+
Float4_ fc;
|
| 451 |
+
fc.x = add(a.x, fb.x);
|
| 452 |
+
fc.y = add(a.y, fb.y);
|
| 453 |
+
return fc;
|
| 454 |
+
}
|
| 455 |
+
|
| 456 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 457 |
+
|
| 458 |
+
inline __device__ Float8_ add(bf16_8_t a, Float8_ fb)
|
| 459 |
+
{
|
| 460 |
+
Float8_ fc;
|
| 461 |
+
fc.x = add(a.x, fb.x);
|
| 462 |
+
fc.y = add(a.y, fb.y);
|
| 463 |
+
fc.z = add(a.z, fb.z);
|
| 464 |
+
fc.w = add(a.w, fb.w);
|
| 465 |
+
return fc;
|
| 466 |
+
}
|
| 467 |
+
#endif // ENABLE_BF16
|
| 468 |
+
|
| 469 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 470 |
+
|
| 471 |
+
inline __device__ uint32_t fma(uint32_t a, uint32_t b, uint32_t c)
|
| 472 |
+
{
|
| 473 |
+
uint32_t d;
|
| 474 |
+
asm volatile("fma.rn.f16x2 %0, %1, %2, %3;\n" : "=r"(d) : "r"(a), "r"(b), "r"(c));
|
| 475 |
+
return d;
|
| 476 |
+
}
|
| 477 |
+
|
| 478 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 479 |
+
|
| 480 |
+
inline __device__ uint32_t fma(uint16_t a, uint32_t b, uint32_t c)
|
| 481 |
+
{
|
| 482 |
+
return fma(h0_h0(a), b, c);
|
| 483 |
+
}
|
| 484 |
+
|
| 485 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 486 |
+
|
| 487 |
+
inline __device__ uint2 fma(uint2 a, uint2 b, uint2 c)
|
| 488 |
+
{
|
| 489 |
+
uint2 d;
|
| 490 |
+
d.x = fma(a.x, b.x, c.x);
|
| 491 |
+
d.y = fma(a.y, b.y, c.y);
|
| 492 |
+
return d;
|
| 493 |
+
}
|
| 494 |
+
|
| 495 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 496 |
+
|
| 497 |
+
inline __device__ uint2 fma(uint16_t a, uint2 b, uint2 c)
|
| 498 |
+
{
|
| 499 |
+
uint32_t s = h0_h0(a);
|
| 500 |
+
uint2 d;
|
| 501 |
+
d.x = fma(s, b.x, c.x);
|
| 502 |
+
d.y = fma(s, b.y, c.y);
|
| 503 |
+
return d;
|
| 504 |
+
}
|
| 505 |
+
|
| 506 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 507 |
+
|
| 508 |
+
inline __device__ uint4 fma(uint4 a, uint4 b, uint4 c)
|
| 509 |
+
{
|
| 510 |
+
uint4 d;
|
| 511 |
+
d.x = fma(a.x, b.x, c.x);
|
| 512 |
+
d.y = fma(a.y, b.y, c.y);
|
| 513 |
+
d.z = fma(a.z, b.z, c.z);
|
| 514 |
+
d.w = fma(a.w, b.w, c.w);
|
| 515 |
+
return d;
|
| 516 |
+
}
|
| 517 |
+
|
| 518 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 519 |
+
|
| 520 |
+
inline __device__ uint4 fma(uint16_t a, uint4 b, uint4 c)
|
| 521 |
+
{
|
| 522 |
+
uint32_t s = h0_h0(a);
|
| 523 |
+
uint4 d;
|
| 524 |
+
d.x = fma(s, b.x, c.x);
|
| 525 |
+
d.y = fma(s, b.y, c.y);
|
| 526 |
+
d.z = fma(s, b.z, c.z);
|
| 527 |
+
d.w = fma(s, b.w, c.w);
|
| 528 |
+
return d;
|
| 529 |
+
}
|
| 530 |
+
|
| 531 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 532 |
+
|
| 533 |
+
inline __device__ float fma(uint16_t a, uint16_t b, float fc)
|
| 534 |
+
{
|
| 535 |
+
float fa = half_to_float(a);
|
| 536 |
+
float fb = half_to_float(b);
|
| 537 |
+
return fa * fb + fc;
|
| 538 |
+
}
|
| 539 |
+
|
| 540 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 541 |
+
|
| 542 |
+
inline __device__ float2 fma(uint32_t a, uint32_t b, float2 fc)
|
| 543 |
+
{
|
| 544 |
+
float2 fa = half2_to_float2(a);
|
| 545 |
+
float2 fb = half2_to_float2(b);
|
| 546 |
+
return fma(fa, fb, fc);
|
| 547 |
+
}
|
| 548 |
+
|
| 549 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 550 |
+
|
| 551 |
+
inline __device__ float2 fma(uint16_t a, uint32_t b, float2 fc)
|
| 552 |
+
{
|
| 553 |
+
return fma(h0_h0(a), b, fc);
|
| 554 |
+
}
|
| 555 |
+
|
| 556 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 557 |
+
|
| 558 |
+
inline __device__ Float4_ fma(uint2 a, uint2 b, Float4_ fc)
|
| 559 |
+
{
|
| 560 |
+
Float4_ fd;
|
| 561 |
+
fd.x = fma(a.x, b.x, fc.x);
|
| 562 |
+
fd.y = fma(a.y, b.y, fc.y);
|
| 563 |
+
return fd;
|
| 564 |
+
}
|
| 565 |
+
|
| 566 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 567 |
+
|
| 568 |
+
inline __device__ Float4_ fma(uint16_t a, uint2 b, Float4_ fc)
|
| 569 |
+
{
|
| 570 |
+
uint32_t s = h0_h0(a);
|
| 571 |
+
Float4_ fd;
|
| 572 |
+
fd.x = fma(s, b.x, fc.x);
|
| 573 |
+
fd.y = fma(s, b.y, fc.y);
|
| 574 |
+
return fd;
|
| 575 |
+
}
|
| 576 |
+
|
| 577 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 578 |
+
|
| 579 |
+
inline __device__ Float8_ fma(uint4 a, uint4 b, Float8_ fc)
|
| 580 |
+
{
|
| 581 |
+
Float8_ fd;
|
| 582 |
+
fd.x = fma(a.x, b.x, fc.x);
|
| 583 |
+
fd.y = fma(a.y, b.y, fc.y);
|
| 584 |
+
fd.z = fma(a.z, b.z, fc.z);
|
| 585 |
+
fd.w = fma(a.w, b.w, fc.w);
|
| 586 |
+
return fd;
|
| 587 |
+
}
|
| 588 |
+
|
| 589 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 590 |
+
|
| 591 |
+
inline __device__ Float8_ fma(uint16_t a, uint4 b, Float8_ fc)
|
| 592 |
+
{
|
| 593 |
+
uint32_t s = h0_h0(a);
|
| 594 |
+
Float8_ fd;
|
| 595 |
+
fd.x = fma(s, b.x, fc.x);
|
| 596 |
+
fd.y = fma(s, b.y, fc.y);
|
| 597 |
+
fd.z = fma(s, b.z, fc.z);
|
| 598 |
+
fd.w = fma(s, b.w, fc.w);
|
| 599 |
+
return fd;
|
| 600 |
+
}
|
| 601 |
+
|
| 602 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 603 |
+
#ifdef ENABLE_BF16
|
| 604 |
+
inline __device__ __nv_bfloat162 fma(__nv_bfloat162 a, __nv_bfloat162 b, __nv_bfloat162 c)
|
| 605 |
+
{
|
| 606 |
+
return bf16hfma2(a, b, c);
|
| 607 |
+
}
|
| 608 |
+
|
| 609 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 610 |
+
|
| 611 |
+
inline __device__ __nv_bfloat162 fma(__nv_bfloat16 a, __nv_bfloat162 b, __nv_bfloat162 c)
|
| 612 |
+
{
|
| 613 |
+
return bf16hfma2(bf162bf162(a), b, c);
|
| 614 |
+
}
|
| 615 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 616 |
+
|
| 617 |
+
inline __device__ bf16_4_t fma(bf16_4_t a, bf16_4_t b, bf16_4_t c)
|
| 618 |
+
{
|
| 619 |
+
bf16_4_t d;
|
| 620 |
+
d.x = fma(a.x, b.x, c.x);
|
| 621 |
+
d.y = fma(a.y, b.y, c.y);
|
| 622 |
+
return d;
|
| 623 |
+
}
|
| 624 |
+
|
| 625 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 626 |
+
|
| 627 |
+
inline __device__ bf16_4_t fma(__nv_bfloat16 a, bf16_4_t b, bf16_4_t c)
|
| 628 |
+
{
|
| 629 |
+
__nv_bfloat162 s = bf162bf162(a);
|
| 630 |
+
bf16_4_t d;
|
| 631 |
+
d.x = fma(s, b.x, c.x);
|
| 632 |
+
d.y = fma(s, b.y, c.y);
|
| 633 |
+
return d;
|
| 634 |
+
}
|
| 635 |
+
|
| 636 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 637 |
+
|
| 638 |
+
inline __device__ bf16_8_t fma(bf16_8_t a, bf16_8_t b, bf16_8_t c)
|
| 639 |
+
{
|
| 640 |
+
bf16_8_t d;
|
| 641 |
+
d.x = fma(a.x, b.x, c.x);
|
| 642 |
+
d.y = fma(a.y, b.y, c.y);
|
| 643 |
+
d.z = fma(a.z, b.z, c.z);
|
| 644 |
+
d.w = fma(a.w, b.w, c.w);
|
| 645 |
+
return d;
|
| 646 |
+
}
|
| 647 |
+
|
| 648 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 649 |
+
|
| 650 |
+
inline __device__ bf16_8_t fma(__nv_bfloat16 a, bf16_8_t b, bf16_8_t c)
|
| 651 |
+
{
|
| 652 |
+
__nv_bfloat162 s = bf162bf162(a);
|
| 653 |
+
bf16_8_t d;
|
| 654 |
+
d.x = fma(s, b.x, c.x);
|
| 655 |
+
d.y = fma(s, b.y, c.y);
|
| 656 |
+
d.z = fma(s, b.z, c.z);
|
| 657 |
+
d.w = fma(s, b.w, c.w);
|
| 658 |
+
return d;
|
| 659 |
+
}
|
| 660 |
+
|
| 661 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 662 |
+
|
| 663 |
+
inline __device__ float fma(__nv_bfloat16 a, __nv_bfloat16 b, float fc)
|
| 664 |
+
{
|
| 665 |
+
return __bfloat162float(a) * __bfloat162float(b) + fc;
|
| 666 |
+
}
|
| 667 |
+
|
| 668 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 669 |
+
|
| 670 |
+
inline __device__ float2 fma(__nv_bfloat162 a, __nv_bfloat162 b, float2 fc)
|
| 671 |
+
{
|
| 672 |
+
float2 fa = bf1622float2(a);
|
| 673 |
+
float2 fb = bf1622float2(b);
|
| 674 |
+
return fma(fa, fb, fc);
|
| 675 |
+
}
|
| 676 |
+
|
| 677 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 678 |
+
|
| 679 |
+
inline __device__ float2 fma(__nv_bfloat16 a, __nv_bfloat162 b, float2 fc)
|
| 680 |
+
{
|
| 681 |
+
return fma(bf162bf162(a), b, fc);
|
| 682 |
+
}
|
| 683 |
+
|
| 684 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 685 |
+
|
| 686 |
+
inline __device__ Float4_ fma(bf16_4_t a, bf16_4_t b, Float4_ fc)
|
| 687 |
+
{
|
| 688 |
+
Float4_ fd;
|
| 689 |
+
fd.x = fma(a.x, b.x, fc.x);
|
| 690 |
+
fd.y = fma(a.y, b.y, fc.y);
|
| 691 |
+
return fd;
|
| 692 |
+
}
|
| 693 |
+
|
| 694 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 695 |
+
|
| 696 |
+
inline __device__ Float4_ fma(__nv_bfloat16 a, bf16_4_t b, Float4_ fc)
|
| 697 |
+
{
|
| 698 |
+
__nv_bfloat162 s = bf162bf162(a);
|
| 699 |
+
Float4_ fd;
|
| 700 |
+
fd.x = fma(s, b.x, fc.x);
|
| 701 |
+
fd.y = fma(s, b.y, fc.y);
|
| 702 |
+
return fd;
|
| 703 |
+
}
|
| 704 |
+
|
| 705 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 706 |
+
|
| 707 |
+
inline __device__ Float8_ fma(bf16_8_t a, bf16_8_t b, Float8_ fc)
|
| 708 |
+
{
|
| 709 |
+
Float8_ fd;
|
| 710 |
+
fd.x = fma(a.x, b.x, fc.x);
|
| 711 |
+
fd.y = fma(a.y, b.y, fc.y);
|
| 712 |
+
fd.z = fma(a.z, b.z, fc.z);
|
| 713 |
+
fd.w = fma(a.w, b.w, fc.w);
|
| 714 |
+
return fd;
|
| 715 |
+
}
|
| 716 |
+
|
| 717 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 718 |
+
|
| 719 |
+
inline __device__ Float8_ fma(__nv_bfloat16 a, bf16_8_t b, Float8_ fc)
|
| 720 |
+
{
|
| 721 |
+
__nv_bfloat162 s = bf162bf162(a);
|
| 722 |
+
Float8_ fd;
|
| 723 |
+
fd.x = fma(s, b.x, fc.x);
|
| 724 |
+
fd.y = fma(s, b.y, fc.y);
|
| 725 |
+
fd.z = fma(s, b.z, fc.z);
|
| 726 |
+
fd.w = fma(s, b.w, fc.w);
|
| 727 |
+
return fd;
|
| 728 |
+
}
|
| 729 |
+
#endif // ENABLE_BF16
|
| 730 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 731 |
+
|
| 732 |
+
template<typename Acc, typename A, typename B>
|
| 733 |
+
inline __device__ Acc mul(A a, B b)
|
| 734 |
+
{
|
| 735 |
+
return a * b;
|
| 736 |
+
}
|
| 737 |
+
|
| 738 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 739 |
+
|
| 740 |
+
template<>
|
| 741 |
+
inline __device__ float mul<float, float>(float a, float b)
|
| 742 |
+
{
|
| 743 |
+
return a * b;
|
| 744 |
+
}
|
| 745 |
+
|
| 746 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 747 |
+
|
| 748 |
+
template<>
|
| 749 |
+
inline __device__ float2 mul(float2 a, float2 b)
|
| 750 |
+
{
|
| 751 |
+
float2 c;
|
| 752 |
+
c.x = a.x * b.x;
|
| 753 |
+
c.y = a.y * b.y;
|
| 754 |
+
return c;
|
| 755 |
+
}
|
| 756 |
+
|
| 757 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 758 |
+
|
| 759 |
+
template<>
|
| 760 |
+
inline __device__ float2 mul(float a, float2 b)
|
| 761 |
+
{
|
| 762 |
+
float2 c;
|
| 763 |
+
c.x = a * b.x;
|
| 764 |
+
c.y = a * b.y;
|
| 765 |
+
return c;
|
| 766 |
+
}
|
| 767 |
+
|
| 768 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 769 |
+
|
| 770 |
+
template<>
|
| 771 |
+
inline __device__ float4 mul(float4 a, float4 b)
|
| 772 |
+
{
|
| 773 |
+
float4 c;
|
| 774 |
+
c.x = a.x * b.x;
|
| 775 |
+
c.y = a.y * b.y;
|
| 776 |
+
c.z = a.z * b.z;
|
| 777 |
+
c.w = a.w * b.w;
|
| 778 |
+
return c;
|
| 779 |
+
}
|
| 780 |
+
|
| 781 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 782 |
+
|
| 783 |
+
template<>
|
| 784 |
+
inline __device__ float4 mul(float a, float4 b)
|
| 785 |
+
{
|
| 786 |
+
float4 c;
|
| 787 |
+
c.x = a * b.x;
|
| 788 |
+
c.y = a * b.y;
|
| 789 |
+
c.z = a * b.z;
|
| 790 |
+
c.w = a * b.w;
|
| 791 |
+
return c;
|
| 792 |
+
}
|
| 793 |
+
|
| 794 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 795 |
+
|
| 796 |
+
template<>
|
| 797 |
+
inline __device__ Float8_ mul(float a, Float8_ b)
|
| 798 |
+
{
|
| 799 |
+
Float8_ c;
|
| 800 |
+
c.x = make_float2(a * b.x.x, a * b.x.y);
|
| 801 |
+
c.y = make_float2(a * b.y.x, a * b.y.y);
|
| 802 |
+
c.z = make_float2(a * b.z.x, a * b.z.y);
|
| 803 |
+
c.w = make_float2(a * b.w.x, a * b.w.y);
|
| 804 |
+
return c;
|
| 805 |
+
}
|
| 806 |
+
|
| 807 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 808 |
+
|
| 809 |
+
template<>
|
| 810 |
+
inline __device__ uint16_t mul(uint16_t a, uint16_t b)
|
| 811 |
+
{
|
| 812 |
+
uint16_t c;
|
| 813 |
+
asm volatile("mul.f16 %0, %1, %2;\n" : "=h"(c) : "h"(a), "h"(b));
|
| 814 |
+
return c;
|
| 815 |
+
}
|
| 816 |
+
|
| 817 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 818 |
+
|
| 819 |
+
template<>
|
| 820 |
+
inline __device__ uint32_t mul(uint32_t a, uint32_t b)
|
| 821 |
+
{
|
| 822 |
+
uint32_t c;
|
| 823 |
+
asm volatile("mul.f16x2 %0, %1, %2;\n" : "=r"(c) : "r"(a), "r"(b));
|
| 824 |
+
return c;
|
| 825 |
+
}
|
| 826 |
+
|
| 827 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 828 |
+
|
| 829 |
+
template<>
|
| 830 |
+
inline __device__ uint32_t mul(uint16_t a, uint32_t b)
|
| 831 |
+
{
|
| 832 |
+
return mul<uint32_t, uint32_t, uint32_t>(h0_h0(a), b);
|
| 833 |
+
}
|
| 834 |
+
|
| 835 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 836 |
+
|
| 837 |
+
template<>
|
| 838 |
+
inline __device__ uint2 mul(uint2 a, uint2 b)
|
| 839 |
+
{
|
| 840 |
+
uint2 c;
|
| 841 |
+
c.x = mul<uint32_t, uint32_t, uint32_t>(a.x, b.x);
|
| 842 |
+
c.y = mul<uint32_t, uint32_t, uint32_t>(a.y, b.y);
|
| 843 |
+
return c;
|
| 844 |
+
}
|
| 845 |
+
|
| 846 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 847 |
+
|
| 848 |
+
template<>
|
| 849 |
+
inline __device__ uint2 mul(uint16_t a, uint2 b)
|
| 850 |
+
{
|
| 851 |
+
uint32_t s = h0_h0(a);
|
| 852 |
+
uint2 c;
|
| 853 |
+
c.x = mul<uint32_t, uint32_t, uint32_t>(s, b.x);
|
| 854 |
+
c.y = mul<uint32_t, uint32_t, uint32_t>(s, b.y);
|
| 855 |
+
return c;
|
| 856 |
+
}
|
| 857 |
+
|
| 858 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 859 |
+
|
| 860 |
+
template<>
|
| 861 |
+
inline __device__ uint4 mul(uint4 a, uint4 b)
|
| 862 |
+
{
|
| 863 |
+
uint4 c;
|
| 864 |
+
c.x = mul<uint32_t, uint32_t, uint32_t>(a.x, b.x);
|
| 865 |
+
c.y = mul<uint32_t, uint32_t, uint32_t>(a.y, b.y);
|
| 866 |
+
c.z = mul<uint32_t, uint32_t, uint32_t>(a.z, b.z);
|
| 867 |
+
c.w = mul<uint32_t, uint32_t, uint32_t>(a.w, b.w);
|
| 868 |
+
return c;
|
| 869 |
+
}
|
| 870 |
+
|
| 871 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 872 |
+
|
| 873 |
+
template<>
|
| 874 |
+
inline __device__ uint4 mul(uint16_t a, uint4 b)
|
| 875 |
+
{
|
| 876 |
+
uint32_t s = h0_h0(a);
|
| 877 |
+
uint4 c;
|
| 878 |
+
c.x = mul<uint32_t, uint32_t, uint32_t>(s, b.x);
|
| 879 |
+
c.y = mul<uint32_t, uint32_t, uint32_t>(s, b.y);
|
| 880 |
+
c.z = mul<uint32_t, uint32_t, uint32_t>(s, b.z);
|
| 881 |
+
c.w = mul<uint32_t, uint32_t, uint32_t>(s, b.w);
|
| 882 |
+
return c;
|
| 883 |
+
}
|
| 884 |
+
|
| 885 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 886 |
+
|
| 887 |
+
template<>
|
| 888 |
+
inline __device__ float mul(uint16_t a, uint16_t b)
|
| 889 |
+
{
|
| 890 |
+
float fa = half_to_float(a);
|
| 891 |
+
float fb = half_to_float(b);
|
| 892 |
+
return fa * fb;
|
| 893 |
+
}
|
| 894 |
+
|
| 895 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 896 |
+
|
| 897 |
+
template<>
|
| 898 |
+
inline __device__ float mul(uint16_t a, float b)
|
| 899 |
+
{
|
| 900 |
+
return half_to_float(a) * b;
|
| 901 |
+
}
|
| 902 |
+
|
| 903 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 904 |
+
|
| 905 |
+
template<>
|
| 906 |
+
inline __device__ float2 mul(uint32_t a, uint32_t b)
|
| 907 |
+
{
|
| 908 |
+
float2 fa = half2_to_float2(a);
|
| 909 |
+
float2 fb = half2_to_float2(b);
|
| 910 |
+
return mul<float2, float2, float2>(fa, fb);
|
| 911 |
+
}
|
| 912 |
+
|
| 913 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 914 |
+
|
| 915 |
+
template<>
|
| 916 |
+
inline __device__ float2 mul(uint16_t a, uint32_t b)
|
| 917 |
+
{
|
| 918 |
+
return mul<float2, uint32_t, uint32_t>(h0_h0(a), b);
|
| 919 |
+
}
|
| 920 |
+
|
| 921 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 922 |
+
|
| 923 |
+
template<>
|
| 924 |
+
inline __device__ Float4_ mul(uint2 a, uint2 b)
|
| 925 |
+
{
|
| 926 |
+
Float4_ fc;
|
| 927 |
+
fc.x = mul<float2, uint32_t, uint32_t>(a.x, b.x);
|
| 928 |
+
fc.y = mul<float2, uint32_t, uint32_t>(a.y, b.y);
|
| 929 |
+
return fc;
|
| 930 |
+
}
|
| 931 |
+
|
| 932 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 933 |
+
|
| 934 |
+
template<>
|
| 935 |
+
inline __device__ Float4_ mul(uint16_t a, uint2 b)
|
| 936 |
+
{
|
| 937 |
+
uint32_t s = h0_h0(a);
|
| 938 |
+
Float4_ fc;
|
| 939 |
+
fc.x = mul<float2, uint32_t, uint32_t>(s, b.x);
|
| 940 |
+
fc.y = mul<float2, uint32_t, uint32_t>(s, b.y);
|
| 941 |
+
return fc;
|
| 942 |
+
}
|
| 943 |
+
|
| 944 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 945 |
+
|
| 946 |
+
template<>
|
| 947 |
+
inline __device__ Float8_ mul(uint4 a, uint4 b)
|
| 948 |
+
{
|
| 949 |
+
Float8_ fc;
|
| 950 |
+
fc.x = mul<float2, uint32_t, uint32_t>(a.x, b.x);
|
| 951 |
+
fc.y = mul<float2, uint32_t, uint32_t>(a.y, b.y);
|
| 952 |
+
fc.z = mul<float2, uint32_t, uint32_t>(a.z, b.z);
|
| 953 |
+
fc.w = mul<float2, uint32_t, uint32_t>(a.w, b.w);
|
| 954 |
+
return fc;
|
| 955 |
+
}
|
| 956 |
+
|
| 957 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 958 |
+
|
| 959 |
+
template<>
|
| 960 |
+
inline __device__ Float8_ mul(uint16_t a, uint4 b)
|
| 961 |
+
{
|
| 962 |
+
uint32_t s = h0_h0(a);
|
| 963 |
+
Float8_ fc;
|
| 964 |
+
fc.x = mul<float2, uint32_t, uint32_t>(s, b.x);
|
| 965 |
+
fc.y = mul<float2, uint32_t, uint32_t>(s, b.y);
|
| 966 |
+
fc.z = mul<float2, uint32_t, uint32_t>(s, b.z);
|
| 967 |
+
fc.w = mul<float2, uint32_t, uint32_t>(s, b.w);
|
| 968 |
+
return fc;
|
| 969 |
+
}
|
| 970 |
+
|
| 971 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 972 |
+
|
| 973 |
+
#ifdef ENABLE_BF16
|
| 974 |
+
template<>
|
| 975 |
+
inline __device__ __nv_bfloat16 mul(__nv_bfloat16 a, __nv_bfloat16 b)
|
| 976 |
+
{
|
| 977 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 800
|
| 978 |
+
return __hmul(a, b);
|
| 979 |
+
#else
|
| 980 |
+
return bf16hmul(a, b);
|
| 981 |
+
#endif
|
| 982 |
+
}
|
| 983 |
+
|
| 984 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 985 |
+
|
| 986 |
+
template<>
|
| 987 |
+
inline __device__ __nv_bfloat162 mul(__nv_bfloat162 a, __nv_bfloat162 b)
|
| 988 |
+
{
|
| 989 |
+
return bf16hmul2(a, b);
|
| 990 |
+
}
|
| 991 |
+
|
| 992 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 993 |
+
|
| 994 |
+
template<>
|
| 995 |
+
inline __device__ __nv_bfloat162 mul(__nv_bfloat16 a, __nv_bfloat162 b)
|
| 996 |
+
{
|
| 997 |
+
return mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(bf162bf162(a), b);
|
| 998 |
+
}
|
| 999 |
+
|
| 1000 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1001 |
+
|
| 1002 |
+
template<>
|
| 1003 |
+
inline __device__ bf16_4_t mul(bf16_4_t a, bf16_4_t b)
|
| 1004 |
+
{
|
| 1005 |
+
bf16_4_t c;
|
| 1006 |
+
c.x = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(a.x, b.x);
|
| 1007 |
+
c.y = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(a.y, b.y);
|
| 1008 |
+
return c;
|
| 1009 |
+
}
|
| 1010 |
+
|
| 1011 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1012 |
+
|
| 1013 |
+
template<>
|
| 1014 |
+
inline __device__ bf16_4_t mul(__nv_bfloat16 a, bf16_4_t b)
|
| 1015 |
+
{
|
| 1016 |
+
__nv_bfloat162 s = bf162bf162(a);
|
| 1017 |
+
bf16_4_t c;
|
| 1018 |
+
c.x = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(s, b.x);
|
| 1019 |
+
c.y = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(s, b.y);
|
| 1020 |
+
return c;
|
| 1021 |
+
}
|
| 1022 |
+
|
| 1023 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1024 |
+
|
| 1025 |
+
template<>
|
| 1026 |
+
inline __device__ bf16_8_t mul(bf16_8_t a, bf16_8_t b)
|
| 1027 |
+
{
|
| 1028 |
+
bf16_8_t c;
|
| 1029 |
+
c.x = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(a.x, b.x);
|
| 1030 |
+
c.y = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(a.y, b.y);
|
| 1031 |
+
c.z = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(a.z, b.z);
|
| 1032 |
+
c.w = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(a.w, b.w);
|
| 1033 |
+
return c;
|
| 1034 |
+
}
|
| 1035 |
+
|
| 1036 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1037 |
+
|
| 1038 |
+
template<>
|
| 1039 |
+
inline __device__ bf16_8_t mul(__nv_bfloat16 a, bf16_8_t b)
|
| 1040 |
+
{
|
| 1041 |
+
__nv_bfloat162 s = bf162bf162(a);
|
| 1042 |
+
bf16_8_t c;
|
| 1043 |
+
c.x = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(s, b.x);
|
| 1044 |
+
c.y = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(s, b.y);
|
| 1045 |
+
c.z = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(s, b.z);
|
| 1046 |
+
c.w = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(s, b.w);
|
| 1047 |
+
return c;
|
| 1048 |
+
}
|
| 1049 |
+
|
| 1050 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1051 |
+
|
| 1052 |
+
template<>
|
| 1053 |
+
inline __device__ float mul(__nv_bfloat16 a, __nv_bfloat16 b)
|
| 1054 |
+
{
|
| 1055 |
+
float fa = (float)a;
|
| 1056 |
+
float fb = (float)b;
|
| 1057 |
+
return fa * fb;
|
| 1058 |
+
}
|
| 1059 |
+
|
| 1060 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1061 |
+
|
| 1062 |
+
template<>
|
| 1063 |
+
inline __device__ float mul(__nv_bfloat16 a, float b)
|
| 1064 |
+
{
|
| 1065 |
+
return __bfloat162float(a) * b;
|
| 1066 |
+
}
|
| 1067 |
+
|
| 1068 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1069 |
+
|
| 1070 |
+
template<>
|
| 1071 |
+
inline __device__ float2 mul(__nv_bfloat162 a, __nv_bfloat162 b)
|
| 1072 |
+
{
|
| 1073 |
+
float2 fa = bf1622float2(a);
|
| 1074 |
+
float2 fb = bf1622float2(b);
|
| 1075 |
+
return mul<float2, float2, float2>(fa, fb);
|
| 1076 |
+
}
|
| 1077 |
+
|
| 1078 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1079 |
+
|
| 1080 |
+
template<>
|
| 1081 |
+
inline __device__ float2 mul(__nv_bfloat16 a, __nv_bfloat162 b)
|
| 1082 |
+
{
|
| 1083 |
+
return mul<float2, __nv_bfloat162, __nv_bfloat162>(bf162bf162(a), b);
|
| 1084 |
+
}
|
| 1085 |
+
|
| 1086 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1087 |
+
|
| 1088 |
+
template<>
|
| 1089 |
+
inline __device__ Float4_ mul(bf16_4_t a, bf16_4_t b)
|
| 1090 |
+
{
|
| 1091 |
+
Float4_ fc;
|
| 1092 |
+
fc.x = mul<float2, __nv_bfloat162, __nv_bfloat162>(a.x, b.x);
|
| 1093 |
+
fc.y = mul<float2, __nv_bfloat162, __nv_bfloat162>(a.y, b.y);
|
| 1094 |
+
return fc;
|
| 1095 |
+
}
|
| 1096 |
+
|
| 1097 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1098 |
+
|
| 1099 |
+
template<>
|
| 1100 |
+
inline __device__ Float4_ mul(__nv_bfloat16 a, bf16_4_t b)
|
| 1101 |
+
{
|
| 1102 |
+
__nv_bfloat162 s = bf162bf162(a);
|
| 1103 |
+
Float4_ fc;
|
| 1104 |
+
fc.x = mul<float2, __nv_bfloat162, __nv_bfloat162>(s, b.x);
|
| 1105 |
+
fc.y = mul<float2, __nv_bfloat162, __nv_bfloat162>(s, b.y);
|
| 1106 |
+
return fc;
|
| 1107 |
+
}
|
| 1108 |
+
|
| 1109 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1110 |
+
|
| 1111 |
+
template<>
|
| 1112 |
+
inline __device__ Float8_ mul(bf16_8_t a, bf16_8_t b)
|
| 1113 |
+
{
|
| 1114 |
+
Float8_ fc;
|
| 1115 |
+
fc.x = mul<float2, __nv_bfloat162, __nv_bfloat162>(a.x, b.x);
|
| 1116 |
+
fc.y = mul<float2, __nv_bfloat162, __nv_bfloat162>(a.y, b.y);
|
| 1117 |
+
fc.z = mul<float2, __nv_bfloat162, __nv_bfloat162>(a.z, b.z);
|
| 1118 |
+
fc.w = mul<float2, __nv_bfloat162, __nv_bfloat162>(a.w, b.w);
|
| 1119 |
+
return fc;
|
| 1120 |
+
}
|
| 1121 |
+
|
| 1122 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1123 |
+
|
| 1124 |
+
template<>
|
| 1125 |
+
inline __device__ Float8_ mul(__nv_bfloat16 a, bf16_8_t b)
|
| 1126 |
+
{
|
| 1127 |
+
__nv_bfloat162 s = bf162bf162(a);
|
| 1128 |
+
Float8_ fc;
|
| 1129 |
+
fc.x = mul<float2, __nv_bfloat162, __nv_bfloat162>(s, b.x);
|
| 1130 |
+
fc.y = mul<float2, __nv_bfloat162, __nv_bfloat162>(s, b.y);
|
| 1131 |
+
fc.z = mul<float2, __nv_bfloat162, __nv_bfloat162>(s, b.z);
|
| 1132 |
+
fc.w = mul<float2, __nv_bfloat162, __nv_bfloat162>(s, b.w);
|
| 1133 |
+
return fc;
|
| 1134 |
+
}
|
| 1135 |
+
#endif // ENABLE_BF16
|
| 1136 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1137 |
+
|
| 1138 |
+
inline __device__ float sum(float v)
|
| 1139 |
+
{
|
| 1140 |
+
return v;
|
| 1141 |
+
}
|
| 1142 |
+
|
| 1143 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1144 |
+
|
| 1145 |
+
inline __device__ float sum(float2 v)
|
| 1146 |
+
{
|
| 1147 |
+
return v.x + v.y;
|
| 1148 |
+
}
|
| 1149 |
+
|
| 1150 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1151 |
+
|
| 1152 |
+
inline __device__ float sum(float4 v)
|
| 1153 |
+
{
|
| 1154 |
+
return v.x + v.y + v.z + v.w;
|
| 1155 |
+
}
|
| 1156 |
+
|
| 1157 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1158 |
+
|
| 1159 |
+
#ifdef ENABLE_BF16
|
| 1160 |
+
inline __device__ float sum(__nv_bfloat162 v)
|
| 1161 |
+
{
|
| 1162 |
+
float2 vf = bf1622float2(v);
|
| 1163 |
+
return vf.x + vf.y;
|
| 1164 |
+
}
|
| 1165 |
+
|
| 1166 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1167 |
+
|
| 1168 |
+
inline __device__ float sum(bf16_4_t v)
|
| 1169 |
+
{
|
| 1170 |
+
return sum(v.x) + sum(v.y);
|
| 1171 |
+
}
|
| 1172 |
+
|
| 1173 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1174 |
+
|
| 1175 |
+
inline __device__ float sum(bf16_8_t v)
|
| 1176 |
+
{
|
| 1177 |
+
return sum(v.x) + sum(v.y) + sum(v.z) + sum(v.w);
|
| 1178 |
+
}
|
| 1179 |
+
#endif // ENABLE_BF16
|
| 1180 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1181 |
+
|
| 1182 |
+
inline __device__ float sum(uint16_t v)
|
| 1183 |
+
{
|
| 1184 |
+
return half_to_float(v);
|
| 1185 |
+
}
|
| 1186 |
+
|
| 1187 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1188 |
+
|
| 1189 |
+
inline __device__ float sum(uint32_t v)
|
| 1190 |
+
{
|
| 1191 |
+
float2 tmp = half2_to_float2(v);
|
| 1192 |
+
return tmp.x + tmp.y;
|
| 1193 |
+
}
|
| 1194 |
+
|
| 1195 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1196 |
+
|
| 1197 |
+
inline __device__ float sum(uint2 v)
|
| 1198 |
+
{
|
| 1199 |
+
uint32_t c = add(v.x, v.y);
|
| 1200 |
+
return sum(c);
|
| 1201 |
+
}
|
| 1202 |
+
|
| 1203 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1204 |
+
|
| 1205 |
+
inline __device__ float sum(uint4 v)
|
| 1206 |
+
{
|
| 1207 |
+
#if 1
|
| 1208 |
+
uint32_t c = add(v.x, v.y);
|
| 1209 |
+
c = add(c, v.z);
|
| 1210 |
+
c = add(c, v.w);
|
| 1211 |
+
#else
|
| 1212 |
+
uint32_t c = add(v.x, v.y);
|
| 1213 |
+
uint32_t d = add(v.z, v.w);
|
| 1214 |
+
c = add(c, d);
|
| 1215 |
+
#endif
|
| 1216 |
+
return sum(c);
|
| 1217 |
+
}
|
| 1218 |
+
|
| 1219 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1220 |
+
|
| 1221 |
+
inline __device__ float sum(Float4_ v)
|
| 1222 |
+
{
|
| 1223 |
+
return v.x.x + v.x.y + v.y.x + v.y.y;
|
| 1224 |
+
}
|
| 1225 |
+
|
| 1226 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1227 |
+
|
| 1228 |
+
inline __device__ float sum(Float8_ v)
|
| 1229 |
+
{
|
| 1230 |
+
return v.x.x + v.x.y + v.y.x + v.y.y + v.z.x + v.z.y + v.w.x + v.w.y;
|
| 1231 |
+
}
|
| 1232 |
+
|
| 1233 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1234 |
+
|
| 1235 |
+
template<typename T>
|
| 1236 |
+
inline __device__ float dot(T a, T b)
|
| 1237 |
+
{
|
| 1238 |
+
return sum(mul<T, T, T>(a, b));
|
| 1239 |
+
}
|
| 1240 |
+
|
| 1241 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1242 |
+
|
| 1243 |
+
template<typename A, typename T>
|
| 1244 |
+
inline __device__ float dot(T a, T b)
|
| 1245 |
+
{
|
| 1246 |
+
return sum(mul<A, T, T>(a, b));
|
| 1247 |
+
}
|
| 1248 |
+
|
| 1249 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1250 |
+
|
| 1251 |
+
inline __device__ void zero(uint16_t& dst)
|
| 1252 |
+
{
|
| 1253 |
+
dst = uint16_t(0);
|
| 1254 |
+
}
|
| 1255 |
+
|
| 1256 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1257 |
+
|
| 1258 |
+
template<typename T>
|
| 1259 |
+
inline __device__ void zero(T& dst)
|
| 1260 |
+
{
|
| 1261 |
+
constexpr int WORDS = sizeof(T) / 4;
|
| 1262 |
+
union {
|
| 1263 |
+
T raw;
|
| 1264 |
+
uint32_t words[WORDS];
|
| 1265 |
+
} tmp;
|
| 1266 |
+
#pragma unroll
|
| 1267 |
+
for (int ii = 0; ii < WORDS; ++ii) {
|
| 1268 |
+
tmp.words[ii] = 0u;
|
| 1269 |
+
}
|
| 1270 |
+
dst = tmp.raw;
|
| 1271 |
+
}
|
| 1272 |
+
|
| 1273 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1274 |
+
|
| 1275 |
+
// inline __device__ float2 rotary_embedding_coefficient(const int zid, const int rot_embed_dim, const float t_step, const float base)
|
| 1276 |
+
// {
|
| 1277 |
+
// const float inv_freq = t_step / pow(base, zid / (float)rot_embed_dim);
|
| 1278 |
+
// return {cos(inv_freq), sin(inv_freq)};
|
| 1279 |
+
// }
|
| 1280 |
+
|
| 1281 |
+
// with scale
|
| 1282 |
+
inline __device__ float2 rotary_embedding_coefficient(
|
| 1283 |
+
const int zid, const int rot_embed_dim, const float t_step, const float base, const float scale)
|
| 1284 |
+
{
|
| 1285 |
+
const float inv_freq = (t_step * scale) / pow(base, zid / (float)rot_embed_dim);
|
| 1286 |
+
return {cos(inv_freq), sin(inv_freq)};
|
| 1287 |
+
}
|
| 1288 |
+
|
| 1289 |
+
|
| 1290 |
+
inline __device__ float2 rotary_embedding_transform(const float2 v, const float2 coef)
|
| 1291 |
+
{
|
| 1292 |
+
float2 rot_v;
|
| 1293 |
+
rot_v.x = coef.x * v.x - coef.y * v.y;
|
| 1294 |
+
rot_v.y = coef.x * v.y + coef.y * v.x;
|
| 1295 |
+
return rot_v;
|
| 1296 |
+
}
|
| 1297 |
+
|
| 1298 |
+
inline __device__ uint32_t rotary_embedding_transform(const uint32_t v, const float2 coef)
|
| 1299 |
+
{
|
| 1300 |
+
float2 fv = half2_to_float2(v);
|
| 1301 |
+
float2 rot_fv = rotary_embedding_transform(fv, coef);
|
| 1302 |
+
return float2_to_half2(rot_fv);
|
| 1303 |
+
}
|
| 1304 |
+
|
| 1305 |
+
#ifdef ENABLE_BF16
|
| 1306 |
+
inline __device__ __nv_bfloat162 rotary_embedding_transform(const __nv_bfloat162 v, const float2 coef)
|
| 1307 |
+
{
|
| 1308 |
+
float2 fv = bf1622float2(v);
|
| 1309 |
+
float2 rot_fv = rotary_embedding_transform(fv, coef);
|
| 1310 |
+
return __floats2bfloat162_rn(rot_fv.x, rot_fv.y);
|
| 1311 |
+
}
|
| 1312 |
+
#endif
|
| 1313 |
+
|
| 1314 |
+
inline __device__ void apply_rotary_embedding(float& q, int zid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
|
| 1315 |
+
{
|
| 1316 |
+
return;
|
| 1317 |
+
}
|
| 1318 |
+
|
| 1319 |
+
inline __device__ void apply_rotary_embedding(float& q, float& k, int zid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
|
| 1320 |
+
{
|
| 1321 |
+
return;
|
| 1322 |
+
}
|
| 1323 |
+
|
| 1324 |
+
inline __device__ void apply_rotary_embedding(float2& q, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
|
| 1325 |
+
{
|
| 1326 |
+
if (2 * tid >= rot_embed_dim) {
|
| 1327 |
+
return;
|
| 1328 |
+
}
|
| 1329 |
+
const auto coef = rotary_embedding_coefficient(2 * tid, rot_embed_dim, t_step, base, scale);
|
| 1330 |
+
q = rotary_embedding_transform(q, coef);
|
| 1331 |
+
}
|
| 1332 |
+
|
| 1333 |
+
inline __device__ void apply_rotary_embedding(float2& q, float2& k, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
|
| 1334 |
+
{
|
| 1335 |
+
if (2 * tid >= rot_embed_dim) {
|
| 1336 |
+
return;
|
| 1337 |
+
}
|
| 1338 |
+
const auto coef = rotary_embedding_coefficient(2 * tid, rot_embed_dim, t_step, base, scale);
|
| 1339 |
+
q = rotary_embedding_transform(q, coef);
|
| 1340 |
+
k = rotary_embedding_transform(k, coef);
|
| 1341 |
+
}
|
| 1342 |
+
|
| 1343 |
+
inline __device__ void apply_rotary_embedding(float4& q, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
|
| 1344 |
+
{
|
| 1345 |
+
if (4 * tid >= rot_embed_dim) {
|
| 1346 |
+
return;
|
| 1347 |
+
}
|
| 1348 |
+
|
| 1349 |
+
Float4_& q_ = *reinterpret_cast<Float4_*>(&q);
|
| 1350 |
+
const auto coef0 = rotary_embedding_coefficient(4 * tid, rot_embed_dim, t_step, base, scale);
|
| 1351 |
+
q_.x = rotary_embedding_transform(q_.x, coef0);
|
| 1352 |
+
const auto coef1 = rotary_embedding_coefficient(4 * tid + 2, rot_embed_dim, t_step, base, scale);
|
| 1353 |
+
q_.y = rotary_embedding_transform(q_.y, coef1);
|
| 1354 |
+
}
|
| 1355 |
+
|
| 1356 |
+
inline __device__ void apply_rotary_embedding(float4& q, float4& k, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
|
| 1357 |
+
{
|
| 1358 |
+
if (4 * tid >= rot_embed_dim) {
|
| 1359 |
+
return;
|
| 1360 |
+
}
|
| 1361 |
+
|
| 1362 |
+
Float4_& q_ = *reinterpret_cast<Float4_*>(&q);
|
| 1363 |
+
Float4_& k_ = *reinterpret_cast<Float4_*>(&k);
|
| 1364 |
+
const auto coef0 = rotary_embedding_coefficient(4 * tid, rot_embed_dim, t_step, base, scale);
|
| 1365 |
+
q_.x = rotary_embedding_transform(q_.x, coef0);
|
| 1366 |
+
k_.x = rotary_embedding_transform(k_.x, coef0);
|
| 1367 |
+
const auto coef1 = rotary_embedding_coefficient(4 * tid + 2, rot_embed_dim, t_step, base, scale);
|
| 1368 |
+
q_.y = rotary_embedding_transform(q_.y, coef1);
|
| 1369 |
+
k_.y = rotary_embedding_transform(k_.y, coef1);
|
| 1370 |
+
}
|
| 1371 |
+
|
| 1372 |
+
inline __device__ void apply_rotary_embedding(uint32_t& q, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
|
| 1373 |
+
{
|
| 1374 |
+
if (2 * tid >= rot_embed_dim) {
|
| 1375 |
+
return;
|
| 1376 |
+
}
|
| 1377 |
+
const auto coef = rotary_embedding_coefficient(2 * tid, rot_embed_dim, t_step, base, scale);
|
| 1378 |
+
q = rotary_embedding_transform(q, coef);
|
| 1379 |
+
}
|
| 1380 |
+
|
| 1381 |
+
inline __device__ void apply_rotary_embedding(uint32_t& q, uint32_t& k, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
|
| 1382 |
+
{
|
| 1383 |
+
if (2 * tid >= rot_embed_dim) {
|
| 1384 |
+
return;
|
| 1385 |
+
}
|
| 1386 |
+
const auto coef = rotary_embedding_coefficient(2 * tid, rot_embed_dim, t_step, base, scale);
|
| 1387 |
+
q = rotary_embedding_transform(q, coef);
|
| 1388 |
+
k = rotary_embedding_transform(k, coef);
|
| 1389 |
+
}
|
| 1390 |
+
|
| 1391 |
+
inline __device__ void apply_rotary_embedding(uint2& q, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
|
| 1392 |
+
{
|
| 1393 |
+
if (4 * tid >= rot_embed_dim) {
|
| 1394 |
+
return;
|
| 1395 |
+
}
|
| 1396 |
+
const auto coef0 = rotary_embedding_coefficient(4 * tid, rot_embed_dim, t_step, base, scale);
|
| 1397 |
+
q.x = rotary_embedding_transform(q.x, coef0);
|
| 1398 |
+
const auto coef1 = rotary_embedding_coefficient(4 * tid + 2, rot_embed_dim, t_step, base, scale);
|
| 1399 |
+
q.y = rotary_embedding_transform(q.y, coef1);
|
| 1400 |
+
}
|
| 1401 |
+
|
| 1402 |
+
inline __device__ void apply_rotary_embedding(uint2& q, uint2& k, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
|
| 1403 |
+
{
|
| 1404 |
+
if (4 * tid >= rot_embed_dim) {
|
| 1405 |
+
return;
|
| 1406 |
+
}
|
| 1407 |
+
const auto coef0 = rotary_embedding_coefficient(4 * tid, rot_embed_dim, t_step, base, scale);
|
| 1408 |
+
q.x = rotary_embedding_transform(q.x, coef0);
|
| 1409 |
+
k.x = rotary_embedding_transform(k.x, coef0);
|
| 1410 |
+
const auto coef1 = rotary_embedding_coefficient(4 * tid + 2, rot_embed_dim, t_step, base, scale);
|
| 1411 |
+
q.y = rotary_embedding_transform(q.y, coef1);
|
| 1412 |
+
k.y = rotary_embedding_transform(k.y, coef1);
|
| 1413 |
+
}
|
| 1414 |
+
|
| 1415 |
+
inline __device__ void apply_rotary_embedding(uint4& q, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
|
| 1416 |
+
{
|
| 1417 |
+
if (8 * tid >= rot_embed_dim) {
|
| 1418 |
+
return;
|
| 1419 |
+
}
|
| 1420 |
+
const auto coef0 = rotary_embedding_coefficient(8 * tid, rot_embed_dim, t_step, base, scale);
|
| 1421 |
+
q.x = rotary_embedding_transform(q.x, coef0);
|
| 1422 |
+
const auto coef1 = rotary_embedding_coefficient(8 * tid + 2, rot_embed_dim, t_step, base, scale);
|
| 1423 |
+
q.y = rotary_embedding_transform(q.y, coef1);
|
| 1424 |
+
const auto coef2 = rotary_embedding_coefficient(8 * tid + 4, rot_embed_dim, t_step, base, scale);
|
| 1425 |
+
q.z = rotary_embedding_transform(q.z, coef2);
|
| 1426 |
+
const auto coef3 = rotary_embedding_coefficient(8 * tid + 6, rot_embed_dim, t_step, base, scale);
|
| 1427 |
+
q.w = rotary_embedding_transform(q.w, coef3);
|
| 1428 |
+
}
|
| 1429 |
+
|
| 1430 |
+
inline __device__ void apply_rotary_embedding(uint4& q, uint4& k, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
|
| 1431 |
+
{
|
| 1432 |
+
if (8 * tid >= rot_embed_dim) {
|
| 1433 |
+
return;
|
| 1434 |
+
}
|
| 1435 |
+
const auto coef0 = rotary_embedding_coefficient(8 * tid, rot_embed_dim, t_step, base, scale);
|
| 1436 |
+
q.x = rotary_embedding_transform(q.x, coef0);
|
| 1437 |
+
k.x = rotary_embedding_transform(k.x, coef0);
|
| 1438 |
+
const auto coef1 = rotary_embedding_coefficient(8 * tid + 2, rot_embed_dim, t_step, base, scale);
|
| 1439 |
+
q.y = rotary_embedding_transform(q.y, coef1);
|
| 1440 |
+
k.y = rotary_embedding_transform(k.y, coef1);
|
| 1441 |
+
const auto coef2 = rotary_embedding_coefficient(8 * tid + 4, rot_embed_dim, t_step, base, scale);
|
| 1442 |
+
q.z = rotary_embedding_transform(q.z, coef2);
|
| 1443 |
+
k.z = rotary_embedding_transform(k.z, coef2);
|
| 1444 |
+
const auto coef3 = rotary_embedding_coefficient(8 * tid + 6, rot_embed_dim, t_step, base, scale);
|
| 1445 |
+
q.w = rotary_embedding_transform(q.w, coef3);
|
| 1446 |
+
k.w = rotary_embedding_transform(k.w, coef3);
|
| 1447 |
+
}
|
| 1448 |
+
|
| 1449 |
+
#ifdef ENABLE_BF16
|
| 1450 |
+
inline __device__ void apply_rotary_embedding(__nv_bfloat162& q, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
|
| 1451 |
+
{
|
| 1452 |
+
if (2 * tid >= rot_embed_dim) {
|
| 1453 |
+
return;
|
| 1454 |
+
}
|
| 1455 |
+
const auto coef = rotary_embedding_coefficient(2 * tid, rot_embed_dim, t_step, base, scale);
|
| 1456 |
+
q = rotary_embedding_transform(q, coef);
|
| 1457 |
+
}
|
| 1458 |
+
|
| 1459 |
+
inline __device__ void
|
| 1460 |
+
apply_rotary_embedding(__nv_bfloat162& q, __nv_bfloat162& k, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
|
| 1461 |
+
{
|
| 1462 |
+
if (2 * tid >= rot_embed_dim) {
|
| 1463 |
+
return;
|
| 1464 |
+
}
|
| 1465 |
+
const auto coef = rotary_embedding_coefficient(2 * tid, rot_embed_dim, t_step, base, scale);
|
| 1466 |
+
q = rotary_embedding_transform(q, coef);
|
| 1467 |
+
k = rotary_embedding_transform(k, coef);
|
| 1468 |
+
}
|
| 1469 |
+
|
| 1470 |
+
inline __device__ void apply_rotary_embedding(bf16_4_t& q, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
|
| 1471 |
+
{
|
| 1472 |
+
if (4 * tid >= rot_embed_dim) {
|
| 1473 |
+
return;
|
| 1474 |
+
}
|
| 1475 |
+
const auto coef0 = rotary_embedding_coefficient(4 * tid, rot_embed_dim, t_step, base, scale);
|
| 1476 |
+
q.x = rotary_embedding_transform(q.x, coef0);
|
| 1477 |
+
const auto coef1 = rotary_embedding_coefficient(4 * tid + 2, rot_embed_dim, t_step, base, scale);
|
| 1478 |
+
q.y = rotary_embedding_transform(q.y, coef1);
|
| 1479 |
+
}
|
| 1480 |
+
|
| 1481 |
+
inline __device__ void apply_rotary_embedding(bf16_4_t& q, bf16_4_t& k, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
|
| 1482 |
+
{
|
| 1483 |
+
if (4 * tid >= rot_embed_dim) {
|
| 1484 |
+
return;
|
| 1485 |
+
}
|
| 1486 |
+
const auto coef0 = rotary_embedding_coefficient(4 * tid, rot_embed_dim, t_step, base, scale);
|
| 1487 |
+
q.x = rotary_embedding_transform(q.x, coef0);
|
| 1488 |
+
k.x = rotary_embedding_transform(k.x, coef0);
|
| 1489 |
+
const auto coef1 = rotary_embedding_coefficient(4 * tid + 2, rot_embed_dim, t_step, base, scale);
|
| 1490 |
+
q.y = rotary_embedding_transform(q.y, coef1);
|
| 1491 |
+
k.y = rotary_embedding_transform(k.y, coef1);
|
| 1492 |
+
}
|
| 1493 |
+
|
| 1494 |
+
inline __device__ void apply_rotary_embedding(bf16_8_t& q, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
|
| 1495 |
+
{
|
| 1496 |
+
if (8 * tid >= rot_embed_dim) {
|
| 1497 |
+
return;
|
| 1498 |
+
}
|
| 1499 |
+
const auto coef0 = rotary_embedding_coefficient(8 * tid, rot_embed_dim, t_step, base, scale);
|
| 1500 |
+
q.x = rotary_embedding_transform(q.x, coef0);
|
| 1501 |
+
const auto coef1 = rotary_embedding_coefficient(8 * tid + 2, rot_embed_dim, t_step, base, scale);
|
| 1502 |
+
q.y = rotary_embedding_transform(q.y, coef1);
|
| 1503 |
+
const auto coef2 = rotary_embedding_coefficient(8 * tid + 4, rot_embed_dim, t_step, base, scale);
|
| 1504 |
+
q.z = rotary_embedding_transform(q.z, coef2);
|
| 1505 |
+
const auto coef3 = rotary_embedding_coefficient(8 * tid + 6, rot_embed_dim, t_step, base, scale);
|
| 1506 |
+
q.w = rotary_embedding_transform(q.w, coef3);
|
| 1507 |
+
}
|
| 1508 |
+
|
| 1509 |
+
inline __device__ void apply_rotary_embedding(bf16_8_t& q, bf16_8_t& k, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
|
| 1510 |
+
{
|
| 1511 |
+
if (8 * tid >= rot_embed_dim) {
|
| 1512 |
+
return;
|
| 1513 |
+
}
|
| 1514 |
+
const auto coef0 = rotary_embedding_coefficient(8 * tid, rot_embed_dim, t_step, base, scale);
|
| 1515 |
+
q.x = rotary_embedding_transform(q.x, coef0);
|
| 1516 |
+
k.x = rotary_embedding_transform(k.x, coef0);
|
| 1517 |
+
const auto coef1 = rotary_embedding_coefficient(8 * tid + 2, rot_embed_dim, t_step, base, scale);
|
| 1518 |
+
q.y = rotary_embedding_transform(q.y, coef1);
|
| 1519 |
+
k.y = rotary_embedding_transform(k.y, coef1);
|
| 1520 |
+
const auto coef2 = rotary_embedding_coefficient(8 * tid + 4, rot_embed_dim, t_step, base, scale);
|
| 1521 |
+
q.z = rotary_embedding_transform(q.z, coef2);
|
| 1522 |
+
k.z = rotary_embedding_transform(k.z, coef2);
|
| 1523 |
+
const auto coef3 = rotary_embedding_coefficient(8 * tid + 6, rot_embed_dim, t_step, base, scale);
|
| 1524 |
+
q.w = rotary_embedding_transform(q.w, coef3);
|
| 1525 |
+
k.w = rotary_embedding_transform(k.w, coef3);
|
| 1526 |
+
}
|
| 1527 |
+
#endif // ENABLE_BF16
|
| 1528 |
+
|
| 1529 |
+
template<typename Vec_T, typename T>
|
| 1530 |
+
__device__ __inline__ void vec_from_smem_transpose(Vec_T& vec, T* smem, int transpose_idx, int smem_pitch);
|
| 1531 |
+
|
| 1532 |
+
template<>
|
| 1533 |
+
__device__ __inline__ void vec_from_smem_transpose(float& vec, float* smem, int transpose_idx, int smem_pitch)
|
| 1534 |
+
{
|
| 1535 |
+
return;
|
| 1536 |
+
}
|
| 1537 |
+
|
| 1538 |
+
template<>
|
| 1539 |
+
__device__ __inline__ void vec_from_smem_transpose(uint32_t& vec, uint16_t* smem, int transpose_idx, int smem_pitch)
|
| 1540 |
+
{
|
| 1541 |
+
union {
|
| 1542 |
+
uint32_t u32;
|
| 1543 |
+
uint16_t u16[2];
|
| 1544 |
+
} tmp;
|
| 1545 |
+
tmp.u16[0] = smem[transpose_idx];
|
| 1546 |
+
tmp.u16[1] = smem[smem_pitch + transpose_idx];
|
| 1547 |
+
|
| 1548 |
+
vec = tmp.u32;
|
| 1549 |
+
}
|
| 1550 |
+
|
| 1551 |
+
template<>
|
| 1552 |
+
__device__ __inline__ void vec_from_smem_transpose(uint2& vec, uint16_t* smem, int transpose_idx, int smem_pitch)
|
| 1553 |
+
{
|
| 1554 |
+
union {
|
| 1555 |
+
uint32_t u32;
|
| 1556 |
+
uint16_t u16[2];
|
| 1557 |
+
} tmp_1, tmp_2;
|
| 1558 |
+
tmp_1.u32 = *reinterpret_cast<uint32_t*>(&smem[transpose_idx]);
|
| 1559 |
+
tmp_2.u32 = *reinterpret_cast<uint32_t*>(&smem[smem_pitch + transpose_idx]);
|
| 1560 |
+
|
| 1561 |
+
union {
|
| 1562 |
+
uint2 u32x2;
|
| 1563 |
+
uint16_t u16[4];
|
| 1564 |
+
} tmp_3;
|
| 1565 |
+
tmp_3.u16[0] = tmp_1.u16[0];
|
| 1566 |
+
tmp_3.u16[1] = tmp_2.u16[0];
|
| 1567 |
+
tmp_3.u16[2] = tmp_1.u16[1];
|
| 1568 |
+
tmp_3.u16[3] = tmp_2.u16[1];
|
| 1569 |
+
|
| 1570 |
+
vec = tmp_3.u32x2;
|
| 1571 |
+
}
|
| 1572 |
+
|
| 1573 |
+
template<>
|
| 1574 |
+
__device__ __inline__ void vec_from_smem_transpose(uint4& vec, uint16_t* smem, int transpose_idx, int smem_pitch)
|
| 1575 |
+
{
|
| 1576 |
+
union {
|
| 1577 |
+
uint64_t u64;
|
| 1578 |
+
uint16_t u16[4];
|
| 1579 |
+
} tmp_1, tmp_2;
|
| 1580 |
+
tmp_1.u64 = *reinterpret_cast<uint64_t*>(&smem[transpose_idx]);
|
| 1581 |
+
tmp_2.u64 = *reinterpret_cast<uint64_t*>(&smem[smem_pitch + transpose_idx]);
|
| 1582 |
+
|
| 1583 |
+
union {
|
| 1584 |
+
uint4 u32x4;
|
| 1585 |
+
uint16_t u16[8];
|
| 1586 |
+
} tmp_3;
|
| 1587 |
+
tmp_3.u16[0] = tmp_1.u16[0];
|
| 1588 |
+
tmp_3.u16[1] = tmp_2.u16[0];
|
| 1589 |
+
tmp_3.u16[2] = tmp_1.u16[1];
|
| 1590 |
+
tmp_3.u16[3] = tmp_2.u16[1];
|
| 1591 |
+
tmp_3.u16[4] = tmp_1.u16[2];
|
| 1592 |
+
tmp_3.u16[5] = tmp_2.u16[2];
|
| 1593 |
+
tmp_3.u16[6] = tmp_1.u16[3];
|
| 1594 |
+
tmp_3.u16[7] = tmp_2.u16[3];
|
| 1595 |
+
|
| 1596 |
+
vec = tmp_3.u32x4;
|
| 1597 |
+
}
|
| 1598 |
+
|
| 1599 |
+
#ifdef ENABLE_BF16
|
| 1600 |
+
template<>
|
| 1601 |
+
__device__ __inline__ void
|
| 1602 |
+
vec_from_smem_transpose(bf16_4_t& vec, __nv_bfloat16* smem, int transpose_idx, int smem_pitch)
|
| 1603 |
+
{
|
| 1604 |
+
union {
|
| 1605 |
+
uint32_t u32;
|
| 1606 |
+
__nv_bfloat16 bf16[2];
|
| 1607 |
+
} tmp_1, tmp_2;
|
| 1608 |
+
tmp_1.u32 = *reinterpret_cast<uint32_t*>(&smem[transpose_idx]);
|
| 1609 |
+
tmp_2.u32 = *reinterpret_cast<uint32_t*>(&smem[smem_pitch + transpose_idx]);
|
| 1610 |
+
|
| 1611 |
+
vec.x = __nv_bfloat162{tmp_1.bf16[0], tmp_2.bf16[0]};
|
| 1612 |
+
vec.y = __nv_bfloat162{tmp_1.bf16[1], tmp_2.bf16[1]};
|
| 1613 |
+
}
|
| 1614 |
+
|
| 1615 |
+
template<>
|
| 1616 |
+
__device__ __inline__ void
|
| 1617 |
+
vec_from_smem_transpose(bf16_8_t& vec, __nv_bfloat16* smem, int transpose_idx, int smem_pitch)
|
| 1618 |
+
{
|
| 1619 |
+
union {
|
| 1620 |
+
uint64_t u64;
|
| 1621 |
+
__nv_bfloat16 bf16[4];
|
| 1622 |
+
} tmp_1, tmp_2;
|
| 1623 |
+
tmp_1.u64 = *reinterpret_cast<uint64_t*>(&smem[transpose_idx]);
|
| 1624 |
+
tmp_2.u64 = *reinterpret_cast<uint64_t*>(&smem[smem_pitch + transpose_idx]);
|
| 1625 |
+
|
| 1626 |
+
vec.x = __nv_bfloat162{tmp_1.bf16[0], tmp_2.bf16[0]};
|
| 1627 |
+
vec.y = __nv_bfloat162{tmp_1.bf16[1], tmp_2.bf16[1]};
|
| 1628 |
+
vec.z = __nv_bfloat162{tmp_1.bf16[2], tmp_2.bf16[2]};
|
| 1629 |
+
vec.w = __nv_bfloat162{tmp_1.bf16[3], tmp_2.bf16[3]};
|
| 1630 |
+
}
|
| 1631 |
+
#endif // ENABLE_BF16
|
| 1632 |
+
|
| 1633 |
+
template<>
|
| 1634 |
+
__device__ __inline__ void vec_from_smem_transpose(float4& vec, float* smem, int transpose_idx, int smem_pitch)
|
| 1635 |
+
{
|
| 1636 |
+
vec.x = smem[transpose_idx];
|
| 1637 |
+
vec.z = smem[transpose_idx + 1];
|
| 1638 |
+
vec.y = smem[smem_pitch + transpose_idx];
|
| 1639 |
+
vec.w = smem[smem_pitch + transpose_idx + 1];
|
| 1640 |
+
}
|
| 1641 |
+
|
| 1642 |
+
template<>
|
| 1643 |
+
__device__ __inline__ void vec_from_smem_transpose(uint32_t& vec, half* smem, int transpose_idx, int smem_pitch)
|
| 1644 |
+
{
|
| 1645 |
+
union {
|
| 1646 |
+
uint32_t u32;
|
| 1647 |
+
half u16[2];
|
| 1648 |
+
} tmp;
|
| 1649 |
+
tmp.u16[0] = smem[transpose_idx];
|
| 1650 |
+
tmp.u16[1] = smem[smem_pitch + transpose_idx];
|
| 1651 |
+
|
| 1652 |
+
vec = tmp.u32;
|
| 1653 |
+
}
|
| 1654 |
+
|
| 1655 |
+
#ifdef ENABLE_BF16
|
| 1656 |
+
template<>
|
| 1657 |
+
__device__ __inline__ void
|
| 1658 |
+
vec_from_smem_transpose(__nv_bfloat162& vec, __nv_bfloat16* smem, int transpose_idx, int smem_pitch)
|
| 1659 |
+
{
|
| 1660 |
+
vec.x = smem[transpose_idx];
|
| 1661 |
+
vec.y = smem[smem_pitch + transpose_idx];
|
| 1662 |
+
}
|
| 1663 |
+
#endif
|
| 1664 |
+
|
| 1665 |
+
template<>
|
| 1666 |
+
__device__ __inline__ void vec_from_smem_transpose(float2& vec, float* smem, int transpose_idx, int smem_pitch)
|
| 1667 |
+
{
|
| 1668 |
+
vec.x = smem[transpose_idx];
|
| 1669 |
+
vec.y = smem[smem_pitch + transpose_idx];
|
| 1670 |
+
}
|
| 1671 |
+
|
| 1672 |
+
template<typename Vec_T, typename T>
|
| 1673 |
+
__device__ __inline__ void write_smem_transpose(const Vec_T& vec, T* smem, int transpose_idx, int smem_pitch);
|
| 1674 |
+
|
| 1675 |
+
template<>
|
| 1676 |
+
__device__ __inline__ void write_smem_transpose(const float& vec, float* smem, int transpose_idx, int smem_pitch)
|
| 1677 |
+
{
|
| 1678 |
+
return;
|
| 1679 |
+
}
|
| 1680 |
+
|
| 1681 |
+
template<>
|
| 1682 |
+
__device__ __inline__ void write_smem_transpose(const uint4& vec, uint16_t* smem, int transpose_idx, int smem_pitch)
|
| 1683 |
+
{
|
| 1684 |
+
union {
|
| 1685 |
+
uint64_t u64;
|
| 1686 |
+
uint16_t u16[4];
|
| 1687 |
+
} tmp_1, tmp_2;
|
| 1688 |
+
|
| 1689 |
+
union {
|
| 1690 |
+
uint4 u32x4;
|
| 1691 |
+
uint16_t u16[8];
|
| 1692 |
+
} tmp_3;
|
| 1693 |
+
tmp_3.u32x4 = vec;
|
| 1694 |
+
tmp_1.u16[0] = tmp_3.u16[0];
|
| 1695 |
+
tmp_2.u16[0] = tmp_3.u16[1];
|
| 1696 |
+
tmp_1.u16[1] = tmp_3.u16[2];
|
| 1697 |
+
tmp_2.u16[1] = tmp_3.u16[3];
|
| 1698 |
+
tmp_1.u16[2] = tmp_3.u16[4];
|
| 1699 |
+
tmp_2.u16[2] = tmp_3.u16[5];
|
| 1700 |
+
tmp_1.u16[3] = tmp_3.u16[6];
|
| 1701 |
+
tmp_2.u16[3] = tmp_3.u16[7];
|
| 1702 |
+
|
| 1703 |
+
*reinterpret_cast<uint64_t*>(&smem[transpose_idx]) = tmp_1.u64;
|
| 1704 |
+
*reinterpret_cast<uint64_t*>(&smem[smem_pitch + transpose_idx]) = tmp_2.u64;
|
| 1705 |
+
}
|
| 1706 |
+
|
| 1707 |
+
template<>
|
| 1708 |
+
__device__ __inline__ void write_smem_transpose(const uint2& vec, uint16_t* smem, int transpose_idx, int smem_pitch)
|
| 1709 |
+
{
|
| 1710 |
+
union {
|
| 1711 |
+
uint32_t u32;
|
| 1712 |
+
uint16_t u16[2];
|
| 1713 |
+
} tmp_1, tmp_2;
|
| 1714 |
+
|
| 1715 |
+
union {
|
| 1716 |
+
uint2 u32x2;
|
| 1717 |
+
uint16_t u16[4];
|
| 1718 |
+
} tmp_3;
|
| 1719 |
+
tmp_3.u32x2 = vec;
|
| 1720 |
+
tmp_1.u16[0] = tmp_3.u16[0];
|
| 1721 |
+
tmp_2.u16[0] = tmp_3.u16[1];
|
| 1722 |
+
tmp_1.u16[1] = tmp_3.u16[2];
|
| 1723 |
+
tmp_2.u16[1] = tmp_3.u16[3];
|
| 1724 |
+
|
| 1725 |
+
*reinterpret_cast<uint32_t*>(&smem[transpose_idx]) = tmp_1.u32;
|
| 1726 |
+
*reinterpret_cast<uint32_t*>(&smem[smem_pitch + transpose_idx]) = tmp_2.u32;
|
| 1727 |
+
}
|
| 1728 |
+
|
| 1729 |
+
template<>
|
| 1730 |
+
__device__ __inline__ void write_smem_transpose(const uint32_t& vec, uint16_t* smem, int transpose_idx, int smem_pitch)
|
| 1731 |
+
{
|
| 1732 |
+
union {
|
| 1733 |
+
uint32_t u32;
|
| 1734 |
+
uint16_t u16[2];
|
| 1735 |
+
} tmp;
|
| 1736 |
+
tmp.u32 = vec;
|
| 1737 |
+
|
| 1738 |
+
smem[transpose_idx] = tmp.u16[0];
|
| 1739 |
+
smem[smem_pitch + transpose_idx] = tmp.u16[1];
|
| 1740 |
+
}
|
| 1741 |
+
|
| 1742 |
+
template<>
|
| 1743 |
+
__device__ __inline__ void write_smem_transpose(const float4& vec, float* smem, int transpose_idx, int smem_pitch)
|
| 1744 |
+
{
|
| 1745 |
+
smem[transpose_idx] = vec.x;
|
| 1746 |
+
smem[transpose_idx + 1] = vec.z;
|
| 1747 |
+
smem[smem_pitch + transpose_idx] = vec.y;
|
| 1748 |
+
smem[smem_pitch + transpose_idx + 1] = vec.w;
|
| 1749 |
+
}
|
| 1750 |
+
|
| 1751 |
+
template<>
|
| 1752 |
+
__device__ __inline__ void write_smem_transpose(const uint32_t& vec, half* smem, int transpose_idx, int smem_pitch)
|
| 1753 |
+
{
|
| 1754 |
+
union {
|
| 1755 |
+
uint32_t u32;
|
| 1756 |
+
half u16[2];
|
| 1757 |
+
} tmp;
|
| 1758 |
+
|
| 1759 |
+
tmp.u32 = vec;
|
| 1760 |
+
smem[transpose_idx] = tmp.u16[0];
|
| 1761 |
+
smem[smem_pitch + transpose_idx] = tmp.u16[1];
|
| 1762 |
+
}
|
| 1763 |
+
|
| 1764 |
+
#ifdef ENABLE_BF16
|
| 1765 |
+
template<>
|
| 1766 |
+
__device__ __inline__ void
|
| 1767 |
+
write_smem_transpose(const __nv_bfloat162& vec, __nv_bfloat16* smem, int transpose_idx, int smem_pitch)
|
| 1768 |
+
{
|
| 1769 |
+
smem[transpose_idx] = vec.x;
|
| 1770 |
+
smem[smem_pitch + transpose_idx] = vec.y;
|
| 1771 |
+
}
|
| 1772 |
+
|
| 1773 |
+
template<>
|
| 1774 |
+
__device__ __inline__ void
|
| 1775 |
+
write_smem_transpose(const bf16_4_t& vec, __nv_bfloat16* smem, int transpose_idx, int smem_pitch)
|
| 1776 |
+
{
|
| 1777 |
+
write_smem_transpose(reinterpret_cast<const uint2&>(vec), reinterpret_cast<uint16_t*>(smem), transpose_idx, smem_pitch);
|
| 1778 |
+
}
|
| 1779 |
+
|
| 1780 |
+
template<>
|
| 1781 |
+
__device__ __inline__ void
|
| 1782 |
+
write_smem_transpose(const bf16_8_t& vec, __nv_bfloat16* smem, int transpose_idx, int smem_pitch)
|
| 1783 |
+
{
|
| 1784 |
+
write_smem_transpose(reinterpret_cast<const uint4&>(vec), reinterpret_cast<uint16_t*>(smem), transpose_idx, smem_pitch);
|
| 1785 |
+
}
|
| 1786 |
+
#endif
|
| 1787 |
+
|
| 1788 |
+
template<>
|
| 1789 |
+
__device__ __inline__ void write_smem_transpose(const float2& vec, float* smem, int transpose_idx, int smem_pitch)
|
| 1790 |
+
{
|
| 1791 |
+
smem[transpose_idx] = vec.x;
|
| 1792 |
+
smem[smem_pitch + transpose_idx] = vec.y;
|
| 1793 |
+
}
|
| 1794 |
+
|
| 1795 |
+
} // namespace mmha
|
llm-awq/awq/kernels/csrc/attention/ft_attention.cpp
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Adapted from NVIDIA/FasterTransformer and FlashAttention
|
| 2 |
+
|
| 3 |
+
#include <torch/extension.h>
|
| 4 |
+
#include "ATen/cuda/CUDAContext.h"
|
| 5 |
+
#include <c10/cuda/CUDAGuard.h>
|
| 6 |
+
|
| 7 |
+
#include "ft_attention.h"
|
| 8 |
+
#include "decoder_masked_multihead_attention.h"
|
| 9 |
+
|
| 10 |
+
#define CHECK_DEVICE(x) TORCH_CHECK(x.device().type() == torch::kCUDA, #x " must be on CUDA")
|
| 11 |
+
#define CHECK_SHAPE(x, ...) TORCH_CHECK(x.sizes() == torch::IntArrayRef({__VA_ARGS__}), #x " must have shape (" #__VA_ARGS__ ")")
|
| 12 |
+
#define CHECK_CONTIGUOUS(x) TORCH_CHECK(x.is_contiguous(), #x " must be contiguous")
|
| 13 |
+
|
| 14 |
+
#define DISPATCH_FLOAT_AND_HALF_AND_BF16(TYPE, NAME, ...) \
|
| 15 |
+
if (TYPE == at::ScalarType::Half) { \
|
| 16 |
+
using scalar_t = at::Half; \
|
| 17 |
+
__VA_ARGS__(); \
|
| 18 |
+
} else if (TYPE == at::ScalarType::BFloat16) { \
|
| 19 |
+
using scalar_t = at::BFloat16; \
|
| 20 |
+
__VA_ARGS__(); \
|
| 21 |
+
} else if (TYPE == at::ScalarType::Float) { \
|
| 22 |
+
using scalar_t = float; \
|
| 23 |
+
__VA_ARGS__(); \
|
| 24 |
+
} else { \
|
| 25 |
+
AT_ERROR(#NAME, " not implemented for type '", toString(TYPE), "'"); \
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
template<typename T>
|
| 29 |
+
void masked_multihead_attention(const Masked_multihead_attention_params<T>& params,
|
| 30 |
+
const cudaStream_t& stream);
|
| 31 |
+
|
| 32 |
+
template<typename T>
|
| 33 |
+
void cross_multihead_attention(const Masked_multihead_attention_params<T>& params,
|
| 34 |
+
const cudaStream_t& stream);
|
| 35 |
+
|
| 36 |
+
template<typename T>
|
| 37 |
+
struct SATypeConverter {
|
| 38 |
+
using Type = T;
|
| 39 |
+
};
|
| 40 |
+
|
| 41 |
+
template<>
|
| 42 |
+
struct SATypeConverter<at::Half> {
|
| 43 |
+
using Type = uint16_t;
|
| 44 |
+
};
|
| 45 |
+
|
| 46 |
+
template<>
|
| 47 |
+
struct SATypeConverter<at::BFloat16> {
|
| 48 |
+
using Type = __nv_bfloat16;
|
| 49 |
+
};
|
| 50 |
+
|
| 51 |
+
template <typename T>
|
| 52 |
+
void set_params(Masked_multihead_attention_params<T> ¶ms,
|
| 53 |
+
const size_t batch_size,
|
| 54 |
+
const size_t nheads,
|
| 55 |
+
const size_t nheads_kv,
|
| 56 |
+
const size_t memory_max_seqlen,
|
| 57 |
+
const size_t headdim,
|
| 58 |
+
const int timestep,
|
| 59 |
+
const int rotary_embedding_dim,
|
| 60 |
+
const float rotary_base,
|
| 61 |
+
const float rotary_scale,
|
| 62 |
+
const bool neox_rotary_style,
|
| 63 |
+
const int qkv_batch_stride,
|
| 64 |
+
T *q_ptr,
|
| 65 |
+
T *k_ptr,
|
| 66 |
+
T *v_ptr,
|
| 67 |
+
T *k_cache_ptr,
|
| 68 |
+
T *v_cache_ptr,
|
| 69 |
+
int *length_per_sample,
|
| 70 |
+
float *alibi_slopes_ptr,
|
| 71 |
+
T *out_ptr) {
|
| 72 |
+
// Reset the parameters
|
| 73 |
+
memset(¶ms, 0, sizeof(params));
|
| 74 |
+
params.q = q_ptr;
|
| 75 |
+
params.k = k_ptr;
|
| 76 |
+
params.v = v_ptr;
|
| 77 |
+
params.q_bias = nullptr;
|
| 78 |
+
params.k_bias = nullptr;
|
| 79 |
+
params.v_bias = nullptr;
|
| 80 |
+
params.k_cache = k_cache_ptr;
|
| 81 |
+
params.v_cache = v_cache_ptr;
|
| 82 |
+
params.linear_bias_slopes = alibi_slopes_ptr;
|
| 83 |
+
params.out = out_ptr;
|
| 84 |
+
params.cache_indir = nullptr;
|
| 85 |
+
params.stride = qkv_batch_stride;
|
| 86 |
+
params.batch_size = batch_size;
|
| 87 |
+
params.beam_width = 1;
|
| 88 |
+
params.memory_max_len = memory_max_seqlen;
|
| 89 |
+
params.num_heads = nheads;
|
| 90 |
+
params.num_kv_heads = nheads_kv;
|
| 91 |
+
params.hidden_size_per_head = headdim;
|
| 92 |
+
params.rotary_embedding_dim = rotary_embedding_dim;
|
| 93 |
+
params.rotary_base = rotary_base;
|
| 94 |
+
params.rotary_scale = rotary_scale;
|
| 95 |
+
params.neox_rotary_style = neox_rotary_style;
|
| 96 |
+
params.timestep = timestep;
|
| 97 |
+
params.inv_sqrt_dh = 1.f / sqrt(float(headdim));
|
| 98 |
+
params.total_padding_tokens = nullptr;
|
| 99 |
+
params.masked_tokens = nullptr;
|
| 100 |
+
params.prefix_prompt_lengths = nullptr;
|
| 101 |
+
params.max_prefix_prompt_length = 0;
|
| 102 |
+
params.relative_attention_bias = nullptr;
|
| 103 |
+
params.relative_attention_bias_stride = 0;
|
| 104 |
+
params.cross_attention_out = nullptr;
|
| 105 |
+
params.max_decoder_seq_len = 0;
|
| 106 |
+
params.is_return_cross_attentions = false;
|
| 107 |
+
params.finished = nullptr;
|
| 108 |
+
params.memory_length_per_sample = nullptr;
|
| 109 |
+
params.length_per_sample = length_per_sample;
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
torch::Tensor single_query_attention(const torch::Tensor q,
|
| 113 |
+
const torch::Tensor k,
|
| 114 |
+
const torch::Tensor v,
|
| 115 |
+
torch::Tensor k_cache,
|
| 116 |
+
torch::Tensor v_cache,
|
| 117 |
+
c10::optional<const torch::Tensor> length_per_sample_,
|
| 118 |
+
c10::optional<const torch::Tensor> alibi_slopes_,
|
| 119 |
+
const int timestep,
|
| 120 |
+
const int rotary_embedding_dim,
|
| 121 |
+
const float rotary_base,
|
| 122 |
+
const float rotary_scale,
|
| 123 |
+
// neox_rotary_style = not interleaved
|
| 124 |
+
const bool neox_rotary_style) {
|
| 125 |
+
CHECK_DEVICE(q); CHECK_DEVICE(k); CHECK_DEVICE(v); CHECK_DEVICE(k_cache); CHECK_DEVICE(v_cache);
|
| 126 |
+
int batch_size = v_cache.size(0);
|
| 127 |
+
int nheads = q.size(1);
|
| 128 |
+
int nheads_kv = v_cache.size(1);
|
| 129 |
+
int memory_max_seqlen = v_cache.size(2);
|
| 130 |
+
int headdim = v_cache.size(3);
|
| 131 |
+
CHECK_SHAPE(q, batch_size, nheads, headdim);
|
| 132 |
+
CHECK_SHAPE(k, batch_size, nheads_kv, headdim);
|
| 133 |
+
CHECK_SHAPE(v, batch_size, nheads_kv, headdim);
|
| 134 |
+
CHECK_SHAPE(v_cache, batch_size, nheads_kv, memory_max_seqlen, headdim);
|
| 135 |
+
// k_cache shape: [B, H, Dh/x, L, x] where x=8 for fp16 and x=4 for fp32
|
| 136 |
+
int packsize = k_cache.dtype() == torch::kFloat32 ? 4 : 8;
|
| 137 |
+
CHECK_SHAPE(k_cache, batch_size, nheads_kv, headdim / packsize, memory_max_seqlen, packsize);
|
| 138 |
+
TORCH_CHECK(q.stride(2) == 1 && q.stride(1) == headdim);
|
| 139 |
+
TORCH_CHECK(k.stride(2) == 1 && k.stride(1) == headdim);
|
| 140 |
+
TORCH_CHECK(v.stride(2) == 1 && v.stride(1) == headdim);
|
| 141 |
+
// TORCH_CHECK(q.stride(0) == k.stride(0) && q.stride(0) == v.stride(0));
|
| 142 |
+
CHECK_CONTIGUOUS(v_cache); CHECK_CONTIGUOUS(k_cache);
|
| 143 |
+
|
| 144 |
+
if (length_per_sample_.has_value()) {
|
| 145 |
+
auto length_per_sample = length_per_sample_.value();
|
| 146 |
+
CHECK_DEVICE(length_per_sample);
|
| 147 |
+
CHECK_SHAPE(length_per_sample, batch_size);
|
| 148 |
+
CHECK_CONTIGUOUS(length_per_sample);
|
| 149 |
+
TORCH_CHECK(length_per_sample.dtype() == torch::kInt32);
|
| 150 |
+
}
|
| 151 |
+
|
| 152 |
+
if (alibi_slopes_.has_value()) {
|
| 153 |
+
auto alibi_slopes = alibi_slopes_.value();
|
| 154 |
+
CHECK_DEVICE(alibi_slopes);
|
| 155 |
+
CHECK_SHAPE(alibi_slopes, nheads);
|
| 156 |
+
CHECK_CONTIGUOUS(alibi_slopes);
|
| 157 |
+
TORCH_CHECK(alibi_slopes.dtype() == torch::kFloat32);
|
| 158 |
+
}
|
| 159 |
+
|
| 160 |
+
// Otherwise the kernel will be launched from cuda:0 device
|
| 161 |
+
// Cast to char to avoid compiler warning about narrowing
|
| 162 |
+
at::cuda::CUDAGuard device_guard{(char)q.get_device()};
|
| 163 |
+
|
| 164 |
+
torch::Tensor out = torch::empty_like(q);
|
| 165 |
+
|
| 166 |
+
DISPATCH_FLOAT_AND_HALF_AND_BF16(q.scalar_type(), "single_query_attention", [&] {
|
| 167 |
+
using DataType = typename SATypeConverter<scalar_t>::Type;
|
| 168 |
+
Masked_multihead_attention_params<DataType> params;
|
| 169 |
+
set_params(params, batch_size, nheads, nheads_kv, memory_max_seqlen, headdim,
|
| 170 |
+
timestep, rotary_embedding_dim, rotary_base, rotary_scale, neox_rotary_style, q.stride(0),
|
| 171 |
+
reinterpret_cast<DataType*>(q.data_ptr()),
|
| 172 |
+
reinterpret_cast<DataType*>(k.data_ptr()),
|
| 173 |
+
reinterpret_cast<DataType*>(v.data_ptr()),
|
| 174 |
+
reinterpret_cast<DataType*>(k_cache.data_ptr()),
|
| 175 |
+
reinterpret_cast<DataType*>(v_cache.data_ptr()),
|
| 176 |
+
length_per_sample_.has_value()
|
| 177 |
+
? length_per_sample_.value().data_ptr<int>() : nullptr,
|
| 178 |
+
alibi_slopes_.has_value()
|
| 179 |
+
? alibi_slopes_.value().data_ptr<float>(): nullptr,
|
| 180 |
+
reinterpret_cast<DataType*>(out.data_ptr()));
|
| 181 |
+
auto stream = at::cuda::getCurrentCUDAStream();
|
| 182 |
+
masked_multihead_attention(params, stream);
|
| 183 |
+
});
|
| 184 |
+
return out;
|
| 185 |
+
}
|
llm-awq/awq/kernels/csrc/attention/ft_attention.h
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
#include <torch/extension.h>
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
torch::Tensor single_query_attention(const torch::Tensor q,
|
| 6 |
+
const torch::Tensor k,
|
| 7 |
+
const torch::Tensor v,
|
| 8 |
+
torch::Tensor k_cache,
|
| 9 |
+
torch::Tensor v_cache,
|
| 10 |
+
c10::optional<const torch::Tensor> length_per_sample_,
|
| 11 |
+
c10::optional<const torch::Tensor> alibi_slopes_,
|
| 12 |
+
const int timestep,
|
| 13 |
+
const int rotary_embedding_dim = 0,
|
| 14 |
+
const float rotary_base = 10000.0f,
|
| 15 |
+
const float rotary_scale = 1.0f,
|
| 16 |
+
const bool neox_rotary_style=true);
|
llm-awq/awq/kernels/csrc/layernorm/layernorm.cu
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*
|
| 2 |
+
|
| 3 |
+
Adapted from NVIDIA FasterTransformer:
|
| 4 |
+
https://github.com/NVIDIA/FasterTransformer/blob/main/src/fastertransformer/kernels/layernorm_kernels.cu
|
| 5 |
+
|
| 6 |
+
*/
|
| 7 |
+
|
| 8 |
+
#include <torch/extension.h>
|
| 9 |
+
#include <cuda_fp16.h>
|
| 10 |
+
#include "reduction.cuh"
|
| 11 |
+
#include "layernorm.h"
|
| 12 |
+
#include <cuda_runtime.h>
|
| 13 |
+
#include <c10/cuda/CUDAGuard.h>
|
| 14 |
+
|
| 15 |
+
#define DISPATCH_PYTORCH_DTYPE_TO_CTYPE_FP16(pytorch_dtype, c_type, ...) \
|
| 16 |
+
if (pytorch_dtype == at::ScalarType::Half) { \
|
| 17 |
+
using c_type = half; \
|
| 18 |
+
__VA_ARGS__ \
|
| 19 |
+
} else if (pytorch_dtype == at::ScalarType::BFloat16) { \
|
| 20 |
+
using c_type = nv_bfloat16; \
|
| 21 |
+
__VA_ARGS__ \
|
| 22 |
+
} else { \
|
| 23 |
+
std::ostringstream oss; \
|
| 24 |
+
oss << __PRETTY_FUNCTION__ << " failed to dispatch data type " << pytorch_dtype; \
|
| 25 |
+
TORCH_CHECK(false, oss.str()); \
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
static inline __device__ float to_float(half src)
|
| 29 |
+
{
|
| 30 |
+
return __half2float(src);
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
static inline __device__ float to_float(float src)
|
| 34 |
+
{
|
| 35 |
+
return src;
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
template<typename T>
|
| 39 |
+
__global__ void generalT5LayerNorm(
|
| 40 |
+
const T* __restrict input, const T* __restrict gamma, T* output, const float layernorm_eps, int m, int n)
|
| 41 |
+
{
|
| 42 |
+
// layernorm module in the T5 style No bias and no subtraction of mean.
|
| 43 |
+
const int tid = threadIdx.x;
|
| 44 |
+
|
| 45 |
+
__shared__ float s_variance;
|
| 46 |
+
float variance = 0.0f;
|
| 47 |
+
|
| 48 |
+
float local_var_sum = 0.0f;
|
| 49 |
+
for (int i = tid; i < n; i += blockDim.x) {
|
| 50 |
+
float diff = to_float(__ldg(&input[blockIdx.x * n + i]));
|
| 51 |
+
local_var_sum += diff * diff;
|
| 52 |
+
}
|
| 53 |
+
variance = blockReduceSum(local_var_sum);
|
| 54 |
+
|
| 55 |
+
if (threadIdx.x == 0) {
|
| 56 |
+
s_variance = rsqrtf(variance / (float)n + layernorm_eps);
|
| 57 |
+
}
|
| 58 |
+
__syncthreads();
|
| 59 |
+
|
| 60 |
+
for (int i = tid; i < n; i += blockDim.x) {
|
| 61 |
+
output[blockIdx.x * n + i] =
|
| 62 |
+
clamp_inf_for_half<T>((to_float(input[blockIdx.x * n + i]) * s_variance) * to_float(__ldg(&gamma[i])));
|
| 63 |
+
}
|
| 64 |
+
}
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
template<typename T>
|
| 68 |
+
void invokeGeneralT5LayerNorm(T* out,
|
| 69 |
+
const T* input,
|
| 70 |
+
const T* gamma,
|
| 71 |
+
// const T* beta,
|
| 72 |
+
const float layernorm_eps,
|
| 73 |
+
const int m,
|
| 74 |
+
const int n)
|
| 75 |
+
{
|
| 76 |
+
dim3 grid(m);
|
| 77 |
+
dim3 block(min(n, 1024));
|
| 78 |
+
|
| 79 |
+
/* For general cases, n is equal to hidden_units, e.g., 512/1024.
|
| 80 |
+
Since we have warp shuffle inside the code, block.x % 32 should be 0.
|
| 81 |
+
*/
|
| 82 |
+
if (n % 32 != 0) {
|
| 83 |
+
block.x = 1024;
|
| 84 |
+
}
|
| 85 |
+
|
| 86 |
+
block.x = block.x / (4 / sizeof(T)); // if using half, only need half of block.x
|
| 87 |
+
|
| 88 |
+
/* should pay attention to the rsqrt precision*/
|
| 89 |
+
generalT5LayerNorm<T><<<grid, block>>>(input, gamma, out, layernorm_eps, m, n); // For gpt-3
|
| 90 |
+
}
|
| 91 |
+
|
| 92 |
+
template void invokeGeneralT5LayerNorm(half* out,
|
| 93 |
+
const half* input,
|
| 94 |
+
const half* gamma,
|
| 95 |
+
// const half* beta,
|
| 96 |
+
const float layernorm_eps,
|
| 97 |
+
const int m,
|
| 98 |
+
const int n);
|
| 99 |
+
|
| 100 |
+
template void invokeGeneralT5LayerNorm(float* out,
|
| 101 |
+
const float* input,
|
| 102 |
+
const float* gamma,
|
| 103 |
+
// const half* beta,
|
| 104 |
+
const float layernorm_eps,
|
| 105 |
+
const int m,
|
| 106 |
+
const int n);
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
// input b, n, c
|
| 111 |
+
void layernorm_forward_cuda(
|
| 112 |
+
torch::Tensor _input,
|
| 113 |
+
torch::Tensor _gamma,
|
| 114 |
+
torch::Tensor _out,
|
| 115 |
+
float eps)
|
| 116 |
+
{
|
| 117 |
+
int m = _input.size(0) * _input.size(1);
|
| 118 |
+
int n = _input.size(2);
|
| 119 |
+
const at::cuda::OptionalCUDAGuard device_guard(device_of(_input));
|
| 120 |
+
|
| 121 |
+
auto data_type = _input.scalar_type();
|
| 122 |
+
TORCH_CHECK(_gamma.scalar_type() == data_type);
|
| 123 |
+
TORCH_CHECK(_out.scalar_type() == data_type);
|
| 124 |
+
|
| 125 |
+
DISPATCH_PYTORCH_DTYPE_TO_CTYPE_FP16(data_type, ctype, {
|
| 126 |
+
auto input = reinterpret_cast<ctype*>(_input.data_ptr());
|
| 127 |
+
auto gamma = reinterpret_cast<ctype*>(_gamma.data_ptr());
|
| 128 |
+
auto out = reinterpret_cast<ctype*>(_out.data_ptr());
|
| 129 |
+
invokeGeneralT5LayerNorm(out, input, gamma, eps, m, n);
|
| 130 |
+
});
|
| 131 |
+
}
|
llm-awq/awq/kernels/csrc/position_embedding/pos_encoding.h
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#pragma once
|
| 2 |
+
#include <torch/extension.h>
|
| 3 |
+
|
| 4 |
+
void rotary_embedding_neox(
|
| 5 |
+
torch::Tensor& positions,
|
| 6 |
+
torch::Tensor& query,
|
| 7 |
+
torch::Tensor& key,
|
| 8 |
+
int head_size,
|
| 9 |
+
torch::Tensor& cos_sin_cache);
|
llm-awq/awq/kernels/csrc/pybind.cpp
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include <pybind11/pybind11.h>
|
| 2 |
+
#include <torch/extension.h>
|
| 3 |
+
#include "attention/ft_attention.h"
|
| 4 |
+
#include "layernorm/layernorm.h"
|
| 5 |
+
#include "quantization/gemm_cuda.h"
|
| 6 |
+
#include "quantization/gemv_cuda.h"
|
| 7 |
+
#include "quantization_new/gemm/gemm_cuda.h"
|
| 8 |
+
#include "quantization_new/gemv/gemv_cuda.h"
|
| 9 |
+
#include "position_embedding/pos_encoding.h"
|
| 10 |
+
#include "rope_new/fused_rope_with_pos.h"
|
| 11 |
+
#include "w8a8/w8a8_gemm_cuda.h"
|
| 12 |
+
#include "w8a8/quantization.h"
|
| 13 |
+
#include "w8a8/layernorm.h"
|
| 14 |
+
#include "w8a8/act.h"
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m)
|
| 18 |
+
{
|
| 19 |
+
m.def("layernorm_forward_cuda", &layernorm_forward_cuda, "FasterTransformer layernorm kernel");
|
| 20 |
+
m.def("gemm_forward_cuda", &gemm_forward_cuda, "Quantized GEMM kernel.");
|
| 21 |
+
m.def("gemv_forward_cuda", &gemv_forward_cuda, "Quantized GEMV kernel.");
|
| 22 |
+
m.def("gemm_forward_cuda_new", &gemm_forward_cuda_new, "New quantized GEMM kernel.");
|
| 23 |
+
m.def("gemv_forward_cuda_new", &gemv_forward_cuda_new, "New quantized GEMV kernel.");
|
| 24 |
+
m.def("rotary_embedding_neox", &rotary_embedding_neox, "Apply GPT-NeoX style rotary embedding to query and key");
|
| 25 |
+
m.def("single_query_attention", &single_query_attention, "Attention with a single query",
|
| 26 |
+
py::arg("q"), py::arg("k"), py::arg("v"), py::arg("k_cache"), py::arg("v_cache"),
|
| 27 |
+
py::arg("length_per_sample_"), py::arg("alibi_slopes_"), py::arg("timestep"), py::arg("rotary_embedding_dim")=0,
|
| 28 |
+
py::arg("rotary_base")=10000.0f, py::arg("rotary_scale")=1.0f, py::arg("neox_rotary_style")=true);
|
| 29 |
+
m.def("fused_rope_with_pos_forward_func", &fused_rope_with_pos_forward_func,"Fused rope forward function with B,S,D embedding");
|
| 30 |
+
m.def("w8a8_gemm_forward_cuda", &w8a8_gemm_forward_cuda, "our w8a8 gemm kernel");
|
| 31 |
+
m.def("w8a8_gemm_fuse_bias_forward_cuda", &w8a8_gemm_fuse_bias_forward_cuda, "our w8a8 gemm fused bias kernel");
|
| 32 |
+
m.def("invoke_quant", &invoke_quant, "fp16->int8 quantization");
|
| 33 |
+
m.def("rms_norm_general", &rms_norm_general, py::arg("out"), py::arg("input"),
|
| 34 |
+
py::arg("weight"), py::arg("bias"),py::arg("scaling"), py::arg("epsilon"), py::arg("use_per_token_quant") = true,
|
| 35 |
+
"Apply Root Mean Square (RMS) Normalization to the input tensor (TRTLLM kernel).");
|
| 36 |
+
m.def("silu_and_mul", &silu_and_mul, "Activation function.");
|
| 37 |
+
m.def("gelu_and_quant",&gelu_and_quant, "Apply gelu act and quant output");
|
| 38 |
+
}
|
llm-awq/awq/kernels/csrc/quantization/gemv_cuda.cu
ADDED
|
@@ -0,0 +1,247 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// Inspired by https://github.com/ankan-ban/llama_cu_awq
|
| 2 |
+
/*
|
| 3 |
+
|
| 4 |
+
@article{lin2023awq,
|
| 5 |
+
title={AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration},
|
| 6 |
+
author={Lin, Ji and Tang, Jiaming and Tang, Haotian and Yang, Shang and Dang, Xingyu and Han, Song},
|
| 7 |
+
journal={arXiv},
|
| 8 |
+
year={2023}
|
| 9 |
+
}
|
| 10 |
+
|
| 11 |
+
*/
|
| 12 |
+
|
| 13 |
+
#include <cuda_fp16.h>
|
| 14 |
+
#include <stdio.h>
|
| 15 |
+
#include <torch/extension.h>
|
| 16 |
+
#include "gemv_cuda.h"
|
| 17 |
+
#define VECTORIZE_FACTOR 8
|
| 18 |
+
#define Q_VECTORIZE_FACTOR 8
|
| 19 |
+
#define PACK_FACTOR 8
|
| 20 |
+
#define WARP_SIZE 32
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
// Reduce sum within the warp using the tree reduction algorithm.
|
| 24 |
+
__device__ __forceinline__ float warp_reduce_sum(float sum) {
|
| 25 |
+
#pragma unroll
|
| 26 |
+
for(int i = 4; i >= 0; i--){
|
| 27 |
+
sum += __shfl_down_sync(0xffffffff, sum, 1<<i);
|
| 28 |
+
}
|
| 29 |
+
/*
|
| 30 |
+
// Equivalent to the following tree reduction implementation:
|
| 31 |
+
sum += __shfl_down_sync(0xffffffff, sum, 16);
|
| 32 |
+
sum += __shfl_down_sync(0xffffffff, sum, 8);
|
| 33 |
+
sum += __shfl_down_sync(0xffffffff, sum, 4);
|
| 34 |
+
sum += __shfl_down_sync(0xffffffff, sum, 2);
|
| 35 |
+
sum += __shfl_down_sync(0xffffffff, sum, 1);
|
| 36 |
+
*/
|
| 37 |
+
return sum;
|
| 38 |
+
}
|
| 39 |
+
|
| 40 |
+
__device__ __forceinline__ int make_divisible(int c, int divisor){
|
| 41 |
+
return (c + divisor - 1) / divisor;
|
| 42 |
+
}
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
/*
|
| 46 |
+
Computes GEMV (group_size = 64).
|
| 47 |
+
|
| 48 |
+
Args:
|
| 49 |
+
inputs: vector of shape [batch_size, IC];
|
| 50 |
+
weight: matrix of shape [OC, IC / 8];
|
| 51 |
+
output: vector of shape [OC];
|
| 52 |
+
zeros: matrix of shape [OC, IC / group_size / 8];
|
| 53 |
+
scaling_factors: matrix of shape [OC, IC / group_size];
|
| 54 |
+
|
| 55 |
+
Notes:
|
| 56 |
+
One cannot infer group_size from the shape of scaling factors.
|
| 57 |
+
the second dimension is rounded up to a multiple of PACK_FACTOR.
|
| 58 |
+
*/
|
| 59 |
+
__global__ void gemv_kernel_g64(
|
| 60 |
+
const float4* _inputs, const uint32_t* weight, const uint32_t* zeros, const half* scaling_factors, half* _outputs,
|
| 61 |
+
const int IC, const int OC){
|
| 62 |
+
const int group_size = 64;
|
| 63 |
+
float psum = 0;
|
| 64 |
+
const int batch_idx = blockIdx.z;
|
| 65 |
+
const int oc_idx = blockIdx.y * blockDim.y + threadIdx.y;
|
| 66 |
+
const float4* inputs = _inputs + batch_idx * IC / PACK_FACTOR;
|
| 67 |
+
half* outputs = _outputs + batch_idx * OC;
|
| 68 |
+
// This is essentially zeros_w.
|
| 69 |
+
const int num_groups_packed = make_divisible(make_divisible(IC / group_size, PACK_FACTOR), 2) * 2;
|
| 70 |
+
const int weight_w = IC / PACK_FACTOR;
|
| 71 |
+
// TODO (Haotian): zeros_w is incorrect, after fixing we got misaligned address
|
| 72 |
+
const int zeros_w = make_divisible(make_divisible(IC / group_size, PACK_FACTOR), 2) * 2;
|
| 73 |
+
// consistent with input shape
|
| 74 |
+
const int sf_w = make_divisible(make_divisible(IC / group_size, PACK_FACTOR), 2) * 2 * PACK_FACTOR;
|
| 75 |
+
// if(blockIdx.x == 0 && blockIdx.y == 0 && threadIdx.x == 0 && threadIdx.y == 0) printf("%d %d %d %d %d\n", IC, group_size, PACK_FACTOR, zeros_w, sf_w);
|
| 76 |
+
// tile size: 4 OC x 1024 IC per iter
|
| 77 |
+
for(int packed_group_idx = 0; packed_group_idx < num_groups_packed / 2; packed_group_idx++){
|
| 78 |
+
// 1024 numbers in one iteration across warp. Need 1024 / group_size zeros.
|
| 79 |
+
uint64_t packed_zeros = *reinterpret_cast<const uint64_t*>(zeros + oc_idx * zeros_w + packed_group_idx * 2);
|
| 80 |
+
uint32_t packed_weights[4];
|
| 81 |
+
// use float4 to load weights, each thread load 32 int4 numbers (1 x float4)
|
| 82 |
+
*((float4*)(packed_weights)) = *((float4*)(weight + oc_idx * weight_w + packed_group_idx * (WARP_SIZE * 4) + threadIdx.x * 4));
|
| 83 |
+
// load scaling factors
|
| 84 |
+
// g64: two threads -> 64 numbers -> 1 group; 1 warp = 16 groups.
|
| 85 |
+
float scaling_factor = __half2float(scaling_factors[oc_idx * sf_w + packed_group_idx * 16 + (threadIdx.x / 2)]);
|
| 86 |
+
float current_zeros = (float)((packed_zeros >> (threadIdx.x / 2 * 4)) & 0xF);
|
| 87 |
+
int inputs_ptr_delta = packed_group_idx * WARP_SIZE * 4 + threadIdx.x * 4;
|
| 88 |
+
const float4* inputs_ptr = inputs + inputs_ptr_delta;
|
| 89 |
+
// multiply 32 weights with 32 inputs
|
| 90 |
+
#pragma unroll
|
| 91 |
+
for (int ic_0 = 0; ic_0 < 4; ic_0++){
|
| 92 |
+
// iterate over different uint32_t packed_weights in this loop
|
| 93 |
+
uint32_t current_packed_weight = packed_weights[ic_0];
|
| 94 |
+
half packed_inputs[PACK_FACTOR];
|
| 95 |
+
// each thread load 8 inputs, starting index is packed_group_idx * 128 * 8 (because each iter loads 128*8)
|
| 96 |
+
if (inputs_ptr_delta + ic_0 < IC / PACK_FACTOR) {
|
| 97 |
+
*((float4*)packed_inputs) = *(inputs_ptr + ic_0);
|
| 98 |
+
#pragma unroll
|
| 99 |
+
for (int ic_1 = 0; ic_1 < PACK_FACTOR; ic_1++){
|
| 100 |
+
// iterate over 8 numbers packed within each uint32_t number
|
| 101 |
+
float current_single_weight_fp = (float)(current_packed_weight & 0xF);
|
| 102 |
+
float dequantized_weight = scaling_factor * (current_single_weight_fp - current_zeros);
|
| 103 |
+
//if(blockIdx.x == 0 && blockIdx.y == 0 && threadIdx.x == 0 && threadIdx.y == 0 && ic_0 == 0 && ic_1 == 0 && packed_group_idx == 0) printf("%f %f %f %f %X %X\n", dequantized_weight, current_single_weight_fp, scaling_factor, current_zeros, current_packed_weight, packed_zeros);
|
| 104 |
+
psum += dequantized_weight * __half2float(packed_inputs[ic_1]);
|
| 105 |
+
current_packed_weight = current_packed_weight >> 4;
|
| 106 |
+
}
|
| 107 |
+
}
|
| 108 |
+
}
|
| 109 |
+
}
|
| 110 |
+
psum = warp_reduce_sum(psum);
|
| 111 |
+
if (threadIdx.x == 0) {
|
| 112 |
+
outputs[oc_idx] = __float2half(psum);
|
| 113 |
+
}
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
|
| 117 |
+
/*
|
| 118 |
+
Computes GEMV (group_size = 128).
|
| 119 |
+
|
| 120 |
+
Args:
|
| 121 |
+
inputs: vector of shape [batch_size, IC];
|
| 122 |
+
weight: matrix of shape [OC, IC / 8];
|
| 123 |
+
output: vector of shape [OC];
|
| 124 |
+
zeros: matrix of shape [OC, IC / group_size / 8];
|
| 125 |
+
scaling_factors: matrix of shape [OC, IC / group_size];
|
| 126 |
+
|
| 127 |
+
Notes:
|
| 128 |
+
One cannot infer group_size from the shape of scaling factors.
|
| 129 |
+
the second dimension is rounded up to a multiple of PACK_FACTOR.
|
| 130 |
+
*/
|
| 131 |
+
__global__ void gemv_kernel_g128(
|
| 132 |
+
const float4* _inputs, const uint32_t* weight, const uint32_t* zeros, const half* scaling_factors, half* _outputs,
|
| 133 |
+
const int IC, const int OC){
|
| 134 |
+
const int group_size = 128;
|
| 135 |
+
float psum = 0;
|
| 136 |
+
const int batch_idx = blockIdx.z;
|
| 137 |
+
const int oc_idx = blockIdx.y * blockDim.y + threadIdx.y;
|
| 138 |
+
const float4* inputs = _inputs + batch_idx * IC / PACK_FACTOR;
|
| 139 |
+
half* outputs = _outputs + batch_idx * OC;
|
| 140 |
+
const int num_groups_packed = make_divisible(IC / group_size, PACK_FACTOR);
|
| 141 |
+
const int weight_w = IC / PACK_FACTOR;
|
| 142 |
+
// TODO (Haotian): zeros_w is incorrect, after fixing we got misaligned address
|
| 143 |
+
const int zeros_w = make_divisible(IC / group_size, PACK_FACTOR);
|
| 144 |
+
// consistent with input shape
|
| 145 |
+
const int sf_w = make_divisible(IC / group_size, PACK_FACTOR) * PACK_FACTOR;
|
| 146 |
+
//if(blockIdx.x == 0 && blockIdx.y == 0 && threadIdx.x == 0 && threadIdx.y == 0) printf("%d %d %d %d\n", IC, group_size, PACK_FACTOR, zeros_w);
|
| 147 |
+
// tile size: 4 OC x 1024 IC per iter
|
| 148 |
+
for(int packed_group_idx = 0; packed_group_idx < num_groups_packed; packed_group_idx++){
|
| 149 |
+
// 1024 numbers in one iteration across warp. Need 1024 / group_size zeros.
|
| 150 |
+
uint32_t packed_zeros = *(zeros + oc_idx * zeros_w + packed_group_idx);
|
| 151 |
+
uint32_t packed_weights[4];
|
| 152 |
+
// use float4 to load weights, each thread load 32 int4 numbers (1 x float4)
|
| 153 |
+
*((float4*)(packed_weights)) = *((float4*)(weight + oc_idx * weight_w + packed_group_idx * (WARP_SIZE * 4) + threadIdx.x * 4));
|
| 154 |
+
// load scaling factors
|
| 155 |
+
// g128: four threads -> 128 numbers -> 1 group; 1 warp = 8 groups.
|
| 156 |
+
float scaling_factor = __half2float(scaling_factors[oc_idx * sf_w + packed_group_idx * 8 + (threadIdx.x / 4)]);
|
| 157 |
+
float current_zeros = (float)((packed_zeros >> (threadIdx.x / 4 * 4)) & 0xF);
|
| 158 |
+
int inputs_ptr_delta = packed_group_idx * WARP_SIZE * 4 + threadIdx.x * 4;
|
| 159 |
+
const float4* inputs_ptr = inputs + inputs_ptr_delta;
|
| 160 |
+
// multiply 32 weights with 32 inputs
|
| 161 |
+
#pragma unroll
|
| 162 |
+
for (int ic_0 = 0; ic_0 < 4; ic_0++){
|
| 163 |
+
// iterate over different uint32_t packed_weights in this loop
|
| 164 |
+
uint32_t current_packed_weight = packed_weights[ic_0];
|
| 165 |
+
half packed_inputs[PACK_FACTOR];
|
| 166 |
+
// each thread load 8 inputs, starting index is packed_group_idx * 128 * 8 (because each iter loads 128*8)
|
| 167 |
+
if (inputs_ptr_delta + ic_0 < IC / PACK_FACTOR) {
|
| 168 |
+
*((float4*)packed_inputs) = *(inputs_ptr + ic_0);
|
| 169 |
+
#pragma unroll
|
| 170 |
+
for (int ic_1 = 0; ic_1 < PACK_FACTOR; ic_1++){
|
| 171 |
+
// iterate over 8 numbers packed within each uint32_t number
|
| 172 |
+
float current_single_weight_fp = (float)(current_packed_weight & 0xF);
|
| 173 |
+
float dequantized_weight = scaling_factor * (current_single_weight_fp - current_zeros);
|
| 174 |
+
//if(blockIdx.x == 0 && blockIdx.y == 0 && threadIdx.x == 0 && threadIdx.y == 0 && ic_0 == 0 && ic_1 == 0 && packed_group_idx == 0) printf("%f %f %f %f %X %X\n", dequantized_weight, current_single_weight_fp, scaling_factor, current_zeros, current_packed_weight, packed_zeros);
|
| 175 |
+
psum += dequantized_weight * __half2float(packed_inputs[ic_1]);
|
| 176 |
+
current_packed_weight = current_packed_weight >> 4;
|
| 177 |
+
}
|
| 178 |
+
}
|
| 179 |
+
}
|
| 180 |
+
}
|
| 181 |
+
psum = warp_reduce_sum(psum);
|
| 182 |
+
if (threadIdx.x == 0) {
|
| 183 |
+
outputs[oc_idx] = __float2half(psum);
|
| 184 |
+
}
|
| 185 |
+
}
|
| 186 |
+
|
| 187 |
+
|
| 188 |
+
/*
|
| 189 |
+
Computes GEMV (PyTorch interface).
|
| 190 |
+
|
| 191 |
+
Args:
|
| 192 |
+
_in_feats: tensor of shape [B, IC];
|
| 193 |
+
_kernel: int tensor of shape [OC, IC // 8];
|
| 194 |
+
_zeros: int tensor of shape [OC, IC // G // 8];
|
| 195 |
+
_scaling_factors: tensor of shape [OC, IC // G];
|
| 196 |
+
blockDim_x: size of thread block, dimension x, where blockDim_x * workload_per_thread = IC;
|
| 197 |
+
blockDim_y: size of thread block, dimension y, where blockDim_y * gridDim_y = OC;
|
| 198 |
+
|
| 199 |
+
Returns:
|
| 200 |
+
out_feats: tensor of shape [B, OC];
|
| 201 |
+
*/
|
| 202 |
+
torch::Tensor gemv_forward_cuda(
|
| 203 |
+
torch::Tensor _in_feats,
|
| 204 |
+
torch::Tensor _kernel,
|
| 205 |
+
torch::Tensor _scaling_factors,
|
| 206 |
+
torch::Tensor _zeros,
|
| 207 |
+
int group_size)
|
| 208 |
+
{
|
| 209 |
+
int num_in_feats = _in_feats.size(0);
|
| 210 |
+
int num_in_channels = _in_feats.size(1);
|
| 211 |
+
// int kernel_volume = _out_in_map.size(1);
|
| 212 |
+
auto in_feats = reinterpret_cast<float4*>(_in_feats.data_ptr<at::Half>());
|
| 213 |
+
auto kernel = reinterpret_cast<uint32_t*>(_kernel.data_ptr<int>());
|
| 214 |
+
auto zeros = reinterpret_cast<uint32_t*>(_zeros.data_ptr<int>());
|
| 215 |
+
auto scaling_factors = reinterpret_cast<half*>(_scaling_factors.data_ptr<at::Half>());
|
| 216 |
+
// auto out_in_map = _out_in_map.data_ptr<int>();
|
| 217 |
+
auto options =
|
| 218 |
+
torch::TensorOptions().dtype(_in_feats.dtype()).device(_in_feats.device());
|
| 219 |
+
// kernel is [OC, IC]
|
| 220 |
+
at::Tensor _out_feats = torch::empty({num_in_feats, _kernel.size(0)}, options);
|
| 221 |
+
int num_out_feats = _out_feats.size(-2);
|
| 222 |
+
int num_out_channels = _out_feats.size(-1);
|
| 223 |
+
auto out_feats = reinterpret_cast<half*>(_out_feats.data_ptr<at::Half>());
|
| 224 |
+
int blockDim_z = num_out_feats;
|
| 225 |
+
dim3 num_blocks(1, num_out_channels / 4, num_out_feats);
|
| 226 |
+
dim3 num_threads(32, 4);
|
| 227 |
+
if (group_size == 64)
|
| 228 |
+
{
|
| 229 |
+
gemv_kernel_g64<<<num_blocks, num_threads>>>(
|
| 230 |
+
// pointers
|
| 231 |
+
in_feats, kernel, zeros, scaling_factors, out_feats,
|
| 232 |
+
// constants
|
| 233 |
+
num_in_channels, num_out_channels
|
| 234 |
+
);
|
| 235 |
+
}
|
| 236 |
+
else if (group_size == 128)
|
| 237 |
+
{
|
| 238 |
+
gemv_kernel_g128<<<num_blocks, num_threads>>>(
|
| 239 |
+
// pointers
|
| 240 |
+
in_feats, kernel, zeros, scaling_factors, out_feats,
|
| 241 |
+
// constants
|
| 242 |
+
num_in_channels, num_out_channels
|
| 243 |
+
);
|
| 244 |
+
}
|
| 245 |
+
return _out_feats;
|
| 246 |
+
;}
|
| 247 |
+
|
llm-awq/awq/kernels/setup.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from setuptools import find_packages, setup
|
| 2 |
+
from torch.utils.cpp_extension import BuildExtension, CUDAExtension, CppExtension
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
extra_compile_args = {
|
| 6 |
+
"cxx": ["-g", "-O3", "-fopenmp", "-lgomp", "-std=c++17", "-DENABLE_BF16"],
|
| 7 |
+
"nvcc": [
|
| 8 |
+
"-O3",
|
| 9 |
+
"-std=c++17",
|
| 10 |
+
"-DENABLE_BF16", # TODO
|
| 11 |
+
"-U__CUDA_NO_HALF_OPERATORS__",
|
| 12 |
+
"-U__CUDA_NO_HALF_CONVERSIONS__",
|
| 13 |
+
"-U__CUDA_NO_BFLOAT16_OPERATORS__",
|
| 14 |
+
"-U__CUDA_NO_BFLOAT16_CONVERSIONS__",
|
| 15 |
+
"-U__CUDA_NO_BFLOAT162_OPERATORS__",
|
| 16 |
+
"-U__CUDA_NO_BFLOAT162_CONVERSIONS__",
|
| 17 |
+
"--expt-relaxed-constexpr",
|
| 18 |
+
"--expt-extended-lambda",
|
| 19 |
+
"--use_fast_math",
|
| 20 |
+
"--threads=8",
|
| 21 |
+
],
|
| 22 |
+
}
|
| 23 |
+
|
| 24 |
+
setup(
|
| 25 |
+
name="awq_inference_engine",
|
| 26 |
+
packages=find_packages(),
|
| 27 |
+
ext_modules=[
|
| 28 |
+
CUDAExtension(
|
| 29 |
+
name="awq_inference_engine",
|
| 30 |
+
sources=[
|
| 31 |
+
"csrc/pybind.cpp",
|
| 32 |
+
"csrc/quantization/gemm_cuda_gen.cu",
|
| 33 |
+
"csrc/quantization/gemv_cuda.cu",
|
| 34 |
+
"csrc/quantization_new/gemv/gemv_cuda.cu",
|
| 35 |
+
"csrc/quantization_new/gemm/gemm_cuda.cu",
|
| 36 |
+
"csrc/layernorm/layernorm.cu",
|
| 37 |
+
"csrc/position_embedding/pos_encoding_kernels.cu",
|
| 38 |
+
"csrc/attention/ft_attention.cpp",
|
| 39 |
+
"csrc/attention/decoder_masked_multihead_attention.cu",
|
| 40 |
+
"csrc/rope_new/fused_rope_with_pos.cu",
|
| 41 |
+
"csrc/w8a8/w8a8_gemm_cuda.cu",
|
| 42 |
+
"csrc/w8a8/quantization.cu",
|
| 43 |
+
"csrc/w8a8/act.cu",
|
| 44 |
+
"csrc/w8a8/layernorm.cu"
|
| 45 |
+
],
|
| 46 |
+
extra_compile_args=extra_compile_args,
|
| 47 |
+
),
|
| 48 |
+
],
|
| 49 |
+
cmdclass={"build_ext": BuildExtension},
|
| 50 |
+
install_requires=["torch"],
|
| 51 |
+
)
|
llm-awq/tinychat/models/falcon.py
ADDED
|
@@ -0,0 +1,304 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
| 2 |
+
# This software may be used and distributed according to the terms of the GNU General Public License version 3.
|
| 3 |
+
|
| 4 |
+
from typing import Optional, Tuple
|
| 5 |
+
from dataclasses import dataclass
|
| 6 |
+
import math
|
| 7 |
+
|
| 8 |
+
import torch
|
| 9 |
+
from torch import nn
|
| 10 |
+
import torch.nn.functional as F
|
| 11 |
+
import awq_inference_engine
|
| 12 |
+
|
| 13 |
+
import tinychat.utils.constants
|
| 14 |
+
|
| 15 |
+
max_batch_size = tinychat.utils.constants.max_batch_size
|
| 16 |
+
max_seq_len = tinychat.utils.constants.max_seq_len
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
# rotary pos emb helpers (torch.jit.script does not seem to support staticmethod...)
|
| 20 |
+
def rotate_half(x):
|
| 21 |
+
x1, x2 = x[..., : x.shape[-1] // 2], x[..., x.shape[-1] // 2 :]
|
| 22 |
+
return torch.cat(
|
| 23 |
+
(-x2, x1), dim=x1.ndim - 1
|
| 24 |
+
) # dim=-1 triggers a bug in torch < 1.8.0
|
| 25 |
+
|
| 26 |
+
|
| 27 |
+
class RotaryEmbedding(nn.Module):
|
| 28 |
+
"""Implementation of RotaryEmbedding from GPT-NeoX.
|
| 29 |
+
This implementation is design to operate on queries and keys that are compatible with
|
| 30 |
+
[batch_size, n_heads_per_partition, seq_len, head_dim] (e.g. MinGPTAttention format).
|
| 31 |
+
"""
|
| 32 |
+
|
| 33 |
+
def __init__(
|
| 34 |
+
self,
|
| 35 |
+
head_dim: int,
|
| 36 |
+
base=10000,
|
| 37 |
+
):
|
| 38 |
+
super().__init__()
|
| 39 |
+
inv_freq = 1.0 / (base ** (torch.arange(0, head_dim, 2).float() / head_dim))
|
| 40 |
+
self.register_buffer("inv_freq", inv_freq, persistent=False)
|
| 41 |
+
self.head_dim = head_dim
|
| 42 |
+
self.seq_len_cached = None
|
| 43 |
+
self.batch_size_cached = None
|
| 44 |
+
self.cos_cached: torch.Tensor | None = None
|
| 45 |
+
self.sin_cached: torch.Tensor | None = None
|
| 46 |
+
|
| 47 |
+
def cos_sin(
|
| 48 |
+
self,
|
| 49 |
+
seq_len: int,
|
| 50 |
+
device="cuda",
|
| 51 |
+
dtype=torch.bfloat16,
|
| 52 |
+
) -> torch.Tensor:
|
| 53 |
+
if seq_len != self.seq_len_cached:
|
| 54 |
+
self.seq_len_cached = seq_len
|
| 55 |
+
t = torch.arange(seq_len, device=device).type_as(self.inv_freq)
|
| 56 |
+
freqs = torch.einsum("i,j->ij", t, self.inv_freq)
|
| 57 |
+
emb = torch.cat((freqs, freqs), dim=-1).to(device)
|
| 58 |
+
|
| 59 |
+
if dtype in [torch.float16, torch.bfloat16]:
|
| 60 |
+
emb = emb.float()
|
| 61 |
+
|
| 62 |
+
self.cos_cached = emb.cos()[None, :, :]
|
| 63 |
+
self.sin_cached = emb.sin()[None, :, :]
|
| 64 |
+
|
| 65 |
+
self.cos_cached = self.cos_cached.type(dtype)
|
| 66 |
+
self.sin_cached = self.sin_cached.type(dtype)
|
| 67 |
+
|
| 68 |
+
return self.cos_cached, self.sin_cached
|
| 69 |
+
|
| 70 |
+
def forward(self, _q, _k):
|
| 71 |
+
batch, seq_len, num_heads, head_dim = _q.shape
|
| 72 |
+
q = _q.permute(0, 2, 1, 3).contiguous().reshape(-1, seq_len, head_dim)
|
| 73 |
+
k = _k.permute(0, 2, 1, 3).contiguous().reshape(-1, seq_len, head_dim)
|
| 74 |
+
cos, sin = self.cos_sin(seq_len, q.device, q.dtype)
|
| 75 |
+
return (q * cos) + (rotate_half(q) * sin), (k * cos) + (rotate_half(k) * sin)
|
| 76 |
+
|
| 77 |
+
|
| 78 |
+
class FalconAttentionFused(nn.Module):
|
| 79 |
+
def __init__(self, args):
|
| 80 |
+
super().__init__()
|
| 81 |
+
self.args = args
|
| 82 |
+
self.n_local_heads = args.n_head
|
| 83 |
+
self.head_dim = args.hidden_size // args.n_head
|
| 84 |
+
|
| 85 |
+
self.query_key_value = nn.Linear(
|
| 86 |
+
args.hidden_size,
|
| 87 |
+
args.n_head * self.head_dim + 2 * self.head_dim,
|
| 88 |
+
bias=False,
|
| 89 |
+
)
|
| 90 |
+
|
| 91 |
+
self.dense = nn.Linear(
|
| 92 |
+
args.n_head * self.head_dim,
|
| 93 |
+
args.hidden_size,
|
| 94 |
+
bias=False,
|
| 95 |
+
)
|
| 96 |
+
|
| 97 |
+
# following fastertransformer definition
|
| 98 |
+
|
| 99 |
+
self.cache_v = (
|
| 100 |
+
torch.zeros(
|
| 101 |
+
(
|
| 102 |
+
max_batch_size,
|
| 103 |
+
1,
|
| 104 |
+
max_seq_len,
|
| 105 |
+
self.head_dim,
|
| 106 |
+
)
|
| 107 |
+
)
|
| 108 |
+
.cuda()
|
| 109 |
+
.half()
|
| 110 |
+
) # added to half
|
| 111 |
+
# 8: pack 8 fp16 in FT, if fp32 then use 4
|
| 112 |
+
self.cache_k = (
|
| 113 |
+
torch.zeros(
|
| 114 |
+
(
|
| 115 |
+
max_batch_size,
|
| 116 |
+
1,
|
| 117 |
+
self.head_dim // 8,
|
| 118 |
+
max_seq_len,
|
| 119 |
+
8,
|
| 120 |
+
)
|
| 121 |
+
)
|
| 122 |
+
.cuda()
|
| 123 |
+
.half()
|
| 124 |
+
) # added to half
|
| 125 |
+
|
| 126 |
+
self.rotary_emb = RotaryEmbedding(self.head_dim)
|
| 127 |
+
self.rope_theta = args.rope_theta
|
| 128 |
+
self.rope_scaling = args.rope_scaling
|
| 129 |
+
if self.rope_scaling is None:
|
| 130 |
+
self.rope_scaling = 1.0
|
| 131 |
+
else:
|
| 132 |
+
self.rope_scaling = 1.0 / self.rope_scaling["factor"]
|
| 133 |
+
|
| 134 |
+
def forward(
|
| 135 |
+
self,
|
| 136 |
+
x: torch.Tensor,
|
| 137 |
+
start_pos: int,
|
| 138 |
+
mask: Optional[torch.Tensor],
|
| 139 |
+
):
|
| 140 |
+
bsz, seqlen, _ = x.shape
|
| 141 |
+
|
| 142 |
+
xqkv = self.query_key_value(x)
|
| 143 |
+
xqkv = xqkv.view(bsz, seqlen, self.n_local_heads + 2, self.head_dim)
|
| 144 |
+
xq = xqkv[:, :, :-2]
|
| 145 |
+
xk = xqkv[:, :, [-2]]
|
| 146 |
+
xv = xqkv[:, :, [-1]]
|
| 147 |
+
|
| 148 |
+
if seqlen > 1:
|
| 149 |
+
xq = xq.view(bsz, seqlen, self.n_local_heads, self.head_dim)
|
| 150 |
+
xk = xk.view(bsz, seqlen, 1, self.head_dim)
|
| 151 |
+
xv = xv.view(bsz, seqlen, 1, self.head_dim)
|
| 152 |
+
|
| 153 |
+
xq, xk = self.rotary_emb(xq, xk)
|
| 154 |
+
xq = (
|
| 155 |
+
xq.reshape(bsz, self.n_local_heads, seqlen, self.head_dim)
|
| 156 |
+
.permute(0, 2, 1, 3)
|
| 157 |
+
.contiguous()
|
| 158 |
+
)
|
| 159 |
+
xk = (
|
| 160 |
+
xk.reshape(bsz, 1, seqlen, self.head_dim)
|
| 161 |
+
.permute(0, 2, 1, 3)
|
| 162 |
+
.contiguous()
|
| 163 |
+
)
|
| 164 |
+
|
| 165 |
+
self.cache_k = self.cache_k.to(xq)
|
| 166 |
+
self.cache_v = self.cache_v.to(xq)
|
| 167 |
+
|
| 168 |
+
values_store = xv.transpose(2, 1)
|
| 169 |
+
keys_store = (
|
| 170 |
+
xk.reshape(bsz, seqlen, 1, self.head_dim // 8, 8)
|
| 171 |
+
.permute(0, 2, 3, 1, 4)
|
| 172 |
+
.contiguous()
|
| 173 |
+
)
|
| 174 |
+
|
| 175 |
+
self.cache_v[:bsz, :, start_pos : start_pos + seqlen, :] = values_store
|
| 176 |
+
self.cache_k[:bsz, :, :, start_pos : start_pos + seqlen, :] = keys_store
|
| 177 |
+
|
| 178 |
+
keys = xk
|
| 179 |
+
values = xv
|
| 180 |
+
|
| 181 |
+
xq = xq.transpose(1, 2)
|
| 182 |
+
keys = keys.transpose(1, 2)
|
| 183 |
+
values = values.transpose(1, 2)
|
| 184 |
+
scores = torch.matmul(xq, keys.transpose(2, 3)) / math.sqrt(self.head_dim)
|
| 185 |
+
if mask is not None:
|
| 186 |
+
scores = scores + mask # (bs, n_local_heads, slen, cache_len + slen)
|
| 187 |
+
scores = F.softmax(scores.float(), dim=-1).type_as(xq)
|
| 188 |
+
output = torch.matmul(scores, values) # (bs, n_local_heads, slen, head_dim)
|
| 189 |
+
output = output.transpose(1, 2).contiguous().view(bsz, seqlen, -1)
|
| 190 |
+
else:
|
| 191 |
+
# xq = xq[:, 0, :, :]
|
| 192 |
+
# xk = xk[:, 0, :, :]
|
| 193 |
+
# xv = xv[:, 0, :, :]
|
| 194 |
+
xq = xq.view(bsz, self.n_local_heads, self.head_dim)
|
| 195 |
+
xk = xk.view(bsz, 1, self.head_dim)
|
| 196 |
+
xv = xv.view(bsz, 1, self.head_dim)
|
| 197 |
+
|
| 198 |
+
output = awq_inference_engine.single_query_attention(
|
| 199 |
+
xq,
|
| 200 |
+
xk,
|
| 201 |
+
xv,
|
| 202 |
+
self.cache_k,
|
| 203 |
+
self.cache_v,
|
| 204 |
+
None,
|
| 205 |
+
# alibi position encodings
|
| 206 |
+
None,
|
| 207 |
+
start_pos,
|
| 208 |
+
self.head_dim,
|
| 209 |
+
self.rope_theta,
|
| 210 |
+
self.rope_scaling,
|
| 211 |
+
True,
|
| 212 |
+
)
|
| 213 |
+
output = output.reshape(bsz, 1, -1)
|
| 214 |
+
|
| 215 |
+
return self.dense(output)
|
| 216 |
+
|
| 217 |
+
|
| 218 |
+
class FalconMLP(nn.Module):
|
| 219 |
+
def __init__(
|
| 220 |
+
self,
|
| 221 |
+
dim: int,
|
| 222 |
+
):
|
| 223 |
+
super().__init__()
|
| 224 |
+
self.dense_h_to_4h = nn.Linear(dim, 4 * dim, bias=False)
|
| 225 |
+
self.act = nn.GELU()
|
| 226 |
+
self.dense_4h_to_h = nn.Linear(4 * dim, dim, bias=False)
|
| 227 |
+
|
| 228 |
+
def forward(self, x):
|
| 229 |
+
x = self.act(self.dense_h_to_4h(x))
|
| 230 |
+
x = self.dense_4h_to_h(x)
|
| 231 |
+
return x
|
| 232 |
+
|
| 233 |
+
|
| 234 |
+
class TransformerBlock(nn.Module):
|
| 235 |
+
def __init__(self, layer_id: int, args):
|
| 236 |
+
super().__init__()
|
| 237 |
+
self.n_heads = args.n_head
|
| 238 |
+
self.dim = args.hidden_size
|
| 239 |
+
self.head_dim = args.hidden_size // args.n_head
|
| 240 |
+
self.self_attention = FalconAttentionFused(args)
|
| 241 |
+
self.mlp = FalconMLP(dim=args.hidden_size)
|
| 242 |
+
self.layer_id = layer_id
|
| 243 |
+
self.input_layernorm = nn.LayerNorm(
|
| 244 |
+
args.hidden_size, eps=args.layer_norm_epsilon
|
| 245 |
+
)
|
| 246 |
+
# self.post_attention_layernorm = nn.LayerNorm(args.dim, eps=args.norm_eps)
|
| 247 |
+
|
| 248 |
+
def forward(
|
| 249 |
+
self,
|
| 250 |
+
x: torch.Tensor,
|
| 251 |
+
start_pos: int,
|
| 252 |
+
mask: Optional[torch.Tensor],
|
| 253 |
+
):
|
| 254 |
+
layernorm_output = self.input_layernorm(x)
|
| 255 |
+
h_attn = x + self.self_attention.forward(layernorm_output, start_pos, mask)
|
| 256 |
+
h_mlp = self.mlp(layernorm_output)
|
| 257 |
+
out = h_attn + h_mlp
|
| 258 |
+
return out
|
| 259 |
+
|
| 260 |
+
|
| 261 |
+
class Transformer(nn.Module):
|
| 262 |
+
def __init__(self, params):
|
| 263 |
+
super().__init__()
|
| 264 |
+
self.params = params
|
| 265 |
+
self.vocab_size = params.vocab_size
|
| 266 |
+
self.n_layers = params.n_layer
|
| 267 |
+
|
| 268 |
+
self.word_embeddings = nn.Embedding(params.vocab_size, params.hidden_size)
|
| 269 |
+
|
| 270 |
+
self.h = torch.nn.ModuleList()
|
| 271 |
+
for layer_id in range(params.n_layer):
|
| 272 |
+
self.h.append(TransformerBlock(layer_id, params))
|
| 273 |
+
|
| 274 |
+
self.ln_f = nn.LayerNorm(params.hidden_size, eps=params.layer_norm_epsilon)
|
| 275 |
+
|
| 276 |
+
@torch.inference_mode()
|
| 277 |
+
def forward(self, tokens: torch.Tensor, start_pos: int):
|
| 278 |
+
_bsz, seqlen = tokens.shape
|
| 279 |
+
h = self.word_embeddings(tokens)
|
| 280 |
+
|
| 281 |
+
mask = None
|
| 282 |
+
if seqlen > 1:
|
| 283 |
+
mask = torch.full(
|
| 284 |
+
(1, 1, seqlen, seqlen), float("-inf"), device=tokens.device
|
| 285 |
+
)
|
| 286 |
+
mask = torch.triu(mask, diagonal=start_pos + 1).type_as(h)
|
| 287 |
+
for layer in self.h:
|
| 288 |
+
h = layer(h, start_pos, mask)
|
| 289 |
+
h = self.ln_f(h)
|
| 290 |
+
return h
|
| 291 |
+
|
| 292 |
+
|
| 293 |
+
class FalconForCausalLM(nn.Module):
|
| 294 |
+
def __init__(self, params):
|
| 295 |
+
super().__init__()
|
| 296 |
+
self.config = params
|
| 297 |
+
self.transformer = Transformer(params)
|
| 298 |
+
self.lm_head = nn.Linear(params.hidden_size, params.vocab_size, bias=False)
|
| 299 |
+
|
| 300 |
+
@torch.inference_mode()
|
| 301 |
+
def forward(self, tokens: torch.Tensor, start_pos: int):
|
| 302 |
+
h = self.transformer(tokens, start_pos)
|
| 303 |
+
output = self.lm_head(h) # only compute last logits
|
| 304 |
+
return output.float()
|
llm-awq/tinychat/models/internvl3.py
ADDED
|
@@ -0,0 +1,383 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from collections import defaultdict, deque
|
| 3 |
+
from typing import Dict, List, Optional, Tuple, Union, Any
|
| 4 |
+
import warnings
|
| 5 |
+
from time import time
|
| 6 |
+
|
| 7 |
+
import torch
|
| 8 |
+
import torch.utils.checkpoint
|
| 9 |
+
from torch import nn
|
| 10 |
+
from torch.nn import CrossEntropyLoss
|
| 11 |
+
|
| 12 |
+
import transformers
|
| 13 |
+
from transformers import (AutoConfig,
|
| 14 |
+
AutoModel,
|
| 15 |
+
AutoTokenizer,
|
| 16 |
+
GenerationConfig,
|
| 17 |
+
PretrainedConfig,
|
| 18 |
+
PreTrainedModel)
|
| 19 |
+
from transformers.modeling_outputs import CausalLMOutputWithPast
|
| 20 |
+
from transformers.modeling_utils import PreTrainedModel
|
| 21 |
+
from transformers.utils import ModelOutput, logging
|
| 22 |
+
from transformers import modeling_utils
|
| 23 |
+
|
| 24 |
+
from .internvl.configuration_internvl import InternVisionConfig, InternVLChatConfig
|
| 25 |
+
from .internvl.internvit import InternVisionModel
|
| 26 |
+
from .internvl.conversation import get_conv_template
|
| 27 |
+
from .internvl.media import load_image, load_video
|
| 28 |
+
|
| 29 |
+
from llava.media import Image, Video
|
| 30 |
+
|
| 31 |
+
from .qwen2 import Qwen2ForCausalLM
|
| 32 |
+
from .llama import LlamaForCausalLM
|
| 33 |
+
|
| 34 |
+
try:
|
| 35 |
+
import flash_attn
|
| 36 |
+
has_flash_attn = True
|
| 37 |
+
except ImportError:
|
| 38 |
+
print('FlashAttention2 is not installed.')
|
| 39 |
+
has_flash_attn = False
|
| 40 |
+
|
| 41 |
+
def skip(*args, **kwargs):
|
| 42 |
+
pass
|
| 43 |
+
|
| 44 |
+
torch.nn.init.kaiming_uniform_ = skip
|
| 45 |
+
torch.nn.init.kaiming_normal_ = skip
|
| 46 |
+
torch.nn.init.uniform_ = skip
|
| 47 |
+
torch.nn.init.normal_ = skip
|
| 48 |
+
|
| 49 |
+
modeling_utils._init_weights = False
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
logger = logging.get_logger(__name__)
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
class InternVL3(PreTrainedModel):
|
| 56 |
+
config_class = InternVLChatConfig
|
| 57 |
+
main_input_name = 'pixel_values'
|
| 58 |
+
base_model_prefix = 'language_model'
|
| 59 |
+
_supports_flash_attn_2 = True
|
| 60 |
+
supports_gradient_checkpointing = True
|
| 61 |
+
_no_split_modules = ['InternVisionModel', 'LlamaDecoderLayer', 'Qwen2DecoderLayer']
|
| 62 |
+
|
| 63 |
+
def __init__(self, config: InternVLChatConfig, vision_model=None, language_model=None, use_flash_attn=True):
|
| 64 |
+
super().__init__(config)
|
| 65 |
+
|
| 66 |
+
self.tokenizer = AutoTokenizer.from_pretrained(config.name_or_path, trust_remote_code=True, use_fast=False)
|
| 67 |
+
|
| 68 |
+
image_size = config.force_image_size or config.vision_config.image_size
|
| 69 |
+
patch_size = config.vision_config.patch_size
|
| 70 |
+
self.patch_size = patch_size
|
| 71 |
+
self.select_layer = config.select_layer
|
| 72 |
+
self.template = config.template
|
| 73 |
+
self.num_image_token = int((image_size // patch_size) ** 2 * (config.downsample_ratio ** 2))
|
| 74 |
+
self.downsample_ratio = config.downsample_ratio
|
| 75 |
+
self.ps_version = config.ps_version
|
| 76 |
+
use_flash_attn = use_flash_attn if has_flash_attn else False
|
| 77 |
+
config.vision_config.use_flash_attn = True if use_flash_attn else False
|
| 78 |
+
config.llm_config._attn_implementation = 'flash_attention_2' if use_flash_attn else 'eager'
|
| 79 |
+
|
| 80 |
+
logger.info(f'num_image_token: {self.num_image_token}')
|
| 81 |
+
logger.info(f'ps_version: {self.ps_version}')
|
| 82 |
+
if vision_model is not None:
|
| 83 |
+
self.vision_model = vision_model
|
| 84 |
+
else:
|
| 85 |
+
self.vision_model = InternVisionModel(config.vision_config)
|
| 86 |
+
if language_model is not None:
|
| 87 |
+
self.language_model = language_model
|
| 88 |
+
else:
|
| 89 |
+
if config.llm_config.architectures[0] == 'LlamaForCausalLM':
|
| 90 |
+
self.language_model = LlamaForCausalLM(config.llm_config)
|
| 91 |
+
elif config.llm_config.architectures[0] == 'Qwen2ForCausalLM':
|
| 92 |
+
self.language_model = Qwen2ForCausalLM(config.llm_config)
|
| 93 |
+
else:
|
| 94 |
+
raise NotImplementedError(f'{config.llm_config.architectures[0]} is not implemented.')
|
| 95 |
+
|
| 96 |
+
vit_hidden_size = config.vision_config.hidden_size
|
| 97 |
+
llm_hidden_size = config.llm_config.hidden_size
|
| 98 |
+
|
| 99 |
+
self.mlp1 = nn.Sequential(
|
| 100 |
+
nn.LayerNorm(vit_hidden_size * int(1 / self.downsample_ratio) ** 2),
|
| 101 |
+
nn.Linear(vit_hidden_size * int(1 / self.downsample_ratio) ** 2, llm_hidden_size),
|
| 102 |
+
nn.GELU(),
|
| 103 |
+
nn.Linear(llm_hidden_size, llm_hidden_size)
|
| 104 |
+
)
|
| 105 |
+
|
| 106 |
+
self.img_context_token_id = None
|
| 107 |
+
self.conv_template = get_conv_template(self.template)
|
| 108 |
+
self.system_message = self.conv_template.system_message
|
| 109 |
+
|
| 110 |
+
def freezed_module_patch(self):
|
| 111 |
+
self.vision_model.eval()
|
| 112 |
+
self.language_model.eval()
|
| 113 |
+
self.mlp1.eval()
|
| 114 |
+
|
| 115 |
+
def pixel_shuffle(self, x, scale_factor=0.5):
|
| 116 |
+
n, w, h, c = x.size()
|
| 117 |
+
# N, W, H, C --> N, W, H * scale, C // scale
|
| 118 |
+
x = x.view(n, w, int(h * scale_factor), int(c / scale_factor))
|
| 119 |
+
# N, W, H * scale, C // scale --> N, H * scale, W, C // scale
|
| 120 |
+
x = x.permute(0, 2, 1, 3).contiguous()
|
| 121 |
+
# N, H * scale, W, C // scale --> N, H * scale, W * scale, C // (scale ** 2)
|
| 122 |
+
x = x.view(n, int(h * scale_factor), int(w * scale_factor),
|
| 123 |
+
int(c / (scale_factor * scale_factor)))
|
| 124 |
+
if self.ps_version == 'v1':
|
| 125 |
+
warnings.warn("In ps_version 'v1', the height and width have not been swapped back, "
|
| 126 |
+
'which results in a transposed image.')
|
| 127 |
+
else:
|
| 128 |
+
x = x.permute(0, 2, 1, 3).contiguous()
|
| 129 |
+
return x
|
| 130 |
+
|
| 131 |
+
@torch.inference_mode()
|
| 132 |
+
def prepare_media(self, conversation):
|
| 133 |
+
prompt = conversation[0]["value"]
|
| 134 |
+
media = {"image": [], "video": []}
|
| 135 |
+
for item in prompt:
|
| 136 |
+
if isinstance(item, Image):
|
| 137 |
+
media["image"].append(load_image(item.path))
|
| 138 |
+
if isinstance(item, Video):
|
| 139 |
+
pixel_values, num_patches_list = load_video(item.path)
|
| 140 |
+
media["video"].extend(pixel_values)
|
| 141 |
+
|
| 142 |
+
return media, num_patches_list if media["video"] else None
|
| 143 |
+
|
| 144 |
+
@torch.inference_mode()
|
| 145 |
+
def extract_features(self, pixel_values):
|
| 146 |
+
if self.select_layer == -1:
|
| 147 |
+
vit_embeds = self.vision_model(
|
| 148 |
+
pixel_values=pixel_values,
|
| 149 |
+
output_hidden_states=False,
|
| 150 |
+
return_dict=True).last_hidden_state
|
| 151 |
+
else:
|
| 152 |
+
vit_embeds = self.vision_model(
|
| 153 |
+
pixel_values=pixel_values,
|
| 154 |
+
output_hidden_states=True,
|
| 155 |
+
return_dict=True).hidden_states[self.select_layer]
|
| 156 |
+
vit_embeds = vit_embeds[:, 1:, :]
|
| 157 |
+
|
| 158 |
+
h = w = int(vit_embeds.shape[1] ** 0.5)
|
| 159 |
+
vit_embeds = vit_embeds.reshape(vit_embeds.shape[0], h, w, -1)
|
| 160 |
+
vit_embeds = self.pixel_shuffle(vit_embeds, scale_factor=self.downsample_ratio)
|
| 161 |
+
vit_embeds = vit_embeds.reshape(vit_embeds.shape[0], -1, vit_embeds.shape[-1])
|
| 162 |
+
vit_embeds = self.mlp1(vit_embeds)
|
| 163 |
+
return vit_embeds
|
| 164 |
+
|
| 165 |
+
@torch.inference_mode()
|
| 166 |
+
def _embed(
|
| 167 |
+
self,
|
| 168 |
+
input_ids: torch.Tensor,
|
| 169 |
+
media: Dict[str, List[torch.Tensor]],
|
| 170 |
+
media_config: Dict[str, Dict[str, Any]],
|
| 171 |
+
labels: Optional[torch.Tensor],
|
| 172 |
+
attention_mask: Optional[torch.Tensor],
|
| 173 |
+
):
|
| 174 |
+
attention_mask = (
|
| 175 |
+
attention_mask
|
| 176 |
+
if attention_mask is not None
|
| 177 |
+
else torch.ones_like(input_ids, dtype=torch.bool)
|
| 178 |
+
)
|
| 179 |
+
|
| 180 |
+
if media["image"]:
|
| 181 |
+
pixel_values = torch.cat(media["image"], dim=0).half().cuda()
|
| 182 |
+
elif media["video"]:
|
| 183 |
+
pixel_values = torch.cat(media["video"], dim=0).half().cuda()
|
| 184 |
+
|
| 185 |
+
vit_embeds = self.extract_features(pixel_values)
|
| 186 |
+
|
| 187 |
+
input_embeds = self.language_model.get_input_embeddings()(input_ids)
|
| 188 |
+
B, N, C = input_embeds.shape
|
| 189 |
+
input_embeds = input_embeds.reshape(B * N, C)
|
| 190 |
+
|
| 191 |
+
input_ids = input_ids.reshape(B * N)
|
| 192 |
+
selected = (input_ids == self.img_context_token_id)
|
| 193 |
+
|
| 194 |
+
input_embeds[selected] = input_embeds[selected] * 0.0 + vit_embeds.reshape(-1, C)
|
| 195 |
+
|
| 196 |
+
input_embeds = input_embeds.reshape(B, N, C)
|
| 197 |
+
|
| 198 |
+
return input_embeds, None, attention_mask
|
| 199 |
+
|
| 200 |
+
@torch.inference_mode()
|
| 201 |
+
def benchmark(self, prompt: Union[str, List], quant_llm) -> None:
|
| 202 |
+
media = {"image": [], "video": []}
|
| 203 |
+
question = ""
|
| 204 |
+
for item in prompt:
|
| 205 |
+
if isinstance(item, str):
|
| 206 |
+
question += item
|
| 207 |
+
if isinstance(item, Image):
|
| 208 |
+
media["image"].append(load_image(item.path))
|
| 209 |
+
if isinstance(item, Video):
|
| 210 |
+
pixel_values, num_patches_list = load_video(item.path)
|
| 211 |
+
media["video"].extend(pixel_values)
|
| 212 |
+
|
| 213 |
+
if media["image"]:
|
| 214 |
+
num_patches_list = [image.size(0) for image in media["image"]]
|
| 215 |
+
|
| 216 |
+
if media["image"] and '<image>' not in question:
|
| 217 |
+
question = '<image>\n' + question
|
| 218 |
+
|
| 219 |
+
if media["video"] and '<image>' not in question:
|
| 220 |
+
video_prefix = ''.join([f'Frame{i+1}: <image>\n' for i in range(len(num_patches_list))])
|
| 221 |
+
question = video_prefix + question
|
| 222 |
+
|
| 223 |
+
template = get_conv_template(self.template)
|
| 224 |
+
template.system_message = self.system_message
|
| 225 |
+
eos_token_id = self.tokenizer.convert_tokens_to_ids(template.sep.strip())
|
| 226 |
+
|
| 227 |
+
template.append_message(template.roles[0], question)
|
| 228 |
+
template.append_message(template.roles[1], None)
|
| 229 |
+
query = template.get_prompt()
|
| 230 |
+
|
| 231 |
+
IMG_START_TOKEN = '<img>'
|
| 232 |
+
IMG_END_TOKEN = '</img>'
|
| 233 |
+
IMG_CONTEXT_TOKEN = '<IMG_CONTEXT>'
|
| 234 |
+
|
| 235 |
+
img_context_token_id = self.tokenizer.convert_tokens_to_ids(IMG_CONTEXT_TOKEN)
|
| 236 |
+
self.img_context_token_id = img_context_token_id
|
| 237 |
+
|
| 238 |
+
for num_patches in num_patches_list:
|
| 239 |
+
image_tokens = IMG_START_TOKEN + IMG_CONTEXT_TOKEN * self.num_image_token * num_patches + IMG_END_TOKEN
|
| 240 |
+
query = query.replace('<image>', image_tokens, 1)
|
| 241 |
+
|
| 242 |
+
model_inputs = self.tokenizer(query, return_tensors='pt')
|
| 243 |
+
input_ids = model_inputs['input_ids'].to(self.device)
|
| 244 |
+
attention_mask = model_inputs['attention_mask'].to(self.device)
|
| 245 |
+
|
| 246 |
+
for i in range(10):
|
| 247 |
+
torch.cuda.synchronize()
|
| 248 |
+
t_st = time()
|
| 249 |
+
inputs_embeds, _, attention_mask = self._embed(
|
| 250 |
+
input_ids=input_ids,
|
| 251 |
+
media=media,
|
| 252 |
+
media_config=None,
|
| 253 |
+
labels=None,
|
| 254 |
+
attention_mask=attention_mask
|
| 255 |
+
)
|
| 256 |
+
torch.cuda.synchronize()
|
| 257 |
+
t_ed = time()
|
| 258 |
+
torch.cuda.empty_cache()
|
| 259 |
+
|
| 260 |
+
if media["image"]:
|
| 261 |
+
print(
|
| 262 |
+
"Time of vision tower and others is {:.5f} s for {} images ({} x {} x {})".format(
|
| 263 |
+
t_ed - t_st, sum(num_patches_list), media["image"][0].shape[1], media["image"][0].shape[2], media["image"][0].shape[3]
|
| 264 |
+
)
|
| 265 |
+
)
|
| 266 |
+
elif media["video"]:
|
| 267 |
+
print(
|
| 268 |
+
"Time of vision tower and others is {:.5f} s for {} video frames ({} x {} x {})".format(
|
| 269 |
+
t_ed - t_st, sum(num_patches_list), media["video"][0].shape[1], media["video"][0].shape[2], media["video"][0].shape[3]
|
| 270 |
+
)
|
| 271 |
+
)
|
| 272 |
+
output = self.language_model.benchmark(
|
| 273 |
+
inputs_embeds=inputs_embeds,
|
| 274 |
+
attention_mask=attention_mask,
|
| 275 |
+
quant_llm=quant_llm
|
| 276 |
+
)
|
| 277 |
+
response = self.tokenizer.decode(output[0], skip_special_tokens=True).strip()
|
| 278 |
+
|
| 279 |
+
return response
|
| 280 |
+
|
| 281 |
+
@torch.inference_mode()
|
| 282 |
+
def stream_gen(
|
| 283 |
+
self,
|
| 284 |
+
input_ids,
|
| 285 |
+
media,
|
| 286 |
+
media_cfg,
|
| 287 |
+
start_pos,
|
| 288 |
+
chunk_prefilling,
|
| 289 |
+
quant_llm,
|
| 290 |
+
attention_mask=None,
|
| 291 |
+
) -> str:
|
| 292 |
+
if media is None:
|
| 293 |
+
inputs_embeds = self.language_model.get_input_embeddings()(input_ids ).clone()
|
| 294 |
+
else:
|
| 295 |
+
inputs_embeds, _, _ = self._embed(input_ids, media, None, None, attention_mask)
|
| 296 |
+
|
| 297 |
+
length = inputs_embeds.shape[1]
|
| 298 |
+
if quant_llm:
|
| 299 |
+
out = self.language_model(None, start_pos, inputs_embeds, chunk_prefilling)
|
| 300 |
+
else:
|
| 301 |
+
out = self.language_model.forwardfp16(None, start_pos, inputs_embeds, chunk_prefilling)
|
| 302 |
+
return out, length
|
| 303 |
+
|
| 304 |
+
@torch.inference_mode()
|
| 305 |
+
def forward(
|
| 306 |
+
self,
|
| 307 |
+
pixel_values: torch.FloatTensor,
|
| 308 |
+
input_ids: torch.LongTensor = None,
|
| 309 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 310 |
+
position_ids: Optional[torch.LongTensor] = None,
|
| 311 |
+
image_flags: Optional[torch.LongTensor] = None,
|
| 312 |
+
past_key_values: Optional[List[torch.FloatTensor]] = None,
|
| 313 |
+
labels: Optional[torch.LongTensor] = None,
|
| 314 |
+
use_cache: Optional[bool] = None,
|
| 315 |
+
output_attentions: Optional[bool] = None,
|
| 316 |
+
output_hidden_states: Optional[bool] = None,
|
| 317 |
+
return_dict: Optional[bool] = None,
|
| 318 |
+
) -> Union[Tuple, CausalLMOutputWithPast]:
|
| 319 |
+
return_dict = return_dict if return_dict is not None else self.config.use_return_dict
|
| 320 |
+
|
| 321 |
+
image_flags = image_flags.squeeze(-1)
|
| 322 |
+
input_embeds = self.language_model.get_input_embeddings()(input_ids).clone()
|
| 323 |
+
|
| 324 |
+
vit_embeds = self.extract_feature(pixel_values)
|
| 325 |
+
vit_embeds = vit_embeds[image_flags == 1]
|
| 326 |
+
vit_batch_size = pixel_values.shape[0]
|
| 327 |
+
|
| 328 |
+
B, N, C = input_embeds.shape
|
| 329 |
+
input_embeds = input_embeds.reshape(B * N, C)
|
| 330 |
+
|
| 331 |
+
if torch.distributed.is_initialized() and torch.distributed.get_rank() == 0:
|
| 332 |
+
print(f'dynamic ViT batch size: {vit_batch_size}, images per sample: {vit_batch_size / B}, dynamic token length: {N}')
|
| 333 |
+
|
| 334 |
+
input_ids = input_ids.reshape(B * N)
|
| 335 |
+
selected = (input_ids == self.img_context_token_id)
|
| 336 |
+
try:
|
| 337 |
+
input_embeds[selected] = input_embeds[selected] * 0.0 + vit_embeds.reshape(-1, C)
|
| 338 |
+
except Exception as e:
|
| 339 |
+
vit_embeds = vit_embeds.reshape(-1, C)
|
| 340 |
+
print(f'warning: {e}, input_embeds[selected].shape={input_embeds[selected].shape}, '
|
| 341 |
+
f'vit_embeds.shape={vit_embeds.shape}')
|
| 342 |
+
n_token = min(selected.sum(), vit_embeds.size(0))
|
| 343 |
+
input_embeds[selected][:n_token] = input_embeds[selected][:n_token] * 0.0 + vit_embeds[:n_token]
|
| 344 |
+
|
| 345 |
+
input_embeds = input_embeds.reshape(B, N, C)
|
| 346 |
+
|
| 347 |
+
outputs = self.language_model(
|
| 348 |
+
inputs_embeds=input_embeds,
|
| 349 |
+
attention_mask=attention_mask,
|
| 350 |
+
position_ids=position_ids,
|
| 351 |
+
past_key_values=past_key_values,
|
| 352 |
+
use_cache=use_cache,
|
| 353 |
+
output_attentions=output_attentions,
|
| 354 |
+
output_hidden_states=output_hidden_states,
|
| 355 |
+
return_dict=return_dict,
|
| 356 |
+
)
|
| 357 |
+
logits = outputs.logits
|
| 358 |
+
|
| 359 |
+
loss = None
|
| 360 |
+
if labels is not None:
|
| 361 |
+
# Shift so that tokens < n predict n
|
| 362 |
+
shift_logits = logits[..., :-1, :].contiguous()
|
| 363 |
+
shift_labels = labels[..., 1:].contiguous()
|
| 364 |
+
# Flatten the tokens
|
| 365 |
+
loss_fct = CrossEntropyLoss()
|
| 366 |
+
shift_logits = shift_logits.view(-1, self.language_model.config.vocab_size)
|
| 367 |
+
shift_labels = shift_labels.view(-1)
|
| 368 |
+
# Enable model parallelism
|
| 369 |
+
shift_labels = shift_labels.to(shift_logits.device)
|
| 370 |
+
loss = loss_fct(shift_logits, shift_labels)
|
| 371 |
+
|
| 372 |
+
if not return_dict:
|
| 373 |
+
output = (logits,) + outputs[1:]
|
| 374 |
+
return (loss,) + output if loss is not None else output
|
| 375 |
+
|
| 376 |
+
return CausalLMOutputWithPast(
|
| 377 |
+
loss=loss,
|
| 378 |
+
logits=logits,
|
| 379 |
+
past_key_values=outputs.past_key_values,
|
| 380 |
+
hidden_states=outputs.hidden_states,
|
| 381 |
+
attentions=outputs.attentions,
|
| 382 |
+
)
|
| 383 |
+
|
llm-awq/tinychat/models/nvila/builder.py
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2024 NVIDIA CORPORATION & AFFILIATES
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
#
|
| 15 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 16 |
+
|
| 17 |
+
import math
|
| 18 |
+
import os
|
| 19 |
+
import os.path as osp
|
| 20 |
+
import warnings
|
| 21 |
+
from dataclasses import asdict
|
| 22 |
+
from typing import Tuple
|
| 23 |
+
|
| 24 |
+
import torch
|
| 25 |
+
from huggingface_hub import file_exists, repo_exists
|
| 26 |
+
from huggingface_hub.utils import HFValidationError
|
| 27 |
+
from transformers import (
|
| 28 |
+
AutoConfig,
|
| 29 |
+
AutoModelForCausalLM,
|
| 30 |
+
AutoTokenizer,
|
| 31 |
+
PretrainedConfig,
|
| 32 |
+
PreTrainedModel,
|
| 33 |
+
PreTrainedTokenizer,
|
| 34 |
+
)
|
| 35 |
+
|
| 36 |
+
from llava.constants import MEDIA_TOKENS
|
| 37 |
+
from llava.model.utils import packing
|
| 38 |
+
from llava.utils.logging import logger
|
| 39 |
+
from llava.utils.tokenizer import infer_stop_tokens
|
| 40 |
+
|
| 41 |
+
|
| 42 |
+
def has_tokenizer(repo_id_or_path: str) -> bool:
|
| 43 |
+
# Check if the tokenizer is in a local directory
|
| 44 |
+
if osp.exists(osp.join(repo_id_or_path, "tokenizer_config.json")):
|
| 45 |
+
return True
|
| 46 |
+
|
| 47 |
+
# Check if the tokenizer is in a Hugging Face Hub repo
|
| 48 |
+
try:
|
| 49 |
+
return repo_exists(repo_id_or_path) and file_exists(
|
| 50 |
+
repo_id_or_path, "tokenizer_config.json"
|
| 51 |
+
)
|
| 52 |
+
except HFValidationError:
|
| 53 |
+
return False
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def context_length_extension(config):
|
| 57 |
+
orig_ctx_len = getattr(config, "max_position_embeddings", None)
|
| 58 |
+
model_max_length = getattr(config, "model_max_length", None)
|
| 59 |
+
if orig_ctx_len and model_max_length > orig_ctx_len:
|
| 60 |
+
print(f"Scaling RoPE from {orig_ctx_len} to {model_max_length}")
|
| 61 |
+
scaling_factor = float(math.ceil(model_max_length / orig_ctx_len))
|
| 62 |
+
config.rope_scaling = {"type": "linear", "factor": scaling_factor}
|
| 63 |
+
return config
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
def build_llm_and_tokenizer(
|
| 67 |
+
model_name_or_path: str,
|
| 68 |
+
config: PretrainedConfig,
|
| 69 |
+
attn_implementation=None,
|
| 70 |
+
model_max_length=None,
|
| 71 |
+
*args,
|
| 72 |
+
**kwargs,
|
| 73 |
+
) -> Tuple[PreTrainedModel, PreTrainedTokenizer]:
|
| 74 |
+
# print(model_name_or_path)
|
| 75 |
+
llm_cfg = AutoConfig.from_pretrained(model_name_or_path)
|
| 76 |
+
llm_cfg._attn_implementation = attn_implementation
|
| 77 |
+
llm_cfg.model_max_length = model_max_length
|
| 78 |
+
if model_max_length is not None:
|
| 79 |
+
context_length_extension(llm_cfg)
|
| 80 |
+
|
| 81 |
+
# Quantization related
|
| 82 |
+
quantization_restore_from_checkpoint = False
|
| 83 |
+
if kwargs.get("quantize_model_class") is not None:
|
| 84 |
+
assert kwargs.get("model_args") is not None
|
| 85 |
+
quantize_model_class = kwargs.pop("quantize_model_class", None)
|
| 86 |
+
model_args = kwargs.pop("model_args", None)
|
| 87 |
+
|
| 88 |
+
if (
|
| 89 |
+
quantize_model_class == "QLlamaForCausalLM"
|
| 90 |
+
): # TODO: Also change the name of this class
|
| 91 |
+
from .qllama import QLlamaConfig
|
| 92 |
+
|
| 93 |
+
llm_cfg.architectures = "QLlamaForCausalLM"
|
| 94 |
+
_attn_implementation = llm_cfg._attn_implementation
|
| 95 |
+
llm_cfg = QLlamaConfig(**llm_cfg.to_dict())
|
| 96 |
+
llm_cfg._attn_implementation = _attn_implementation
|
| 97 |
+
elif (
|
| 98 |
+
quantize_model_class == "QMemLlamaForCausalLM"
|
| 99 |
+
): # TODO: Also change the name of this class
|
| 100 |
+
from .qmemllama import QMemLlamaConfig
|
| 101 |
+
|
| 102 |
+
llm_cfg.architectures = "QMemLlamaForCausalLM"
|
| 103 |
+
llm_cfg = QMemLlamaConfig(**llm_cfg.to_dict())
|
| 104 |
+
elif quantize_model_class == "FP8LinearQwen2ForCausalLM":
|
| 105 |
+
from .configuration_quantize import QuantizationConfig
|
| 106 |
+
from .fp8linearqwen2 import FP8LinearQwen2Config
|
| 107 |
+
|
| 108 |
+
llm_cfg.architectures = "FP8LinearQwen2ForCausalLM"
|
| 109 |
+
coat_fp8_args = QuantizationConfig(**asdict(model_args))
|
| 110 |
+
|
| 111 |
+
# Remove the quantization args from llm_cfg and make it a independent config
|
| 112 |
+
model_args_dict = asdict(model_args)
|
| 113 |
+
for key in asdict(coat_fp8_args).keys():
|
| 114 |
+
model_args_dict.pop(key, None)
|
| 115 |
+
|
| 116 |
+
llm_cfg.coat_fp8_args = asdict(coat_fp8_args)
|
| 117 |
+
_attn_implementation = llm_cfg._attn_implementation
|
| 118 |
+
|
| 119 |
+
llm_cfg = FP8LinearQwen2Config(**llm_cfg.to_dict())
|
| 120 |
+
llm_cfg._attn_implementation = _attn_implementation
|
| 121 |
+
|
| 122 |
+
elif quantize_model_class == "FP8ActivationQwen2ForCausalLM":
|
| 123 |
+
from ..coat.activation.models._fp8_quantization_config import (
|
| 124 |
+
QuantizationConfig,
|
| 125 |
+
)
|
| 126 |
+
from .fp8activationqwen2 import FP8ActivationQwen2Config
|
| 127 |
+
|
| 128 |
+
quantization_restore_from_checkpoint = True
|
| 129 |
+
|
| 130 |
+
llm_cfg.architectures = "FP8ActivationQwen2ForCausalLM"
|
| 131 |
+
coat_fp8_args = QuantizationConfig(**asdict(model_args))
|
| 132 |
+
|
| 133 |
+
# Remove the quantization args from llm_cfg and make it a independent config
|
| 134 |
+
model_args_dict = asdict(model_args)
|
| 135 |
+
for key in asdict(coat_fp8_args).keys():
|
| 136 |
+
model_args_dict.pop(key, None)
|
| 137 |
+
|
| 138 |
+
llm_cfg.coat_fp8_args = asdict(coat_fp8_args)
|
| 139 |
+
_attn_implementation = llm_cfg._attn_implementation
|
| 140 |
+
|
| 141 |
+
llm_cfg = FP8ActivationQwen2Config(**llm_cfg.to_dict())
|
| 142 |
+
llm_cfg._attn_implementation = _attn_implementation
|
| 143 |
+
|
| 144 |
+
elif quantize_model_class == "FP8ActivationResidualQwen2ForCausalLM":
|
| 145 |
+
from ..coat.activation.models._fp8_quantization_config import (
|
| 146 |
+
QuantizationConfig,
|
| 147 |
+
)
|
| 148 |
+
from .fp8activationresidualqwen2 import FP8ActivationResidualQwen2Config
|
| 149 |
+
|
| 150 |
+
quantization_restore_from_checkpoint = True
|
| 151 |
+
|
| 152 |
+
llm_cfg.architectures = "FP8ActivationResidualQwen2ForCausalLM"
|
| 153 |
+
coat_fp8_args = QuantizationConfig(**asdict(model_args))
|
| 154 |
+
|
| 155 |
+
# Remove the quantization args from llm_cfg and make it a independent config
|
| 156 |
+
model_args_dict = asdict(model_args)
|
| 157 |
+
for key in asdict(coat_fp8_args).keys():
|
| 158 |
+
model_args_dict.pop(key, None)
|
| 159 |
+
|
| 160 |
+
llm_cfg.coat_fp8_args = asdict(coat_fp8_args)
|
| 161 |
+
_attn_implementation = llm_cfg._attn_implementation
|
| 162 |
+
|
| 163 |
+
llm_cfg = FP8ActivationResidualQwen2Config(**llm_cfg.to_dict())
|
| 164 |
+
llm_cfg._attn_implementation = _attn_implementation
|
| 165 |
+
else:
|
| 166 |
+
raise ValueError(
|
| 167 |
+
f"{quantize_model_class} is not supported quantize_model_class."
|
| 168 |
+
)
|
| 169 |
+
|
| 170 |
+
kwargs.pop("quantize_model_class", None)
|
| 171 |
+
|
| 172 |
+
if quantize_model_class in [
|
| 173 |
+
"FP8LinearQwen2ForCausalLM",
|
| 174 |
+
"FP8ActivationQwen2ForCausalLM",
|
| 175 |
+
"FP8ActivationResidualQwen2ForCausalLM",
|
| 176 |
+
]: # Remove the quantization args from llm_cfg and make it a independent config
|
| 177 |
+
llm_cfg.update(model_args_dict)
|
| 178 |
+
else:
|
| 179 |
+
llm_cfg.update(asdict(model_args))
|
| 180 |
+
# print(model_args)
|
| 181 |
+
|
| 182 |
+
if quantization_restore_from_checkpoint:
|
| 183 |
+
fp8_model_name_or_path = kwargs.pop("fp8_llm_cfg", None)
|
| 184 |
+
|
| 185 |
+
llm = AutoModelForCausalLM.from_pretrained(
|
| 186 |
+
fp8_model_name_or_path,
|
| 187 |
+
config=llm_cfg,
|
| 188 |
+
torch_dtype=eval(config.model_dtype),
|
| 189 |
+
*args,
|
| 190 |
+
**kwargs,
|
| 191 |
+
)
|
| 192 |
+
|
| 193 |
+
else:
|
| 194 |
+
llm = AutoModelForCausalLM.from_pretrained(
|
| 195 |
+
model_name_or_path,
|
| 196 |
+
config=llm_cfg,
|
| 197 |
+
torch_dtype=eval(config.model_dtype),
|
| 198 |
+
*args,
|
| 199 |
+
**kwargs,
|
| 200 |
+
)
|
| 201 |
+
packing.patch(llm)
|
| 202 |
+
|
| 203 |
+
# Locate the tokenizer.
|
| 204 |
+
llm_path = model_name_or_path
|
| 205 |
+
if not has_tokenizer(llm_path):
|
| 206 |
+
llm_path = osp.join(llm_path, "llm")
|
| 207 |
+
if not has_tokenizer(llm_path):
|
| 208 |
+
raise ValueError(f"Cannot find tokenizer in {llm_path}.")
|
| 209 |
+
|
| 210 |
+
tokenizer = AutoTokenizer.from_pretrained(
|
| 211 |
+
llm_path, padding_side="right", use_fast=False, legacy=False
|
| 212 |
+
)
|
| 213 |
+
if model_max_length is not None:
|
| 214 |
+
tokenizer.model_max_length = model_max_length
|
| 215 |
+
|
| 216 |
+
# Load chat template if specified.
|
| 217 |
+
if getattr(config, "chat_template", None) is not None:
|
| 218 |
+
logger.info(f"Using chat template: {config.chat_template}")
|
| 219 |
+
fpath = os.path.join(
|
| 220 |
+
os.path.dirname(__file__), "chat_templates", f"{config.chat_template}.jinja"
|
| 221 |
+
)
|
| 222 |
+
with open(fpath) as fd:
|
| 223 |
+
chat_template = fd.read()
|
| 224 |
+
tokenizer.chat_template = chat_template.replace(" ", "").replace("\n", "")
|
| 225 |
+
|
| 226 |
+
# Set stop tokens for the tokenizer
|
| 227 |
+
tokenizer.stop_tokens = infer_stop_tokens(tokenizer)
|
| 228 |
+
tokenizer.stop_token_ids = tokenizer.convert_tokens_to_ids(tokenizer.stop_tokens)
|
| 229 |
+
|
| 230 |
+
# Add media tokens to the tokenizer
|
| 231 |
+
tokenizer.media_tokens = MEDIA_TOKENS
|
| 232 |
+
tokenizer.media_token_ids = {}
|
| 233 |
+
for name, token in MEDIA_TOKENS.items():
|
| 234 |
+
tokenizer.add_tokens([token], special_tokens=True)
|
| 235 |
+
tokenizer.media_token_ids[name] = tokenizer.convert_tokens_to_ids(token)
|
| 236 |
+
|
| 237 |
+
# TODO(ligeng): is this necessary for llava?
|
| 238 |
+
config.hidden_size = llm.config.hidden_size
|
| 239 |
+
return llm, tokenizer
|
| 240 |
+
|
| 241 |
+
|
| 242 |
+
def build_tokenizer(
|
| 243 |
+
model_name_or_path: str,
|
| 244 |
+
config: PretrainedConfig,
|
| 245 |
+
attn_implementation=None,
|
| 246 |
+
model_max_length=None,
|
| 247 |
+
*args,
|
| 248 |
+
**kwargs,
|
| 249 |
+
) -> Tuple[PreTrainedModel, PreTrainedTokenizer]:
|
| 250 |
+
# print(model_name_or_path)
|
| 251 |
+
llm_cfg = AutoConfig.from_pretrained(model_name_or_path)
|
| 252 |
+
llm_cfg._attn_implementation = attn_implementation
|
| 253 |
+
llm_cfg.model_max_length = model_max_length
|
| 254 |
+
if model_max_length is not None:
|
| 255 |
+
context_length_extension(llm_cfg)
|
| 256 |
+
|
| 257 |
+
# Locate the tokenizer.
|
| 258 |
+
llm_path = model_name_or_path
|
| 259 |
+
if not has_tokenizer(llm_path):
|
| 260 |
+
llm_path = osp.join(llm_path, "llm")
|
| 261 |
+
if not has_tokenizer(llm_path):
|
| 262 |
+
raise ValueError(f"Cannot find tokenizer in {llm_path}.")
|
| 263 |
+
|
| 264 |
+
tokenizer = AutoTokenizer.from_pretrained(
|
| 265 |
+
llm_path, padding_side="right", use_fast=False, legacy=False
|
| 266 |
+
)
|
| 267 |
+
if model_max_length is not None:
|
| 268 |
+
tokenizer.model_max_length = model_max_length
|
| 269 |
+
|
| 270 |
+
# Load chat template if specified.
|
| 271 |
+
if getattr(config, "chat_template", None) is not None:
|
| 272 |
+
logger.info(f"Using chat template: {config.chat_template}")
|
| 273 |
+
fpath = os.path.join(
|
| 274 |
+
os.path.dirname(__file__), "chat_templates", f"{config.chat_template}.jinja"
|
| 275 |
+
)
|
| 276 |
+
with open(fpath) as fd:
|
| 277 |
+
chat_template = fd.read()
|
| 278 |
+
tokenizer.chat_template = chat_template.replace(" ", "").replace("\n", "")
|
| 279 |
+
|
| 280 |
+
# Set stop tokens for the tokenizer
|
| 281 |
+
tokenizer.stop_tokens = infer_stop_tokens(tokenizer)
|
| 282 |
+
tokenizer.stop_token_ids = tokenizer.convert_tokens_to_ids(tokenizer.stop_tokens)
|
| 283 |
+
|
| 284 |
+
# Add media tokens to the tokenizer
|
| 285 |
+
tokenizer.media_tokens = MEDIA_TOKENS
|
| 286 |
+
tokenizer.media_token_ids = {}
|
| 287 |
+
for name, token in MEDIA_TOKENS.items():
|
| 288 |
+
tokenizer.add_tokens([token], special_tokens=True)
|
| 289 |
+
tokenizer.media_token_ids[name] = tokenizer.convert_tokens_to_ids(token)
|
| 290 |
+
|
| 291 |
+
return tokenizer
|
llm-awq/tinychat/models/nvila/llava_arch.py
ADDED
|
@@ -0,0 +1,909 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright 2023 Haotian Liu
|
| 2 |
+
#
|
| 3 |
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
| 4 |
+
# you may not use this file except in compliance with the License.
|
| 5 |
+
# You may obtain a copy of the License at
|
| 6 |
+
#
|
| 7 |
+
# http://www.apache.org/licenses/LICENSE-2.0
|
| 8 |
+
#
|
| 9 |
+
# Unless required by applicable law or agreed to in writing, software
|
| 10 |
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
| 11 |
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
| 12 |
+
# See the License for the specific language governing permissions and
|
| 13 |
+
# limitations under the License.
|
| 14 |
+
|
| 15 |
+
import copy
|
| 16 |
+
import json
|
| 17 |
+
import logging
|
| 18 |
+
import os
|
| 19 |
+
import os.path as osp
|
| 20 |
+
import warnings
|
| 21 |
+
from abc import ABC
|
| 22 |
+
from collections import OrderedDict, defaultdict, deque
|
| 23 |
+
from itertools import chain
|
| 24 |
+
from typing import Any, Dict, List, Optional, Tuple, Union
|
| 25 |
+
|
| 26 |
+
import torch
|
| 27 |
+
import torch.distributed as dist
|
| 28 |
+
import torch.nn.functional as F
|
| 29 |
+
from einops import rearrange
|
| 30 |
+
from hydra.utils import instantiate
|
| 31 |
+
from transformers import AutoConfig, GenerationConfig, PreTrainedModel
|
| 32 |
+
from transformers.modeling_utils import ContextManagers, no_init_weights
|
| 33 |
+
from time import time
|
| 34 |
+
from llava.constants import DEFAULT_IMAGE_TOKEN, IGNORE_INDEX
|
| 35 |
+
from llava.mm_utils import process_image, process_images
|
| 36 |
+
from llava.model.configuration_llava import LlavaConfig
|
| 37 |
+
from llava.model.language_model.builder import build_llm_and_tokenizer
|
| 38 |
+
from llava.model.multimodal_encoder.builder import build_vision_tower
|
| 39 |
+
from llava.model.multimodal_projector.builder import build_mm_projector
|
| 40 |
+
from llava.model.utils import get_model_config
|
| 41 |
+
|
| 42 |
+
# from llava.train.sequence_parallel import get_pg_manager
|
| 43 |
+
from llava.utils import distributed as dist
|
| 44 |
+
from llava.utils.media import extract_media
|
| 45 |
+
from llava.utils.tokenizer import tokenize_conversation
|
| 46 |
+
from .builder import build_tokenizer
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
class LlavaMetaModel(ABC):
|
| 50 |
+
def init_vlm(self, config, *args, **kwargs):
|
| 51 |
+
# TODO(ligeng): figure out how from_config and from_pretrained works in HF implementation.
|
| 52 |
+
if (
|
| 53 |
+
hasattr(self, "llm")
|
| 54 |
+
or hasattr(self, "vision_tower")
|
| 55 |
+
or hasattr(self, "mm_projector")
|
| 56 |
+
):
|
| 57 |
+
# already initialized, skipped
|
| 58 |
+
return
|
| 59 |
+
|
| 60 |
+
model_dtype = getattr(config, "model_dtype", "torch.float16")
|
| 61 |
+
if not hasattr(config, "model_dtype"):
|
| 62 |
+
warnings.warn(
|
| 63 |
+
"model_dtype not found in config, defaulting to torch.float16."
|
| 64 |
+
)
|
| 65 |
+
config.model_dtype = model_dtype
|
| 66 |
+
|
| 67 |
+
cfgs = get_model_config(config)
|
| 68 |
+
if len(cfgs) == 3:
|
| 69 |
+
self.llm_cfg, vision_tower_cfg, mm_projector_cfg = cfgs
|
| 70 |
+
else:
|
| 71 |
+
raise ValueError(
|
| 72 |
+
"`llm_cfg` `mm_projector_cfg` `vision_tower_cfg` not found in the config."
|
| 73 |
+
)
|
| 74 |
+
self.tokenizer = build_tokenizer(self.llm_cfg, config, *args, **kwargs)
|
| 75 |
+
self.vision_tower = build_vision_tower(vision_tower_cfg, config)
|
| 76 |
+
self.mm_projector = build_mm_projector(mm_projector_cfg, config)
|
| 77 |
+
|
| 78 |
+
self.encoders = {}
|
| 79 |
+
for name in ["image", "video"]:
|
| 80 |
+
config = getattr(self.config, f"{name}_encoder")
|
| 81 |
+
if isinstance(config, str):
|
| 82 |
+
config = json.loads(config)
|
| 83 |
+
self.encoders[name] = instantiate(config, parent=self)
|
| 84 |
+
|
| 85 |
+
self.post_config()
|
| 86 |
+
self.is_loaded = True
|
| 87 |
+
|
| 88 |
+
assert (
|
| 89 |
+
self.vision_tower is not None or self.mm_projector is not None
|
| 90 |
+
), "At least one of the components must be instantiated."
|
| 91 |
+
|
| 92 |
+
@classmethod
|
| 93 |
+
def load_from_config(cls, model_path_or_config, *args, **kwargs):
|
| 94 |
+
pass
|
| 95 |
+
|
| 96 |
+
## FIXME we will use this function to load model in the future
|
| 97 |
+
@classmethod
|
| 98 |
+
def load_pretrained(cls, model_path_or_config, *args, **kwargs):
|
| 99 |
+
kwargs.pop("config", None)
|
| 100 |
+
|
| 101 |
+
if isinstance(model_path_or_config, str):
|
| 102 |
+
config = AutoConfig.from_pretrained(model_path_or_config)
|
| 103 |
+
elif isinstance(model_path_or_config, LlavaConfig):
|
| 104 |
+
config = model_path_or_config
|
| 105 |
+
else:
|
| 106 |
+
raise NotImplementedError(
|
| 107 |
+
f"wrong type, {type(model_path_or_config)} \
|
| 108 |
+
{isinstance(model_path_or_config, LlavaConfig)}"
|
| 109 |
+
)
|
| 110 |
+
|
| 111 |
+
model_dtype = getattr(config, "model_dtype", "torch.float16")
|
| 112 |
+
if not hasattr(config, "model_dtype"):
|
| 113 |
+
warnings.warn(
|
| 114 |
+
"model_dtype not found in config, defaulting to torch.float16."
|
| 115 |
+
)
|
| 116 |
+
config.model_dtype = model_dtype
|
| 117 |
+
|
| 118 |
+
cfgs = get_model_config(config)
|
| 119 |
+
if len(cfgs) == 3:
|
| 120 |
+
llm_cfg, vision_tower_cfg, mm_projector_cfg = cfgs
|
| 121 |
+
else:
|
| 122 |
+
raise ValueError(
|
| 123 |
+
"`llm_cfg` `mm_projector_cfg` `vision_tower_cfg` not found in the config."
|
| 124 |
+
)
|
| 125 |
+
|
| 126 |
+
# print(llm_cfg, vision_tower_cfg, mm_projector_cfg); input("DEBUG load_pretrained")
|
| 127 |
+
init_context = [
|
| 128 |
+
no_init_weights(_enable=True),
|
| 129 |
+
]
|
| 130 |
+
# print("Before Init Context")
|
| 131 |
+
# if hasattr(config, "deepspeed") and "mics" in config.deepspeed:
|
| 132 |
+
# print("Using MiCS_Init")
|
| 133 |
+
# import deepspeed
|
| 134 |
+
# init_context.append(deepspeed.zero.MiCS_Init(config_dict_or_path=config.deepspeed))
|
| 135 |
+
with ContextManagers(init_context):
|
| 136 |
+
vlm = cls(config, *args, **kwargs)
|
| 137 |
+
# print(llm_cfg, vision_tower_cfg, mm_projector_cfg); input("DEBUG load_pretrained finish")
|
| 138 |
+
|
| 139 |
+
if (
|
| 140 |
+
hasattr(vlm, "llm")
|
| 141 |
+
or hasattr(vlm, "vision_tower")
|
| 142 |
+
or hasattr(vlm, "mm_projector")
|
| 143 |
+
):
|
| 144 |
+
if vlm.is_loaded:
|
| 145 |
+
return vlm
|
| 146 |
+
|
| 147 |
+
vlm.llm, vlm.tokenizer = build_llm_and_tokenizer(
|
| 148 |
+
llm_cfg, config, *args, **kwargs
|
| 149 |
+
)
|
| 150 |
+
vlm.vision_tower = build_vision_tower(vision_tower_cfg, config)
|
| 151 |
+
vlm.mm_projector = build_mm_projector(mm_projector_cfg, config)
|
| 152 |
+
|
| 153 |
+
self.post_config()
|
| 154 |
+
self.is_loaded = True
|
| 155 |
+
|
| 156 |
+
# FIXME(ligeng, yunhao): llm should never be none here.
|
| 157 |
+
assert (
|
| 158 |
+
vlm.llm is not None
|
| 159 |
+
or vlm.vision_tower is not None
|
| 160 |
+
or vlm.mm_projector is not None
|
| 161 |
+
), "At least one of the components must be instantiated."
|
| 162 |
+
return vlm
|
| 163 |
+
|
| 164 |
+
## FIXME we will use this function to save the model in the future
|
| 165 |
+
def save_pretrained(self, output_dir, state_dict=None):
|
| 166 |
+
if state_dict is None:
|
| 167 |
+
# other wise fetch from deepspeed
|
| 168 |
+
# state_dict = accelerator.get_state_dict(is_deepspeed_enabled)
|
| 169 |
+
state_dict = self.state_dict()
|
| 170 |
+
|
| 171 |
+
if getattr(self, "tokenizer", None):
|
| 172 |
+
self.tokenizer.save_pretrained(osp.join(output_dir, "llm"))
|
| 173 |
+
|
| 174 |
+
if self.get_llm():
|
| 175 |
+
print(f"saving llm to {osp.join(output_dir, 'llm')}")
|
| 176 |
+
self.llm.config._name_or_path = osp.join(output_dir, "llm")
|
| 177 |
+
llm_state_dict = OrderedDict(
|
| 178 |
+
{k.split("llm.")[-1]: v for k, v in state_dict.items() if "llm" in k}
|
| 179 |
+
)
|
| 180 |
+
self.llm.save_pretrained(
|
| 181 |
+
os.path.join(output_dir, "llm"), state_dict=llm_state_dict
|
| 182 |
+
)
|
| 183 |
+
self.config.llm_cfg = self.llm.config
|
| 184 |
+
|
| 185 |
+
if self.get_vision_tower():
|
| 186 |
+
print(f"saving vision_tower to {osp.join(output_dir, 'vision_tower')}")
|
| 187 |
+
self.vision_tower.config._name_or_path = osp.join(
|
| 188 |
+
output_dir, "vision_tower"
|
| 189 |
+
)
|
| 190 |
+
vision_tower_state_dict = OrderedDict(
|
| 191 |
+
{
|
| 192 |
+
k.split("vision_tower.vision_tower.")[-1]: v
|
| 193 |
+
for k, v in state_dict.items()
|
| 194 |
+
if "vision_tower" in k
|
| 195 |
+
}
|
| 196 |
+
)
|
| 197 |
+
self.vision_tower.vision_tower.save_pretrained(
|
| 198 |
+
os.path.join(output_dir, "vision_tower"),
|
| 199 |
+
state_dict=vision_tower_state_dict,
|
| 200 |
+
)
|
| 201 |
+
self.vision_tower.image_processor.save_pretrained(
|
| 202 |
+
os.path.join(output_dir, "vision_tower")
|
| 203 |
+
)
|
| 204 |
+
self.config.vision_tower_cfg = self.vision_tower.config
|
| 205 |
+
if hasattr(self.config.vision_tower_cfg, "auto_map"):
|
| 206 |
+
if "radio" not in self.get_vision_tower().__class__.__name__.lower():
|
| 207 |
+
delattr(self.config.vision_tower_cfg, "auto_map")
|
| 208 |
+
|
| 209 |
+
if self.get_mm_projector():
|
| 210 |
+
print(f"saving mm_projector to {osp.join(output_dir, 'mm_projector')}")
|
| 211 |
+
self.mm_projector.config._name_or_path = osp.join(
|
| 212 |
+
output_dir, "mm_projector"
|
| 213 |
+
)
|
| 214 |
+
mm_projector_state_dict = OrderedDict(
|
| 215 |
+
{
|
| 216 |
+
k.split("mm_projector.")[-1]: v
|
| 217 |
+
for k, v in state_dict.items()
|
| 218 |
+
if "mm_projector" in k
|
| 219 |
+
}
|
| 220 |
+
)
|
| 221 |
+
self.mm_projector.save_pretrained(
|
| 222 |
+
os.path.join(output_dir, "mm_projector"),
|
| 223 |
+
state_dict=mm_projector_state_dict,
|
| 224 |
+
)
|
| 225 |
+
self.config.mm_projector_cfg = self.mm_projector.config
|
| 226 |
+
## update and save top-level config
|
| 227 |
+
self.config._name_or_path = output_dir
|
| 228 |
+
self.config.architectures = [self.__class__.__name__]
|
| 229 |
+
self.config.save_pretrained(output_dir)
|
| 230 |
+
|
| 231 |
+
def get_llm(self):
|
| 232 |
+
llm = getattr(self, "llm", None)
|
| 233 |
+
if type(llm) is list:
|
| 234 |
+
llm = llm[0]
|
| 235 |
+
return llm
|
| 236 |
+
|
| 237 |
+
def get_lm_head(self):
|
| 238 |
+
lm_head = getattr(self.get_llm(), "lm_head", None)
|
| 239 |
+
return lm_head
|
| 240 |
+
|
| 241 |
+
def get_vision_tower(self):
|
| 242 |
+
vision_tower = getattr(self, "vision_tower", None)
|
| 243 |
+
if type(vision_tower) is list:
|
| 244 |
+
vision_tower = vision_tower[0]
|
| 245 |
+
return vision_tower
|
| 246 |
+
|
| 247 |
+
def get_mm_projector(self):
|
| 248 |
+
mm_projector = getattr(self, "mm_projector", None)
|
| 249 |
+
if type(mm_projector) is list:
|
| 250 |
+
mm_projector = mm_projector[0]
|
| 251 |
+
return mm_projector
|
| 252 |
+
|
| 253 |
+
def post_config(self):
|
| 254 |
+
|
| 255 |
+
if getattr(self.config, "vision_tower_cfg", None) is None:
|
| 256 |
+
self.config.vision_tower_cfg = self.vision_tower.config
|
| 257 |
+
if getattr(self.config, "mm_projector_cfg", None) is None:
|
| 258 |
+
self.config.mm_projector_cfg = self.mm_projector.config
|
| 259 |
+
|
| 260 |
+
@staticmethod
|
| 261 |
+
def merge_chessboard(x, num_split_h, num_split_w):
|
| 262 |
+
"""
|
| 263 |
+
x: b * n * c or b * h * w * c
|
| 264 |
+
out: b * c * h * w
|
| 265 |
+
Assuming x contains num_split**2 sub-squares concatenated along batch dimension, merge the sub-squares back to the original whole square.
|
| 266 |
+
"""
|
| 267 |
+
B = x.shape[0]
|
| 268 |
+
if x.dim() == 3:
|
| 269 |
+
N = x.shape[1]
|
| 270 |
+
x = rearrange(x, "b (h w) c -> b c h w", h=int(N**0.5), w=int(N**0.5))
|
| 271 |
+
|
| 272 |
+
assert B % (num_split_h * num_split_w) == 0
|
| 273 |
+
b = B // (num_split_h * num_split_w)
|
| 274 |
+
|
| 275 |
+
x_merge = torch.cat(
|
| 276 |
+
[
|
| 277 |
+
torch.cat(
|
| 278 |
+
[
|
| 279 |
+
x[(i * num_split_w + j) * b : (i * num_split_w + j + 1) * b]
|
| 280 |
+
for j in range(num_split_w)
|
| 281 |
+
],
|
| 282 |
+
dim=-1,
|
| 283 |
+
)
|
| 284 |
+
for i in range(num_split_h)
|
| 285 |
+
],
|
| 286 |
+
dim=-2,
|
| 287 |
+
)
|
| 288 |
+
|
| 289 |
+
return x_merge
|
| 290 |
+
|
| 291 |
+
@staticmethod
|
| 292 |
+
def split_chessboard(x, num_split_h, num_split_w):
|
| 293 |
+
"""
|
| 294 |
+
x: b * c * h * w
|
| 295 |
+
out: b * c * h * w
|
| 296 |
+
Deividing x into num_split**2 sub-squares, and concatenate all the sub-squares on the batch dimension
|
| 297 |
+
"""
|
| 298 |
+
B, C, H, W = x.shape
|
| 299 |
+
assert H % num_split_h == 0 and W % num_split_w == 0
|
| 300 |
+
h, w = H // num_split_h, W // num_split_w
|
| 301 |
+
x_split = torch.cat(
|
| 302 |
+
[
|
| 303 |
+
x[:, :, i * h : (i + 1) * h, j * w : (j + 1) * w]
|
| 304 |
+
for i in range(num_split_h)
|
| 305 |
+
for j in range(num_split_w)
|
| 306 |
+
],
|
| 307 |
+
dim=0,
|
| 308 |
+
)
|
| 309 |
+
return x_split
|
| 310 |
+
|
| 311 |
+
def merge_features_for_dynamic_s2(self, image_features, block_sizes):
|
| 312 |
+
scales = self.get_vision_tower().scales
|
| 313 |
+
resize_output_to_scale_idx = self.get_vision_tower().resize_output_to_scale_idx
|
| 314 |
+
|
| 315 |
+
image_features_each_image = []
|
| 316 |
+
new_block_sizes = []
|
| 317 |
+
block_cnt = 0
|
| 318 |
+
for block_size_each_image in block_sizes:
|
| 319 |
+
if block_size_each_image is None:
|
| 320 |
+
cur_features = image_features[block_cnt : block_cnt + 1]
|
| 321 |
+
cur_features = rearrange(
|
| 322 |
+
cur_features,
|
| 323 |
+
"1 (h w) c -> 1 c h w",
|
| 324 |
+
h=int(cur_features.shape[1] ** 0.5),
|
| 325 |
+
)
|
| 326 |
+
cur_features = cur_features.repeat(1, len(scales), 1, 1)
|
| 327 |
+
image_features_each_image.append(cur_features)
|
| 328 |
+
new_block_sizes.append((1, 1))
|
| 329 |
+
block_cnt += 1
|
| 330 |
+
else:
|
| 331 |
+
cur_features_each_scale = []
|
| 332 |
+
for scale in scales[:-1]:
|
| 333 |
+
num_blocks_this_scale = (scale // scales[0]) ** 2
|
| 334 |
+
cur_features_each_scale.append(
|
| 335 |
+
self.merge_chessboard(
|
| 336 |
+
image_features[
|
| 337 |
+
block_cnt : block_cnt + num_blocks_this_scale
|
| 338 |
+
],
|
| 339 |
+
num_split_h=scale // scales[0],
|
| 340 |
+
num_split_w=scale // scales[0],
|
| 341 |
+
)
|
| 342 |
+
) # 1 * C * H * W
|
| 343 |
+
block_cnt += num_blocks_this_scale
|
| 344 |
+
num_blocks_last_scale = (
|
| 345 |
+
block_size_each_image[0] * block_size_each_image[1]
|
| 346 |
+
)
|
| 347 |
+
cur_features_each_scale.append(
|
| 348 |
+
self.merge_chessboard(
|
| 349 |
+
image_features[block_cnt : block_cnt + num_blocks_last_scale],
|
| 350 |
+
num_split_h=block_size_each_image[0],
|
| 351 |
+
num_split_w=block_size_each_image[1],
|
| 352 |
+
)
|
| 353 |
+
) # 1 * C * H * W
|
| 354 |
+
block_cnt += num_blocks_last_scale
|
| 355 |
+
|
| 356 |
+
# resize and concat features from different scales
|
| 357 |
+
output_size = cur_features_each_scale[resize_output_to_scale_idx].shape[
|
| 358 |
+
-2:
|
| 359 |
+
]
|
| 360 |
+
cur_features = torch.cat(
|
| 361 |
+
[
|
| 362 |
+
F.interpolate(
|
| 363 |
+
cur_features_each_scale[i].to(torch.float32),
|
| 364 |
+
size=output_size,
|
| 365 |
+
mode="area",
|
| 366 |
+
).to(cur_features_each_scale[i].dtype)
|
| 367 |
+
for i in range(len(cur_features_each_scale))
|
| 368 |
+
],
|
| 369 |
+
dim=1,
|
| 370 |
+
)
|
| 371 |
+
# cur_features = rearrange(cur_features, "1 c h w -> (h w) c")
|
| 372 |
+
|
| 373 |
+
image_features_each_image.append(cur_features)
|
| 374 |
+
|
| 375 |
+
if (
|
| 376 |
+
resize_output_to_scale_idx == len(scales) - 1
|
| 377 |
+
or resize_output_to_scale_idx == -1
|
| 378 |
+
):
|
| 379 |
+
new_block_sizes.append(block_size_each_image)
|
| 380 |
+
else:
|
| 381 |
+
new_block_sizes.append(
|
| 382 |
+
(
|
| 383 |
+
scales[resize_output_to_scale_idx] // scales[0],
|
| 384 |
+
scales[resize_output_to_scale_idx] // scales[0],
|
| 385 |
+
)
|
| 386 |
+
)
|
| 387 |
+
|
| 388 |
+
assert block_cnt == len(image_features)
|
| 389 |
+
|
| 390 |
+
return image_features_each_image, new_block_sizes
|
| 391 |
+
|
| 392 |
+
def encode_images(
|
| 393 |
+
self, images, block_sizes: Optional[Optional[Tuple[int, ...]]] = None
|
| 394 |
+
):
|
| 395 |
+
if block_sizes is None:
|
| 396 |
+
block_sizes = [None] * len(images)
|
| 397 |
+
if getattr(self.config, "dynamic_s2", False):
|
| 398 |
+
image_features = self.get_vision_tower()(images)
|
| 399 |
+
image_features, new_block_sizes = self.merge_features_for_dynamic_s2(
|
| 400 |
+
image_features, block_sizes
|
| 401 |
+
)
|
| 402 |
+
|
| 403 |
+
image_features = [
|
| 404 |
+
self.split_chessboard(x, block_size[0], block_size[1])
|
| 405 |
+
for x, block_size in zip(image_features, new_block_sizes)
|
| 406 |
+
] # list of B * C * H * W tensors
|
| 407 |
+
image_features = torch.cat(
|
| 408 |
+
[rearrange(x, "b c h w -> b (h w) c") for x in image_features], dim=0
|
| 409 |
+
) # B * N * C
|
| 410 |
+
image_features = self.get_mm_projector()(image_features)
|
| 411 |
+
image_features = list(
|
| 412 |
+
image_features.split(
|
| 413 |
+
[block_size[0] * block_size[1] for block_size in new_block_sizes],
|
| 414 |
+
dim=0,
|
| 415 |
+
)
|
| 416 |
+
)
|
| 417 |
+
image_features = [
|
| 418 |
+
self.merge_chessboard(x, block_size[0], block_size[1])
|
| 419 |
+
for x, block_size in zip(image_features, new_block_sizes)
|
| 420 |
+
] # list of 1 * C * H * W tensors
|
| 421 |
+
image_features = [
|
| 422 |
+
rearrange(x, "1 c h w -> (h w) c") for x in image_features
|
| 423 |
+
] # list of N * C tensors
|
| 424 |
+
image_features = torch.stack(image_features, dim=0)
|
| 425 |
+
else:
|
| 426 |
+
image_features = self.get_vision_tower()(images)
|
| 427 |
+
image_features = self.get_mm_projector()(image_features)
|
| 428 |
+
return image_features
|
| 429 |
+
|
| 430 |
+
## @yunhao: is there a better way to handle function call and attributes for llm?
|
| 431 |
+
## support beam search
|
| 432 |
+
def _temporary_reorder_cache(self, past_key_values, sorted_idx):
|
| 433 |
+
return self.get_llm()._temporary_reorder_cache(past_key_values, sorted_idx)
|
| 434 |
+
|
| 435 |
+
def get_input_embeddings(self):
|
| 436 |
+
return self.get_llm().get_input_embeddings()
|
| 437 |
+
|
| 438 |
+
def get_output_embeddings(self):
|
| 439 |
+
return self.get_llm().get_output_embeddings()
|
| 440 |
+
|
| 441 |
+
def resize_token_embeddings(self, embed_size):
|
| 442 |
+
self.get_llm().resize_token_embeddings(embed_size)
|
| 443 |
+
|
| 444 |
+
|
| 445 |
+
class LlavaMetaForCausalLM(ABC):
|
| 446 |
+
def _embed(
|
| 447 |
+
self,
|
| 448 |
+
input_ids: torch.Tensor,
|
| 449 |
+
media: Dict[str, List[torch.Tensor]],
|
| 450 |
+
media_config: Dict[str, Dict[str, Any]],
|
| 451 |
+
labels: Optional[torch.Tensor],
|
| 452 |
+
attention_mask: Optional[torch.Tensor],
|
| 453 |
+
) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
|
| 454 |
+
labels = (
|
| 455 |
+
labels if labels is not None else torch.full_like(input_ids, IGNORE_INDEX)
|
| 456 |
+
)
|
| 457 |
+
attention_mask = (
|
| 458 |
+
attention_mask
|
| 459 |
+
if attention_mask is not None
|
| 460 |
+
else torch.ones_like(input_ids, dtype=torch.bool)
|
| 461 |
+
)
|
| 462 |
+
|
| 463 |
+
# Extract text and media embeddings
|
| 464 |
+
text_embeds = self.llm.model.embed_tokens(input_ids)
|
| 465 |
+
media_embeds = self.__embed_media_tokens(media, media_config)
|
| 466 |
+
|
| 467 |
+
# This is a workaround to make sure the dummy embeddings are consumed
|
| 468 |
+
while media_embeds.get("dummy"):
|
| 469 |
+
dummy_embed = media_embeds["dummy"].popleft()
|
| 470 |
+
text_embeds += torch.sum(dummy_embed) * 0
|
| 471 |
+
# Remove padding
|
| 472 |
+
batch_size = labels.shape[0]
|
| 473 |
+
text_embeds = [text_embeds[k][attention_mask[k]] for k in range(batch_size)]
|
| 474 |
+
labels = [labels[k][attention_mask[k]] for k in range(batch_size)]
|
| 475 |
+
|
| 476 |
+
# Build inverse mapping from token ID to media name
|
| 477 |
+
media_tokens = {}
|
| 478 |
+
for name, token_id in self.tokenizer.media_token_ids.items():
|
| 479 |
+
media_tokens[token_id] = name
|
| 480 |
+
|
| 481 |
+
# Fuse text and media embeddings
|
| 482 |
+
inputs_m, labels_m = [], []
|
| 483 |
+
for k in range(batch_size):
|
| 484 |
+
inputs_mk, labels_mk = [], []
|
| 485 |
+
pos = 0
|
| 486 |
+
while pos < len(labels[k]):
|
| 487 |
+
if input_ids[k][pos].item() in media_tokens:
|
| 488 |
+
end = pos + 1
|
| 489 |
+
name = media_tokens[input_ids[k][pos].item()]
|
| 490 |
+
input = media_embeds[name].popleft()
|
| 491 |
+
label = torch.full(
|
| 492 |
+
[input.shape[0]],
|
| 493 |
+
IGNORE_INDEX,
|
| 494 |
+
device=labels[k].device,
|
| 495 |
+
dtype=labels[k].dtype,
|
| 496 |
+
)
|
| 497 |
+
else:
|
| 498 |
+
end = pos
|
| 499 |
+
while (
|
| 500 |
+
end < len(labels[k])
|
| 501 |
+
and input_ids[k][end].item() not in media_tokens
|
| 502 |
+
):
|
| 503 |
+
end += 1
|
| 504 |
+
input = text_embeds[k][pos:end]
|
| 505 |
+
label = labels[k][pos:end]
|
| 506 |
+
inputs_mk.append(input)
|
| 507 |
+
labels_mk.append(label)
|
| 508 |
+
pos = end
|
| 509 |
+
inputs_m.append(torch.cat(inputs_mk, dim=0))
|
| 510 |
+
labels_m.append(torch.cat(labels_mk, dim=0))
|
| 511 |
+
inputs, labels = inputs_m, labels_m
|
| 512 |
+
|
| 513 |
+
# Check if all media embeddings are consumed
|
| 514 |
+
for name in media_embeds:
|
| 515 |
+
if media_embeds[name]:
|
| 516 |
+
raise ValueError(f"Not all {name} embeddings are consumed!")
|
| 517 |
+
|
| 518 |
+
# Truncate sequences to `model_max_length` as media embeddings are inserted
|
| 519 |
+
inputs, labels = self.__truncate_sequence(inputs, labels)
|
| 520 |
+
|
| 521 |
+
# Pad sequences to the longest one in the batch
|
| 522 |
+
return self.__batchify_sequence(inputs, labels)
|
| 523 |
+
|
| 524 |
+
def __embed_media_tokens(
|
| 525 |
+
self,
|
| 526 |
+
media: Dict[str, List[torch.Tensor]],
|
| 527 |
+
media_config: Dict[str, Dict[str, Any]],
|
| 528 |
+
) -> Dict[str, List[torch.Tensor]]:
|
| 529 |
+
embeds = defaultdict(deque)
|
| 530 |
+
for name in media:
|
| 531 |
+
embeds[name] = deque(self.encoders[name](media[name], media_config[name]))
|
| 532 |
+
return embeds
|
| 533 |
+
|
| 534 |
+
def __truncate_sequence(
|
| 535 |
+
self, inputs: List[torch.Tensor], labels: List[torch.Tensor]
|
| 536 |
+
) -> Tuple[torch.Tensor, torch.Tensor]:
|
| 537 |
+
if any(len(input) > self.tokenizer.model_max_length for input in inputs):
|
| 538 |
+
warnings.warn(
|
| 539 |
+
f"Truncating sequences to `model_max_length` ({self.tokenizer.model_max_length})."
|
| 540 |
+
)
|
| 541 |
+
inputs = [input[: self.tokenizer.model_max_length] for input in inputs]
|
| 542 |
+
labels = [label[: self.tokenizer.model_max_length] for label in labels]
|
| 543 |
+
return inputs, labels
|
| 544 |
+
|
| 545 |
+
def __batchify_sequence(
|
| 546 |
+
self, inputs: List[torch.Tensor], labels: List[torch.Tensor]
|
| 547 |
+
) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
|
| 548 |
+
batch_size = len(inputs)
|
| 549 |
+
device = inputs[0].device
|
| 550 |
+
hidden_size = inputs[0].shape[1]
|
| 551 |
+
max_length = max(inputs[k].shape[0] for k in range(batch_size))
|
| 552 |
+
attention_mask = torch.ones(
|
| 553 |
+
(batch_size, max_length), dtype=torch.bool, device=device
|
| 554 |
+
)
|
| 555 |
+
|
| 556 |
+
inputs_p, labels_p = [], []
|
| 557 |
+
for k in range(batch_size):
|
| 558 |
+
size_pk = max_length - inputs[k].shape[0]
|
| 559 |
+
inputs_pk = torch.zeros(
|
| 560 |
+
(size_pk, hidden_size), dtype=inputs[k].dtype, device=device
|
| 561 |
+
)
|
| 562 |
+
labels_pk = torch.full(
|
| 563 |
+
(size_pk,), IGNORE_INDEX, dtype=labels[k].dtype, device=device
|
| 564 |
+
)
|
| 565 |
+
if self.tokenizer.padding_side == "right":
|
| 566 |
+
attention_mask[k, inputs[k].shape[0] :] = False
|
| 567 |
+
inputs_pk = torch.cat([inputs[k], inputs_pk], dim=0)
|
| 568 |
+
labels_pk = torch.cat([labels[k], labels_pk], dim=0)
|
| 569 |
+
else:
|
| 570 |
+
attention_mask[k, : -inputs[k].shape[0]] = False
|
| 571 |
+
inputs_pk = torch.cat([inputs_pk, inputs[k]], dim=0)
|
| 572 |
+
labels_pk = torch.cat([labels_pk, labels[k]], dim=0)
|
| 573 |
+
inputs_p.append(inputs_pk)
|
| 574 |
+
labels_p.append(labels_pk)
|
| 575 |
+
|
| 576 |
+
inputs = torch.stack(inputs_p, dim=0)
|
| 577 |
+
labels = torch.stack(labels_p, dim=0)
|
| 578 |
+
return inputs, labels, attention_mask
|
| 579 |
+
|
| 580 |
+
@torch.inference_mode()
|
| 581 |
+
def generate(
|
| 582 |
+
self,
|
| 583 |
+
input_ids: Optional[torch.FloatTensor] = None,
|
| 584 |
+
media: Optional[Dict[str, List[torch.Tensor]]] = None,
|
| 585 |
+
media_config: Dict[str, Dict[str, Any]] = None,
|
| 586 |
+
attention_mask: Optional[torch.LongTensor] = None,
|
| 587 |
+
quant_llm: Optional[bool] = True,
|
| 588 |
+
**generation_kwargs,
|
| 589 |
+
):
|
| 590 |
+
inputs_embeds, _, attention_mask = self._embed(
|
| 591 |
+
input_ids, media, media_config, None, attention_mask
|
| 592 |
+
)
|
| 593 |
+
return self.llm.generate(
|
| 594 |
+
inputs_embeds=inputs_embeds,
|
| 595 |
+
attention_mask=attention_mask,
|
| 596 |
+
quant_llm=quant_llm,
|
| 597 |
+
**generation_kwargs,
|
| 598 |
+
)
|
| 599 |
+
|
| 600 |
+
@torch.inference_mode()
|
| 601 |
+
def generate_content(
|
| 602 |
+
self,
|
| 603 |
+
prompt: Union[str, List],
|
| 604 |
+
generation_config: Optional[GenerationConfig] = None,
|
| 605 |
+
quant_llm: Optional[bool] = True,
|
| 606 |
+
) -> str:
|
| 607 |
+
# TODO(zhijianl): Support directly taking conversation as input
|
| 608 |
+
conversation = [{"from": "human", "value": prompt}]
|
| 609 |
+
|
| 610 |
+
# Extract media from the conversation
|
| 611 |
+
|
| 612 |
+
# TODO (extract and preprocess should be done together, as the preprocess of image and video can be different, i.e. when dynamic res is used)
|
| 613 |
+
media = extract_media(conversation, self.config)
|
| 614 |
+
|
| 615 |
+
# Process media
|
| 616 |
+
media_config = defaultdict(dict)
|
| 617 |
+
for name in media:
|
| 618 |
+
if name == "image":
|
| 619 |
+
if len(media["image"]) == 1 and self.config.image_aspect_ratio in [
|
| 620 |
+
"dynamic",
|
| 621 |
+
"dynamic_s2",
|
| 622 |
+
]:
|
| 623 |
+
self.config.image_processor = self.vision_tower.image_processor
|
| 624 |
+
if self.config.image_aspect_ratio == "dynamic":
|
| 625 |
+
images = process_image(
|
| 626 |
+
media["image"][0],
|
| 627 |
+
self.config,
|
| 628 |
+
None,
|
| 629 |
+
enable_dynamic_res=True,
|
| 630 |
+
).half()
|
| 631 |
+
conversation[0]["value"] = conversation[0]["value"].replace(
|
| 632 |
+
DEFAULT_IMAGE_TOKEN,
|
| 633 |
+
f"{DEFAULT_IMAGE_TOKEN}\n" * images.shape[0],
|
| 634 |
+
)
|
| 635 |
+
else:
|
| 636 |
+
if type(self.config.s2_scales) is str:
|
| 637 |
+
self.config.s2_scales = list(
|
| 638 |
+
map(int, self.config.s2_scales.split(","))
|
| 639 |
+
)
|
| 640 |
+
images, block_sizes = process_image(
|
| 641 |
+
media["image"][0], self.config, None, enable_dynamic_s2=True
|
| 642 |
+
)
|
| 643 |
+
images = images.half()
|
| 644 |
+
media_config[name]["block_sizes"] = [block_sizes]
|
| 645 |
+
else:
|
| 646 |
+
images = process_images(
|
| 647 |
+
media["image"], self.vision_tower.image_processor, self.config
|
| 648 |
+
).half()
|
| 649 |
+
media[name] = [image for image in images]
|
| 650 |
+
elif name == "video":
|
| 651 |
+
media[name] = [
|
| 652 |
+
process_images(
|
| 653 |
+
images, self.vision_tower.image_processor, self.config
|
| 654 |
+
).half()
|
| 655 |
+
for images in media[name]
|
| 656 |
+
]
|
| 657 |
+
else:
|
| 658 |
+
raise ValueError(f"Unsupported media type: {name}")
|
| 659 |
+
|
| 660 |
+
# Tokenize the conversation
|
| 661 |
+
input_ids = (
|
| 662 |
+
tokenize_conversation(
|
| 663 |
+
conversation, self.tokenizer, add_generation_prompt=True
|
| 664 |
+
)
|
| 665 |
+
.cuda()
|
| 666 |
+
.unsqueeze(0)
|
| 667 |
+
)
|
| 668 |
+
|
| 669 |
+
# Set up the generation config
|
| 670 |
+
generation_config = generation_config or self.default_generation_config
|
| 671 |
+
# Generate the response
|
| 672 |
+
try:
|
| 673 |
+
output_ids = self.generate(
|
| 674 |
+
input_ids=input_ids,
|
| 675 |
+
media=media,
|
| 676 |
+
media_config=media_config,
|
| 677 |
+
generation_config=generation_config,
|
| 678 |
+
quant_llm=quant_llm,
|
| 679 |
+
)
|
| 680 |
+
except ValueError:
|
| 681 |
+
if not generation_config.do_sample:
|
| 682 |
+
raise
|
| 683 |
+
# FIXME(zhijianl): This is a temporary workaround for the sampling issue
|
| 684 |
+
logging.warning(
|
| 685 |
+
"Generation failed with sampling, retrying with greedy decoding."
|
| 686 |
+
)
|
| 687 |
+
generation_config.do_sample = False
|
| 688 |
+
output_ids = self.generate(
|
| 689 |
+
input_ids=input_ids,
|
| 690 |
+
media=media,
|
| 691 |
+
media_config=media_config,
|
| 692 |
+
generation_config=generation_config,
|
| 693 |
+
)
|
| 694 |
+
|
| 695 |
+
# Decode the response
|
| 696 |
+
response = self.tokenizer.decode(
|
| 697 |
+
output_ids[0], skip_special_tokens=True
|
| 698 |
+
).strip()
|
| 699 |
+
return response
|
| 700 |
+
|
| 701 |
+
@torch.inference_mode()
|
| 702 |
+
def benchmark(self, prompt: Union[str, List], quant_llm) -> None:
|
| 703 |
+
# TODO(zhijianl): Support directly taking conversation as input
|
| 704 |
+
conversation = [{"from": "human", "value": prompt}]
|
| 705 |
+
|
| 706 |
+
# Extract media from the conversation
|
| 707 |
+
|
| 708 |
+
# TODO (extract and preprocess should be done together, as the preprocess of image and video can be different, i.e. when dynamic res is used)
|
| 709 |
+
media = extract_media(conversation, self.config)
|
| 710 |
+
|
| 711 |
+
# Process media
|
| 712 |
+
media_config = defaultdict(dict)
|
| 713 |
+
image_num = 0
|
| 714 |
+
for name in media:
|
| 715 |
+
if name == "image":
|
| 716 |
+
if len(media["image"]) == 1 and self.config.image_aspect_ratio in [
|
| 717 |
+
"dynamic",
|
| 718 |
+
"dynamic_s2",
|
| 719 |
+
]:
|
| 720 |
+
self.config.image_processor = self.vision_tower.image_processor
|
| 721 |
+
if self.config.image_aspect_ratio == "dynamic":
|
| 722 |
+
images = process_image(
|
| 723 |
+
media["image"][0],
|
| 724 |
+
self.config,
|
| 725 |
+
None,
|
| 726 |
+
enable_dynamic_res=True,
|
| 727 |
+
).half()
|
| 728 |
+
if len(images.shape) == 3:
|
| 729 |
+
images = images.reshape(1, *images.shape)
|
| 730 |
+
image_num += images.shape[0]
|
| 731 |
+
size = images.shape[1:]
|
| 732 |
+
conversation[0]["value"] = conversation[0]["value"].replace(
|
| 733 |
+
DEFAULT_IMAGE_TOKEN,
|
| 734 |
+
f"{DEFAULT_IMAGE_TOKEN}\n" * images.shape[0],
|
| 735 |
+
)
|
| 736 |
+
else:
|
| 737 |
+
if type(self.config.s2_scales) is str:
|
| 738 |
+
self.config.s2_scales = list(
|
| 739 |
+
map(int, self.config.s2_scales.split(","))
|
| 740 |
+
)
|
| 741 |
+
images, block_sizes = process_image(
|
| 742 |
+
media["image"][0], self.config, None, enable_dynamic_s2=True
|
| 743 |
+
)
|
| 744 |
+
images = images.half()
|
| 745 |
+
if len(images.shape) == 3:
|
| 746 |
+
images = images.reshape(1, *images.shape)
|
| 747 |
+
image_num += images.shape[0]
|
| 748 |
+
size = images.shape[1:]
|
| 749 |
+
media_config[name]["block_sizes"] = [block_sizes]
|
| 750 |
+
else:
|
| 751 |
+
images = process_images(
|
| 752 |
+
media["image"], self.vision_tower.image_processor, self.config
|
| 753 |
+
).half()
|
| 754 |
+
image_num += images.shape[0]
|
| 755 |
+
size = images.shape[1:]
|
| 756 |
+
media[name] = [image for image in images]
|
| 757 |
+
elif name == "video":
|
| 758 |
+
media[name] = [
|
| 759 |
+
process_images(
|
| 760 |
+
images, self.vision_tower.image_processor, self.config
|
| 761 |
+
).half()
|
| 762 |
+
for images in media[name]
|
| 763 |
+
]
|
| 764 |
+
for images in media[name]:
|
| 765 |
+
image_num += images.shape[0]
|
| 766 |
+
size = images.shape[1:]
|
| 767 |
+
else:
|
| 768 |
+
raise ValueError(f"Unsupported media type: {name}")
|
| 769 |
+
|
| 770 |
+
# Tokenize the conversation
|
| 771 |
+
input_ids = (
|
| 772 |
+
tokenize_conversation(
|
| 773 |
+
conversation, self.tokenizer, add_generation_prompt=True
|
| 774 |
+
)
|
| 775 |
+
.cuda()
|
| 776 |
+
.unsqueeze(0)
|
| 777 |
+
)
|
| 778 |
+
|
| 779 |
+
# Set up the generation config
|
| 780 |
+
for i in range(10):
|
| 781 |
+
torch.cuda.synchronize()
|
| 782 |
+
t_st = time()
|
| 783 |
+
inputs_embeds, _, attention_mask = self._embed(
|
| 784 |
+
input_ids, media, media_config, None, None
|
| 785 |
+
)
|
| 786 |
+
torch.cuda.synchronize()
|
| 787 |
+
t_ed = time()
|
| 788 |
+
torch.cuda.empty_cache()
|
| 789 |
+
print(
|
| 790 |
+
"Time of vision tower and others is {:.5f} s for {} images ({} x {} x {})".format(
|
| 791 |
+
t_ed - t_st, image_num, size[0], size[1], size[2]
|
| 792 |
+
)
|
| 793 |
+
)
|
| 794 |
+
output = self.llm.benchmark(
|
| 795 |
+
inputs_embeds=inputs_embeds,
|
| 796 |
+
attention_mask=attention_mask,
|
| 797 |
+
quant_llm=quant_llm,
|
| 798 |
+
)
|
| 799 |
+
# response = self.tokenizer.decode(output, skip_special_tokens=True).strip()
|
| 800 |
+
return
|
| 801 |
+
|
| 802 |
+
@property
|
| 803 |
+
def default_generation_config(self) -> GenerationConfig:
|
| 804 |
+
generation_config = copy.deepcopy(self.generation_config or GenerationConfig())
|
| 805 |
+
if self.tokenizer.eos_token_id is None:
|
| 806 |
+
raise ValueError("Tokenizer must have an EOS token")
|
| 807 |
+
if generation_config.max_length == GenerationConfig().max_length:
|
| 808 |
+
generation_config.max_length = self.tokenizer.model_max_length
|
| 809 |
+
if generation_config.pad_token_id is None:
|
| 810 |
+
generation_config.pad_token_id = (
|
| 811 |
+
self.tokenizer.pad_token_id or self.tokenizer.eos_token_id
|
| 812 |
+
)
|
| 813 |
+
if generation_config.bos_token_id is None:
|
| 814 |
+
generation_config.bos_token_id = (
|
| 815 |
+
self.tokenizer.bos_token_id or self.tokenizer.eos_token_id
|
| 816 |
+
)
|
| 817 |
+
if generation_config.eos_token_id is None:
|
| 818 |
+
generation_config.eos_token_id = self.tokenizer.stop_token_ids
|
| 819 |
+
return generation_config
|
| 820 |
+
|
| 821 |
+
# Prepare media
|
| 822 |
+
|
| 823 |
+
# Process media
|
| 824 |
+
@torch.inference_mode()
|
| 825 |
+
def prepare_media(self, conversation):
|
| 826 |
+
media = extract_media(conversation, self.config)
|
| 827 |
+
|
| 828 |
+
# Process media
|
| 829 |
+
media_config = defaultdict(dict)
|
| 830 |
+
for name in media:
|
| 831 |
+
if name == "image":
|
| 832 |
+
if len(media["image"]) == 1 and self.config.image_aspect_ratio in [
|
| 833 |
+
"dynamic",
|
| 834 |
+
"dynamic_s2",
|
| 835 |
+
]:
|
| 836 |
+
self.config.image_processor = self.vision_tower.image_processor
|
| 837 |
+
if self.config.image_aspect_ratio == "dynamic":
|
| 838 |
+
images = process_image(
|
| 839 |
+
media["image"][0],
|
| 840 |
+
self.config,
|
| 841 |
+
None,
|
| 842 |
+
enable_dynamic_res=True,
|
| 843 |
+
).half()
|
| 844 |
+
conversation[0]["value"] = conversation[0]["value"].replace(
|
| 845 |
+
DEFAULT_IMAGE_TOKEN,
|
| 846 |
+
f"{DEFAULT_IMAGE_TOKEN}\n" * images.shape[0],
|
| 847 |
+
)
|
| 848 |
+
else:
|
| 849 |
+
if type(self.config.s2_scales) is str:
|
| 850 |
+
self.config.s2_scales = list(
|
| 851 |
+
map(int, self.config.s2_scales.split(","))
|
| 852 |
+
)
|
| 853 |
+
images, block_sizes = process_image(
|
| 854 |
+
media["image"][0], self.config, None, enable_dynamic_s2=True
|
| 855 |
+
)
|
| 856 |
+
images = images.half()
|
| 857 |
+
media_config[name]["block_sizes"] = [block_sizes]
|
| 858 |
+
else:
|
| 859 |
+
images = process_images(
|
| 860 |
+
media["image"], self.vision_tower.image_processor, self.config
|
| 861 |
+
).half()
|
| 862 |
+
media[name] = [image for image in images]
|
| 863 |
+
elif name == "video":
|
| 864 |
+
media[name] = [
|
| 865 |
+
process_images(
|
| 866 |
+
images, self.vision_tower.image_processor, self.config
|
| 867 |
+
).half()
|
| 868 |
+
for images in media[name]
|
| 869 |
+
]
|
| 870 |
+
else:
|
| 871 |
+
raise ValueError(f"Unsupported media type: {name}")
|
| 872 |
+
return media, media_config
|
| 873 |
+
|
| 874 |
+
@torch.inference_mode()
|
| 875 |
+
def stream_gen(
|
| 876 |
+
self,
|
| 877 |
+
input_ids,
|
| 878 |
+
media,
|
| 879 |
+
media_cfg,
|
| 880 |
+
start_pos,
|
| 881 |
+
chunk_prefilling,
|
| 882 |
+
quant_llm,
|
| 883 |
+
attention_mask=None,
|
| 884 |
+
) -> str:
|
| 885 |
+
if media is None:
|
| 886 |
+
inputs_embeds = self.llm.model.embed_tokens(input_ids)
|
| 887 |
+
else:
|
| 888 |
+
image_num = torch.sum(input_ids == 151649)
|
| 889 |
+
if image_num == 1 and self.config.image_aspect_ratio == "dynamic":
|
| 890 |
+
patch_num = len(media["image"])
|
| 891 |
+
new_input_ids = []
|
| 892 |
+
for i, id in enumerate(input_ids[0]):
|
| 893 |
+
if id == 151649:
|
| 894 |
+
new_input_ids.extend(input_ids[0, 0:i])
|
| 895 |
+
new_input_ids.extend([198, 151649, 198] * patch_num)
|
| 896 |
+
new_input_ids.extend(input_ids[0, i + 1 :])
|
| 897 |
+
break
|
| 898 |
+
input_ids = torch.tensor(
|
| 899 |
+
[new_input_ids], dtype=torch.int, device="cuda"
|
| 900 |
+
)
|
| 901 |
+
inputs_embeds, _, _ = self._embed(
|
| 902 |
+
input_ids, media, media_cfg, None, attention_mask=None
|
| 903 |
+
)
|
| 904 |
+
length = inputs_embeds.shape[1]
|
| 905 |
+
if quant_llm:
|
| 906 |
+
out = self.llm(None, start_pos, inputs_embeds, chunk_prefilling)
|
| 907 |
+
else:
|
| 908 |
+
out = self.llm.forwardfp16(None, start_pos, inputs_embeds, chunk_prefilling)
|
| 909 |
+
return out, length
|
llm-awq/tinychat/models/qwen2.py
ADDED
|
@@ -0,0 +1,511 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Modified from https://github.com/huggingface/transformers/blob/main/src/transformers/models/qwen2/modeling_qwen2.py
|
| 2 |
+
"""PyTorch Qwen2 model."""
|
| 3 |
+
|
| 4 |
+
import math
|
| 5 |
+
from typing import List, Optional, Tuple, Union
|
| 6 |
+
|
| 7 |
+
import torch
|
| 8 |
+
import torch.utils.checkpoint
|
| 9 |
+
from torch import nn
|
| 10 |
+
import awq_inference_engine
|
| 11 |
+
from torch.nn import BCEWithLogitsLoss, CrossEntropyLoss, MSELoss
|
| 12 |
+
from transformers.models.qwen2.configuration_qwen2 import Qwen2Config
|
| 13 |
+
from transformers.activations import ACT2FN
|
| 14 |
+
import tinychat
|
| 15 |
+
import torch.nn.functional as F
|
| 16 |
+
import time
|
| 17 |
+
from tqdm import tqdm
|
| 18 |
+
from transformers import GenerationMixin
|
| 19 |
+
from transformers.models.qwen2 import Qwen2ForCausalLM
|
| 20 |
+
from flash_attn import flash_attn_func
|
| 21 |
+
|
| 22 |
+
max_batch_size = tinychat.utils.constants.max_batch_size
|
| 23 |
+
max_seq_len = tinychat.utils.constants.max_seq_len
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
class Qwen2RMSNorm(nn.Module):
|
| 27 |
+
def __init__(self, dim: int, eps: float = 1e-6):
|
| 28 |
+
super().__init__()
|
| 29 |
+
self.eps = eps
|
| 30 |
+
self.weight = nn.Parameter(torch.ones(dim))
|
| 31 |
+
|
| 32 |
+
def _norm(self, x):
|
| 33 |
+
return x * torch.rsqrt(x.pow(2).mean(-1, keepdim=True) + self.eps)
|
| 34 |
+
|
| 35 |
+
def forward(self, x):
|
| 36 |
+
output = torch.empty_like(x)
|
| 37 |
+
awq_inference_engine.layernorm_forward_cuda(x, self.weight, output, self.eps)
|
| 38 |
+
return output
|
| 39 |
+
|
| 40 |
+
|
| 41 |
+
def precompute_freqs_cis(
|
| 42 |
+
dim: int, end: int, theta: float = 10000.0, scale: float = 1.0
|
| 43 |
+
):
|
| 44 |
+
freqs = 1.0 / (theta ** (torch.arange(0, dim, 2)[: (dim // 2)].float() / dim))
|
| 45 |
+
t = torch.arange(end, device=freqs.device) # type: ignore
|
| 46 |
+
freqs = torch.outer(t * scale, freqs).float() # type: ignore
|
| 47 |
+
|
| 48 |
+
freqs_cis = torch.polar(torch.ones_like(freqs), freqs) # complex64
|
| 49 |
+
return freqs_cis
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def precompute_freqs(
|
| 53 |
+
dim: int, end: int, theta: float = 10000.0, scale: float = 1.0, device=None
|
| 54 |
+
):
|
| 55 |
+
inv_freq = 1.0 / (theta ** (torch.arange(0, dim, 2).float().to(device) / dim))
|
| 56 |
+
seq = torch.arange(end, dtype=inv_freq.dtype, device=device)
|
| 57 |
+
freqs = torch.einsum("i , j -> i j", seq, inv_freq)
|
| 58 |
+
freqs = freqs.reshape(freqs.shape[0], 1, 1, -1)
|
| 59 |
+
return torch.cat((freqs, freqs), dim=-1)
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def reshape_for_broadcast(freqs_cis: torch.Tensor, x: torch.Tensor):
|
| 63 |
+
ndim = x.ndim
|
| 64 |
+
assert 0 <= 1 < ndim
|
| 65 |
+
assert freqs_cis.shape == (x.shape[1], x.shape[-1])
|
| 66 |
+
shape = [d if i == 1 or i == ndim - 1 else 1 for i, d in enumerate(x.shape)]
|
| 67 |
+
return freqs_cis.view(*shape)
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def apply_rotary_emb(
|
| 71 |
+
xq: torch.Tensor,
|
| 72 |
+
xk: torch.Tensor,
|
| 73 |
+
freqs_cis: torch.Tensor,
|
| 74 |
+
) -> Tuple[torch.Tensor, torch.Tensor]:
|
| 75 |
+
# xq_ = torch.view_as_complex(xq.float().reshape(*xq.shape[:-1], -1, 2))
|
| 76 |
+
# k_ = torch.view_as_complex(xk.float().reshape(*xk.shape[:-1], -1, 2))
|
| 77 |
+
xq_ = torch.view_as_complex(
|
| 78 |
+
xq.float().reshape(*xq.shape[:-1], 2, -1).transpose(-2, -1).contiguous()
|
| 79 |
+
)
|
| 80 |
+
xk_ = torch.view_as_complex(
|
| 81 |
+
xk.float().reshape(*xk.shape[:-1], 2, -1).transpose(-2, -1).contiguous()
|
| 82 |
+
)
|
| 83 |
+
freqs_cis = reshape_for_broadcast(freqs_cis, xq_)
|
| 84 |
+
xq_out = torch.view_as_real(xq_ * freqs_cis).transpose(-2, -1).flatten(3)
|
| 85 |
+
xk_out = torch.view_as_real(xk_ * freqs_cis).transpose(-2, -1).flatten(3)
|
| 86 |
+
return xq_out.type_as(xq), xk_out.type_as(xk)
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
class Qwen2MLP(nn.Module):
|
| 90 |
+
def __init__(self, config):
|
| 91 |
+
super().__init__()
|
| 92 |
+
self.hidden_size = config.hidden_size
|
| 93 |
+
self.intermediate_size = config.intermediate_size
|
| 94 |
+
self.gate_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
|
| 95 |
+
self.up_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
|
| 96 |
+
self.down_proj = nn.Linear(self.intermediate_size, self.hidden_size, bias=False)
|
| 97 |
+
self.act_fn = ACT2FN[config.hidden_act]
|
| 98 |
+
|
| 99 |
+
def forward(self, hidden_state):
|
| 100 |
+
return self.down_proj(
|
| 101 |
+
self.act_fn(self.gate_proj(hidden_state)) * self.up_proj(hidden_state)
|
| 102 |
+
)
|
| 103 |
+
|
| 104 |
+
|
| 105 |
+
# Copied from transformers.models.llama.modeling_llama.repeat_kv
|
| 106 |
+
def repeat_kv(x: torch.Tensor, n_rep: int) -> torch.Tensor:
|
| 107 |
+
"""
|
| 108 |
+
This is the equivalent of torch.repeat_interleave(x, dim=1, repeats=n_rep). The hidden states go from (batch,
|
| 109 |
+
num_key_value_heads, seqlen, head_dim) to (batch, num_attention_heads, seqlen, head_dim)
|
| 110 |
+
"""
|
| 111 |
+
batch, num_key_value_heads, slen, head_dim = x.shape
|
| 112 |
+
if n_rep == 1:
|
| 113 |
+
return x
|
| 114 |
+
x = x[:, :, None, :, :].expand(batch, num_key_value_heads, n_rep, slen, head_dim)
|
| 115 |
+
return x.reshape(batch, num_key_value_heads * n_rep, slen, head_dim)
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
class Qwen2AttentionFused(nn.Module):
|
| 119 |
+
"""
|
| 120 |
+
Multi-headed attention from 'Attention Is All You Need' paper. Modified to use sliding window attention: Longformer
|
| 121 |
+
and "Generating Long Sequences with Sparse Transformers".
|
| 122 |
+
"""
|
| 123 |
+
|
| 124 |
+
def __init__(self, config: Qwen2Config, layer_idx: Optional[int] = None):
|
| 125 |
+
super().__init__()
|
| 126 |
+
self.args = config
|
| 127 |
+
self.layer_idx = layer_idx
|
| 128 |
+
if layer_idx is None:
|
| 129 |
+
print(
|
| 130 |
+
f"Instantiating {self.__class__.__name__} without passing `layer_idx` is not recommended and will "
|
| 131 |
+
"to errors during the forward call, if caching is used. Please make sure to provide a `layer_idx` "
|
| 132 |
+
"when creating this class."
|
| 133 |
+
)
|
| 134 |
+
|
| 135 |
+
self.hidden_size = config.hidden_size
|
| 136 |
+
self.num_heads = config.num_attention_heads
|
| 137 |
+
self.head_dim = self.hidden_size // self.num_heads
|
| 138 |
+
self.num_key_value_heads = config.num_key_value_heads
|
| 139 |
+
self.num_key_value_groups = self.num_heads // self.num_key_value_heads
|
| 140 |
+
self.max_position_embeddings = config.max_position_embeddings
|
| 141 |
+
self.rope_theta = config.rope_theta
|
| 142 |
+
self.is_causal = True
|
| 143 |
+
self.attention_dropout = config.attention_dropout
|
| 144 |
+
self.rope_scaling = config.rope_scaling
|
| 145 |
+
if self.rope_scaling is None:
|
| 146 |
+
self.rope_scaling = 1.0
|
| 147 |
+
elif isinstance(self.rope_scaling, dict):
|
| 148 |
+
self.rope_scaling = self.rope_scaling.get("factor", 1.0)
|
| 149 |
+
|
| 150 |
+
if (self.head_dim * self.num_heads) != self.hidden_size:
|
| 151 |
+
raise ValueError(
|
| 152 |
+
f"hidden_size must be divisible by num_heads (got `hidden_size`: {self.hidden_size}"
|
| 153 |
+
f" and `num_heads`: {self.num_heads})."
|
| 154 |
+
)
|
| 155 |
+
self.q_proj = nn.Linear(
|
| 156 |
+
self.hidden_size, self.num_heads * self.head_dim, bias=True
|
| 157 |
+
)
|
| 158 |
+
self.k_proj = nn.Linear(
|
| 159 |
+
self.hidden_size, self.num_key_value_heads * self.head_dim, bias=True
|
| 160 |
+
)
|
| 161 |
+
self.v_proj = nn.Linear(
|
| 162 |
+
self.hidden_size, self.num_key_value_heads * self.head_dim, bias=True
|
| 163 |
+
)
|
| 164 |
+
self.o_proj = nn.Linear(
|
| 165 |
+
self.num_heads * self.head_dim, self.hidden_size, bias=False
|
| 166 |
+
)
|
| 167 |
+
self.kv_max_seq_len = min(max_seq_len, self.max_position_embeddings)
|
| 168 |
+
# following fastertransformer definition
|
| 169 |
+
self.cache_v = (
|
| 170 |
+
torch.zeros(
|
| 171 |
+
(
|
| 172 |
+
max_batch_size,
|
| 173 |
+
self.num_key_value_heads,
|
| 174 |
+
# args.max_position_embeddings,
|
| 175 |
+
self.kv_max_seq_len,
|
| 176 |
+
self.head_dim,
|
| 177 |
+
)
|
| 178 |
+
)
|
| 179 |
+
.cuda()
|
| 180 |
+
.half()
|
| 181 |
+
) # added to half
|
| 182 |
+
# 8: pack 8 fp16 in FT, if fp32 then use 4
|
| 183 |
+
self.cache_k = (
|
| 184 |
+
torch.zeros(
|
| 185 |
+
(
|
| 186 |
+
max_batch_size,
|
| 187 |
+
self.num_key_value_heads,
|
| 188 |
+
self.head_dim // 8,
|
| 189 |
+
# args.max_position_embeddings,
|
| 190 |
+
self.kv_max_seq_len,
|
| 191 |
+
8,
|
| 192 |
+
)
|
| 193 |
+
)
|
| 194 |
+
.cuda()
|
| 195 |
+
.half()
|
| 196 |
+
) # added to half
|
| 197 |
+
|
| 198 |
+
def forward(
|
| 199 |
+
self,
|
| 200 |
+
x: torch.Tensor,
|
| 201 |
+
start_pos: int,
|
| 202 |
+
freqs: torch.Tensor,
|
| 203 |
+
mask: Optional[torch.Tensor],
|
| 204 |
+
chunk_prefilling: bool = False,
|
| 205 |
+
):
|
| 206 |
+
bsz, seqlen, _ = x.shape
|
| 207 |
+
|
| 208 |
+
query_states = self.q_proj(x)
|
| 209 |
+
key_states = self.k_proj(x)
|
| 210 |
+
value_states = self.v_proj(x)
|
| 211 |
+
|
| 212 |
+
if seqlen > 1:
|
| 213 |
+
xq = query_states.view(bsz, seqlen, self.num_heads, self.head_dim)
|
| 214 |
+
xk = key_states.view(bsz, seqlen, self.num_key_value_heads, self.head_dim)
|
| 215 |
+
xv = value_states.view(bsz, seqlen, self.num_key_value_heads, self.head_dim)
|
| 216 |
+
|
| 217 |
+
xq, xk = apply_rotary_emb(xq, xk, freqs_cis=freqs)
|
| 218 |
+
|
| 219 |
+
self.cache_k = self.cache_k.to(xq)
|
| 220 |
+
self.cache_v = self.cache_v.to(xq)
|
| 221 |
+
|
| 222 |
+
values_store = xv.transpose(2, 1)
|
| 223 |
+
|
| 224 |
+
keys_store = (
|
| 225 |
+
xk.reshape(bsz, seqlen, self.num_key_value_heads, self.head_dim // 8, 8)
|
| 226 |
+
.permute(0, 2, 3, 1, 4)
|
| 227 |
+
.contiguous()
|
| 228 |
+
)
|
| 229 |
+
|
| 230 |
+
self.cache_v[:bsz, :, start_pos : start_pos + seqlen, :] = values_store
|
| 231 |
+
self.cache_k[:bsz, :, :, start_pos : start_pos + seqlen, :] = keys_store
|
| 232 |
+
if chunk_prefilling:
|
| 233 |
+
keys = self.cache_k[:, :, :, 0 : start_pos + seqlen, :]
|
| 234 |
+
keys = (
|
| 235 |
+
keys.permute(0, 3, 1, 2, 4)
|
| 236 |
+
.reshape(
|
| 237 |
+
bsz, start_pos + seqlen, self.num_key_value_heads, self.head_dim
|
| 238 |
+
)
|
| 239 |
+
.contiguous()
|
| 240 |
+
)
|
| 241 |
+
values = self.cache_v[:, :, 0 : start_pos + seqlen, :]
|
| 242 |
+
values = (
|
| 243 |
+
values.transpose(2, 1)
|
| 244 |
+
.reshape(
|
| 245 |
+
bsz, start_pos + seqlen, self.num_key_value_heads, self.head_dim
|
| 246 |
+
)
|
| 247 |
+
.contiguous()
|
| 248 |
+
)
|
| 249 |
+
else:
|
| 250 |
+
keys = xk
|
| 251 |
+
values = xv
|
| 252 |
+
output = flash_attn_func(
|
| 253 |
+
q=xq,
|
| 254 |
+
k=keys,
|
| 255 |
+
v=values,
|
| 256 |
+
causal=True,
|
| 257 |
+
)
|
| 258 |
+
output = output.contiguous().view(bsz, seqlen, -1)
|
| 259 |
+
else:
|
| 260 |
+
xq = query_states.view(bsz, self.num_heads, self.head_dim)
|
| 261 |
+
xk = key_states.view(bsz, self.num_key_value_heads, self.head_dim)
|
| 262 |
+
xv = value_states.view(bsz, self.num_key_value_heads, self.head_dim)
|
| 263 |
+
|
| 264 |
+
output = awq_inference_engine.single_query_attention(
|
| 265 |
+
xq,
|
| 266 |
+
xk,
|
| 267 |
+
xv,
|
| 268 |
+
self.cache_k,
|
| 269 |
+
self.cache_v,
|
| 270 |
+
None,
|
| 271 |
+
# alibi position encodings
|
| 272 |
+
None,
|
| 273 |
+
start_pos,
|
| 274 |
+
self.head_dim,
|
| 275 |
+
self.rope_theta,
|
| 276 |
+
self.rope_scaling,
|
| 277 |
+
True,
|
| 278 |
+
)
|
| 279 |
+
output = output.reshape(bsz, 1, -1)
|
| 280 |
+
|
| 281 |
+
return self.o_proj(output)
|
| 282 |
+
|
| 283 |
+
|
| 284 |
+
class Qwen2DecoderLayer(nn.Module):
|
| 285 |
+
def __init__(self, config: Qwen2Config, layer_idx: int):
|
| 286 |
+
super().__init__()
|
| 287 |
+
self.hidden_size = config.hidden_size
|
| 288 |
+
|
| 289 |
+
self.self_attn = Qwen2AttentionFused(config, layer_idx)
|
| 290 |
+
|
| 291 |
+
self.mlp = Qwen2MLP(config)
|
| 292 |
+
self.input_layernorm = Qwen2RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
| 293 |
+
self.post_attention_layernorm = Qwen2RMSNorm(
|
| 294 |
+
config.hidden_size, eps=config.rms_norm_eps
|
| 295 |
+
)
|
| 296 |
+
|
| 297 |
+
def forward(
|
| 298 |
+
self,
|
| 299 |
+
x: torch.Tensor,
|
| 300 |
+
start_pos: int,
|
| 301 |
+
freqs: torch.Tensor,
|
| 302 |
+
mask: Optional[torch.Tensor],
|
| 303 |
+
chunk_prefilling: bool = False,
|
| 304 |
+
):
|
| 305 |
+
residual = x
|
| 306 |
+
x = self.input_layernorm(x)
|
| 307 |
+
|
| 308 |
+
# Self Attention
|
| 309 |
+
x = self.self_attn(
|
| 310 |
+
x=x,
|
| 311 |
+
start_pos=start_pos,
|
| 312 |
+
freqs=freqs,
|
| 313 |
+
mask=mask,
|
| 314 |
+
chunk_prefilling=chunk_prefilling,
|
| 315 |
+
)
|
| 316 |
+
x = residual + x
|
| 317 |
+
|
| 318 |
+
# Fully Connected
|
| 319 |
+
residual = x
|
| 320 |
+
x = self.post_attention_layernorm(x)
|
| 321 |
+
x = self.mlp(x)
|
| 322 |
+
x = residual + x
|
| 323 |
+
return x
|
| 324 |
+
|
| 325 |
+
|
| 326 |
+
class Qwen2Model(nn.Module):
|
| 327 |
+
def __init__(self, config: Qwen2Config):
|
| 328 |
+
super().__init__()
|
| 329 |
+
self.padding_idx = config.pad_token_id
|
| 330 |
+
self.vocab_size = config.vocab_size
|
| 331 |
+
|
| 332 |
+
self.embed_tokens = nn.Embedding(
|
| 333 |
+
config.vocab_size, config.hidden_size, self.padding_idx
|
| 334 |
+
)
|
| 335 |
+
self.layers = nn.ModuleList(
|
| 336 |
+
[
|
| 337 |
+
Qwen2DecoderLayer(config, layer_idx)
|
| 338 |
+
for layer_idx in range(config.num_hidden_layers)
|
| 339 |
+
]
|
| 340 |
+
)
|
| 341 |
+
self.norm = Qwen2RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
| 342 |
+
# Note (Haotian): rope_theta has to be defined here, otherwise context stage is wrong.
|
| 343 |
+
rope_scale = config.rope_scaling
|
| 344 |
+
if rope_scale is None:
|
| 345 |
+
rope_scale = 1.0
|
| 346 |
+
else:
|
| 347 |
+
rope_scale = 1.0 / rope_scale["factor"]
|
| 348 |
+
self.freqs = precompute_freqs(
|
| 349 |
+
config.hidden_size // config.num_attention_heads,
|
| 350 |
+
config.max_position_embeddings * 2,
|
| 351 |
+
config.rope_theta,
|
| 352 |
+
rope_scale,
|
| 353 |
+
)
|
| 354 |
+
self.freqs_cis = precompute_freqs_cis(
|
| 355 |
+
config.hidden_size // config.num_attention_heads,
|
| 356 |
+
config.max_position_embeddings * 2,
|
| 357 |
+
config.rope_theta,
|
| 358 |
+
rope_scale,
|
| 359 |
+
)
|
| 360 |
+
|
| 361 |
+
def forward(
|
| 362 |
+
self,
|
| 363 |
+
input_ids: torch.LongTensor = None,
|
| 364 |
+
start_pos: Optional[int] = 0,
|
| 365 |
+
inputs_embeds: Optional[torch.FloatTensor] = None,
|
| 366 |
+
chunk_prefilling: bool = False,
|
| 367 |
+
):
|
| 368 |
+
if inputs_embeds is None:
|
| 369 |
+
inputs_embeds = self.embed_tokens(input_ids)
|
| 370 |
+
seqlen = inputs_embeds.shape[1]
|
| 371 |
+
|
| 372 |
+
self.freqs = self.freqs.to(inputs_embeds.device)
|
| 373 |
+
freqs = self.freqs[start_pos : start_pos + seqlen]
|
| 374 |
+
|
| 375 |
+
mask = None
|
| 376 |
+
if seqlen > 1:
|
| 377 |
+
mask = torch.full(
|
| 378 |
+
(1, 1, seqlen, seqlen), float("-inf"), device=inputs_embeds.device
|
| 379 |
+
)
|
| 380 |
+
mask = torch.triu(mask, diagonal=1).type_as(inputs_embeds)
|
| 381 |
+
if chunk_prefilling:
|
| 382 |
+
mask_history = torch.zeros(
|
| 383 |
+
(1, 1, seqlen, start_pos),
|
| 384 |
+
dtype=torch.float16,
|
| 385 |
+
device=inputs_embeds.device,
|
| 386 |
+
).type_as(inputs_embeds)
|
| 387 |
+
mask = torch.cat((mask_history, mask), dim=-1)
|
| 388 |
+
x = inputs_embeds
|
| 389 |
+
|
| 390 |
+
for decoder_layer in self.layers:
|
| 391 |
+
x = decoder_layer(x, start_pos, freqs, mask, chunk_prefilling)
|
| 392 |
+
x = x[:, -1:, :]
|
| 393 |
+
x = self.norm(x)
|
| 394 |
+
|
| 395 |
+
return x
|
| 396 |
+
|
| 397 |
+
def forwardfp16(
|
| 398 |
+
self,
|
| 399 |
+
input_ids: torch.LongTensor = None,
|
| 400 |
+
start_pos: Optional[int] = 0,
|
| 401 |
+
inputs_embeds: Optional[torch.FloatTensor] = None,
|
| 402 |
+
chunk_prefilling: bool = False,
|
| 403 |
+
):
|
| 404 |
+
if inputs_embeds is None:
|
| 405 |
+
inputs_embeds = self.embed_tokens(input_ids)
|
| 406 |
+
seqlen = inputs_embeds.shape[1]
|
| 407 |
+
|
| 408 |
+
self.freqs_cis = self.freqs_cis.to(inputs_embeds.device)
|
| 409 |
+
freqs_cis = self.freqs_cis[start_pos : start_pos + seqlen]
|
| 410 |
+
|
| 411 |
+
mask = None
|
| 412 |
+
if seqlen > 1:
|
| 413 |
+
mask = torch.full(
|
| 414 |
+
(1, 1, seqlen, seqlen), float("-inf"), device=inputs_embeds.device
|
| 415 |
+
)
|
| 416 |
+
mask = torch.triu(mask, diagonal=1).type_as(inputs_embeds)
|
| 417 |
+
if chunk_prefilling:
|
| 418 |
+
mask_history = torch.zeros(
|
| 419 |
+
(1, 1, seqlen, start_pos),
|
| 420 |
+
dtype=torch.float16,
|
| 421 |
+
device=inputs_embeds.device,
|
| 422 |
+
).type_as(inputs_embeds)
|
| 423 |
+
mask = torch.cat((mask_history, mask), dim=-1)
|
| 424 |
+
x = inputs_embeds
|
| 425 |
+
|
| 426 |
+
for decoder_layer in self.layers:
|
| 427 |
+
x = decoder_layer(x, start_pos, freqs_cis, mask, chunk_prefilling)
|
| 428 |
+
x = x[:, -1:, :]
|
| 429 |
+
x = self.norm(x)
|
| 430 |
+
|
| 431 |
+
return x
|
| 432 |
+
|
| 433 |
+
|
| 434 |
+
class Qwen2ForCausalLM(Qwen2ForCausalLM):
|
| 435 |
+
def __init__(self, config):
|
| 436 |
+
|
| 437 |
+
def skip(*args, **kwargs):
|
| 438 |
+
pass
|
| 439 |
+
|
| 440 |
+
torch.nn.init.kaiming_uniform_ = skip
|
| 441 |
+
torch.nn.init.kaiming_normal_ = skip
|
| 442 |
+
torch.nn.init.uniform_ = skip
|
| 443 |
+
torch.nn.init.normal_ = skip
|
| 444 |
+
from transformers import modeling_utils
|
| 445 |
+
|
| 446 |
+
modeling_utils._init_weights = False
|
| 447 |
+
|
| 448 |
+
super().__init__(config)
|
| 449 |
+
self.model = Qwen2Model(config)
|
| 450 |
+
self.vocab_size = config.vocab_size
|
| 451 |
+
self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
|
| 452 |
+
self.config = config
|
| 453 |
+
|
| 454 |
+
@torch.inference_mode()
|
| 455 |
+
def forward(
|
| 456 |
+
self,
|
| 457 |
+
input_ids: torch.Tensor,
|
| 458 |
+
start_pos: int = 0,
|
| 459 |
+
inputs_embeds: torch.Tensor = None,
|
| 460 |
+
chunk_prefilling: bool = False,
|
| 461 |
+
quant=True,
|
| 462 |
+
):
|
| 463 |
+
if quant:
|
| 464 |
+
outputs = self.model(
|
| 465 |
+
input_ids=input_ids,
|
| 466 |
+
inputs_embeds=inputs_embeds,
|
| 467 |
+
start_pos=start_pos,
|
| 468 |
+
chunk_prefilling=chunk_prefilling,
|
| 469 |
+
)
|
| 470 |
+
else:
|
| 471 |
+
outputs = self.model.forwardfp16(
|
| 472 |
+
input_ids=input_ids,
|
| 473 |
+
inputs_embeds=inputs_embeds,
|
| 474 |
+
start_pos=start_pos,
|
| 475 |
+
chunk_prefilling=chunk_prefilling,
|
| 476 |
+
)
|
| 477 |
+
logits = self.lm_head(outputs)
|
| 478 |
+
return logits
|
| 479 |
+
|
| 480 |
+
def benchmark(self, inputs_embeds, attention_mask, max_output=128, quant_llm=True):
|
| 481 |
+
output_list = []
|
| 482 |
+
start_pos = 0
|
| 483 |
+
for i in range(10):
|
| 484 |
+
torch.cuda.synchronize()
|
| 485 |
+
tst = time.time()
|
| 486 |
+
token = self.forward(None, start_pos, inputs_embeds, quant=quant_llm)
|
| 487 |
+
torch.cuda.synchronize()
|
| 488 |
+
ted = time.time()
|
| 489 |
+
print(
|
| 490 |
+
"LLM TTFT: {:.6f} s for {} tokens".format(
|
| 491 |
+
(ted - tst), inputs_embeds.shape[1]
|
| 492 |
+
)
|
| 493 |
+
)
|
| 494 |
+
start_pos = inputs_embeds.shape[1]
|
| 495 |
+
token = torch.argmax(token, keepdim=True)[0]
|
| 496 |
+
output_list.append(token)
|
| 497 |
+
|
| 498 |
+
torch.cuda.synchronize()
|
| 499 |
+
tst = time.time()
|
| 500 |
+
for _ in range(max_output):
|
| 501 |
+
token = self.forward(token, start_pos)
|
| 502 |
+
token = torch.argmax(token, keepdim=True)[
|
| 503 |
+
0
|
| 504 |
+
] # Only fixed-length eager decoding is supported now
|
| 505 |
+
output_list.append(token)
|
| 506 |
+
start_pos += 1
|
| 507 |
+
torch.cuda.synchronize()
|
| 508 |
+
ted = time.time()
|
| 509 |
+
print("Decoding througput: {:.6f} tokens/s".format(max_output / (ted - tst)))
|
| 510 |
+
|
| 511 |
+
return torch.cat(output_list, dim=1)
|
llm-awq/tinychat/models/vila_llama.py
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import warnings
|
| 3 |
+
import shutil
|
| 4 |
+
import torch
|
| 5 |
+
import torch.nn as nn
|
| 6 |
+
from typing import List, Optional, Tuple, Union
|
| 7 |
+
import time
|
| 8 |
+
|
| 9 |
+
from transformers import AutoConfig, PreTrainedModel
|
| 10 |
+
from transformers.modeling_outputs import CausalLMOutputWithPast
|
| 11 |
+
|
| 12 |
+
from llava.model.utils import get_model_config
|
| 13 |
+
from llava.model.language_model.builder import build_llm_and_tokenizer
|
| 14 |
+
from llava.model.multimodal_encoder.builder import build_vision_tower
|
| 15 |
+
from llava.model.multimodal_projector.builder import build_mm_projector
|
| 16 |
+
from llava.model.llava_arch import LlavaMetaModel, LlavaMetaForCausalLM
|
| 17 |
+
from .llama import LlamaForCausalLM, Transformer
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
class VilaLlamaForCausalLM(LlavaMetaModel, LlavaMetaForCausalLM, PreTrainedModel):
|
| 21 |
+
def __init__(self, config):
|
| 22 |
+
super().__init__(config)
|
| 23 |
+
self.init_vlm(config)
|
| 24 |
+
|
| 25 |
+
def init_vlm(self, config=None, *args, **kwargs):
|
| 26 |
+
if (
|
| 27 |
+
hasattr(self, "llm")
|
| 28 |
+
or hasattr(self, "vision_tower")
|
| 29 |
+
or hasattr(self, "mm_projector")
|
| 30 |
+
):
|
| 31 |
+
# already initialized, skipped
|
| 32 |
+
return
|
| 33 |
+
|
| 34 |
+
model_dtype = getattr(config, "model_dtype", "torch.float16")
|
| 35 |
+
if not hasattr(config, "model_dtype"):
|
| 36 |
+
warnings.warn(
|
| 37 |
+
"model_dtype not found in config, defaulting to torch.float16."
|
| 38 |
+
)
|
| 39 |
+
config.model_dtype = model_dtype
|
| 40 |
+
|
| 41 |
+
# print("init_vlm(): config", config); input("DEBUG init_vlm")
|
| 42 |
+
cfgs = get_model_config(config)
|
| 43 |
+
if len(cfgs) == 3:
|
| 44 |
+
llm_cfg, vision_tower_cfg, mm_projector_cfg = cfgs
|
| 45 |
+
else:
|
| 46 |
+
raise ValueError(
|
| 47 |
+
"`llm_cfg` `mm_projector_cfg` `vision_tower_cfg` not found in the config."
|
| 48 |
+
)
|
| 49 |
+
# print("init_vlm():", cfgs); input("DEBUG init_vlm")
|
| 50 |
+
llm_cfg = AutoConfig.from_pretrained(llm_cfg)
|
| 51 |
+
|
| 52 |
+
# self.llm, self.tokenizer = build_llm_and_tokenizer(llm_cfg, config, *args, **kwargs)
|
| 53 |
+
self.llm = LlamaForCausalLM(llm_cfg)
|
| 54 |
+
self.vision_tower = build_vision_tower(vision_tower_cfg, config)
|
| 55 |
+
self.mm_projector = build_mm_projector(mm_projector_cfg, config)
|
| 56 |
+
|
| 57 |
+
self.post_config()
|
| 58 |
+
self.is_loaded = True
|
| 59 |
+
|
| 60 |
+
assert (
|
| 61 |
+
self.llm is not None
|
| 62 |
+
or self.vision_tower is not None
|
| 63 |
+
or self.mm_projector is not None
|
| 64 |
+
), "At least one of the components must be instantiated."
|
| 65 |
+
|
| 66 |
+
def forward(
|
| 67 |
+
self,
|
| 68 |
+
input_ids: torch.LongTensor = None,
|
| 69 |
+
start_pos: int = None,
|
| 70 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 71 |
+
position_ids: Optional[torch.LongTensor] = None,
|
| 72 |
+
past_key_values: Optional[List[torch.FloatTensor]] = None,
|
| 73 |
+
inputs_embeds: Optional[torch.FloatTensor] = None,
|
| 74 |
+
labels: Optional[torch.LongTensor] = None,
|
| 75 |
+
use_cache: Optional[bool] = None,
|
| 76 |
+
output_attentions: Optional[bool] = None,
|
| 77 |
+
output_hidden_states: Optional[bool] = None,
|
| 78 |
+
images: Optional[torch.FloatTensor] = None,
|
| 79 |
+
return_dict: Optional[bool] = None,
|
| 80 |
+
special_token: bool = False,
|
| 81 |
+
chunk_prefilling: bool = False,
|
| 82 |
+
) -> Union[Tuple, CausalLMOutputWithPast]:
|
| 83 |
+
self.freezed_module_patch()
|
| 84 |
+
if inputs_embeds is None:
|
| 85 |
+
(
|
| 86 |
+
_,
|
| 87 |
+
_,
|
| 88 |
+
_,
|
| 89 |
+
_,
|
| 90 |
+
inputs_embeds,
|
| 91 |
+
_,
|
| 92 |
+
) = self.prepare_inputs_labels_for_multimodal(
|
| 93 |
+
input_ids, position_ids, attention_mask, past_key_values, labels, images
|
| 94 |
+
)
|
| 95 |
+
if inputs_embeds is not None:
|
| 96 |
+
outputs = self.llm.forward(
|
| 97 |
+
tokens=None,
|
| 98 |
+
start_pos=start_pos,
|
| 99 |
+
inputs_embeds=inputs_embeds,
|
| 100 |
+
chunk_prefilling=chunk_prefilling,
|
| 101 |
+
)
|
| 102 |
+
else: # tokens
|
| 103 |
+
outputs = self.llm.forward(
|
| 104 |
+
tokens=input_ids,
|
| 105 |
+
start_pos=start_pos,
|
| 106 |
+
inputs_embeds=None,
|
| 107 |
+
chunk_prefilling=chunk_prefilling,
|
| 108 |
+
)
|
| 109 |
+
return outputs
|
llm-awq/tinychat/modules/fused_attn.py
ADDED
|
@@ -0,0 +1,634 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import math
|
| 2 |
+
import torch
|
| 3 |
+
import torch.nn as nn
|
| 4 |
+
from torch.nn import functional as F
|
| 5 |
+
from transformers.models.llama.modeling_llama import (
|
| 6 |
+
LlamaAttention,
|
| 7 |
+
LlamaRotaryEmbedding,
|
| 8 |
+
apply_rotary_pos_emb,
|
| 9 |
+
)
|
| 10 |
+
from typing import Optional
|
| 11 |
+
from awq.quantize.qmodule import WQLinear
|
| 12 |
+
import awq_inference_engine
|
| 13 |
+
from tinychat.models.llama import apply_rotary_emb
|
| 14 |
+
import gc
|
| 15 |
+
|
| 16 |
+
import tinychat.utils.constants
|
| 17 |
+
from flash_attn import flash_attn_func
|
| 18 |
+
from tinychat.models.llama import LlamaAttentionFused
|
| 19 |
+
from tinychat.models.qwen2 import Qwen2AttentionFused
|
| 20 |
+
|
| 21 |
+
max_batch_size = tinychat.utils.constants.max_batch_size
|
| 22 |
+
max_seq_len = tinychat.utils.constants.max_seq_len
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
class QuantLlamaRotaryEmbedding(nn.Module):
|
| 26 |
+
def __init__(self, dim, max_position_embeddings=2048, base=10000, device=None):
|
| 27 |
+
super().__init__()
|
| 28 |
+
|
| 29 |
+
self.dim = dim
|
| 30 |
+
self.max_position_embeddings = max_position_embeddings
|
| 31 |
+
self.base = base
|
| 32 |
+
inv_freq = 1.0 / (
|
| 33 |
+
self.base ** (torch.arange(0, self.dim, 2).float().to(device) / self.dim)
|
| 34 |
+
)
|
| 35 |
+
self.register_buffer("inv_freq", inv_freq)
|
| 36 |
+
# Build here to make `torch.jit.trace` work.
|
| 37 |
+
self._set_cos_sin_cache(
|
| 38 |
+
seq_len=max_position_embeddings,
|
| 39 |
+
device=self.inv_freq.device,
|
| 40 |
+
dtype=torch.get_default_dtype(),
|
| 41 |
+
)
|
| 42 |
+
|
| 43 |
+
def _set_cos_sin_cache(self, seq_len, device, dtype):
|
| 44 |
+
self.max_seq_len_cached = seq_len
|
| 45 |
+
t = torch.arange(
|
| 46 |
+
self.max_seq_len_cached, device=device, dtype=self.inv_freq.dtype
|
| 47 |
+
)
|
| 48 |
+
|
| 49 |
+
freqs = torch.einsum("i,j->ij", t, self.inv_freq)
|
| 50 |
+
# Different from paper, but it uses a different permutation in order to obtain the same calculation
|
| 51 |
+
# emb = torch.cat((freqs, freqs), dim=-1)
|
| 52 |
+
|
| 53 |
+
cos = freqs.cos()
|
| 54 |
+
sin = freqs.sin()
|
| 55 |
+
cache = torch.cat((cos, sin), dim=-1)
|
| 56 |
+
|
| 57 |
+
# self.register_buffer("cos_cached", emb.cos()[None, None, :, :].to(dtype), persistent=False)
|
| 58 |
+
# self.register_buffer("sin_cached", emb.sin()[None, None, :, :].to(dtype), persistent=False)
|
| 59 |
+
self.register_buffer("cos_sin_cache", cache.half(), persistent=False)
|
| 60 |
+
|
| 61 |
+
def forward(
|
| 62 |
+
self,
|
| 63 |
+
query: torch.Tensor,
|
| 64 |
+
key: torch.Tensor,
|
| 65 |
+
positions: torch.Tensor,
|
| 66 |
+
):
|
| 67 |
+
# Apply rotary embedding to the query and key before passing them
|
| 68 |
+
# to the attention op.
|
| 69 |
+
# print(positions.shape, query.shape, key.shape, self.cos_sin_cache.shape)
|
| 70 |
+
query = query.contiguous()
|
| 71 |
+
key = key.contiguous()
|
| 72 |
+
awq_inference_engine.rotary_embedding_neox(
|
| 73 |
+
positions,
|
| 74 |
+
query,
|
| 75 |
+
key,
|
| 76 |
+
self.dim,
|
| 77 |
+
self.cos_sin_cache,
|
| 78 |
+
)
|
| 79 |
+
return query, key
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
class QuantLlamaAttention(nn.Module):
|
| 83 |
+
"""Multi-headed attention from 'Attention Is All You Need' paper"""
|
| 84 |
+
|
| 85 |
+
def __init__(self, hidden_size, num_heads, qkv_proj, o_proj, dev):
|
| 86 |
+
super().__init__()
|
| 87 |
+
self.hidden_size = hidden_size
|
| 88 |
+
self.num_heads = num_heads
|
| 89 |
+
self.head_dim = hidden_size // num_heads
|
| 90 |
+
|
| 91 |
+
if (self.head_dim * num_heads) != self.hidden_size:
|
| 92 |
+
raise ValueError(
|
| 93 |
+
f"hidden_size must be divisible by num_heads (got `hidden_size`: {self.hidden_size}"
|
| 94 |
+
f" and `num_heads`: {num_heads})."
|
| 95 |
+
)
|
| 96 |
+
self.qkv_proj = qkv_proj
|
| 97 |
+
self.o_proj = o_proj
|
| 98 |
+
self.rotary_emb = QuantLlamaRotaryEmbedding(
|
| 99 |
+
self.head_dim, max_position_embeddings=2048, device=dev
|
| 100 |
+
)
|
| 101 |
+
|
| 102 |
+
def forward(
|
| 103 |
+
self,
|
| 104 |
+
hidden_states,
|
| 105 |
+
past_key_value=None,
|
| 106 |
+
attention_mask=None,
|
| 107 |
+
position_ids=None,
|
| 108 |
+
output_attentions=False,
|
| 109 |
+
use_cache=False,
|
| 110 |
+
):
|
| 111 |
+
"""Input shape: Batch x Time x Channel"""
|
| 112 |
+
|
| 113 |
+
bsz, q_len, _ = hidden_states.size()
|
| 114 |
+
|
| 115 |
+
qkv_states = self.qkv_proj(hidden_states)
|
| 116 |
+
qkv_states = qkv_states.view(bsz, q_len, 3, self.num_heads, self.head_dim)
|
| 117 |
+
|
| 118 |
+
# This updates the query and key states in-place, saving VRAM.
|
| 119 |
+
query_states, key_states, value_states = torch.split(qkv_states, 1, dim=2)
|
| 120 |
+
query_states, key_states = self.rotary_emb(
|
| 121 |
+
query_states, key_states, position_ids
|
| 122 |
+
)
|
| 123 |
+
|
| 124 |
+
del qkv_states
|
| 125 |
+
query_states = query_states.view(
|
| 126 |
+
bsz, q_len, self.num_heads, self.head_dim
|
| 127 |
+
).transpose(1, 2)
|
| 128 |
+
key_states = key_states.view(
|
| 129 |
+
bsz, q_len, self.num_heads, self.head_dim
|
| 130 |
+
).transpose(1, 2)
|
| 131 |
+
value_states = value_states.view(
|
| 132 |
+
bsz, q_len, self.num_heads, self.head_dim
|
| 133 |
+
).transpose(1, 2)
|
| 134 |
+
|
| 135 |
+
is_causal = past_key_value is None
|
| 136 |
+
|
| 137 |
+
kv_seq_len = q_len
|
| 138 |
+
if past_key_value is not None:
|
| 139 |
+
kv_seq_len += past_key_value[0].shape[-2]
|
| 140 |
+
|
| 141 |
+
value_states = value_states.to("cuda:0")
|
| 142 |
+
|
| 143 |
+
if past_key_value is not None:
|
| 144 |
+
# reuse k, v, self_attention
|
| 145 |
+
key_states = torch.cat([past_key_value[0], key_states], dim=2)
|
| 146 |
+
value_states = torch.cat([past_key_value[1], value_states], dim=2)
|
| 147 |
+
|
| 148 |
+
if use_cache:
|
| 149 |
+
# Since qkv_proj is fused, query_states etc will hold a reference to the original qkv_states tensor
|
| 150 |
+
# which can cause excessive memory usage by the cache. `contiguous` is a convenient way to workaround this.
|
| 151 |
+
key_states = key_states.contiguous()
|
| 152 |
+
value_states = value_states.contiguous()
|
| 153 |
+
query_states = query_states.contiguous()
|
| 154 |
+
|
| 155 |
+
past_key_value = (key_states, value_states) if use_cache else None
|
| 156 |
+
|
| 157 |
+
# with torch.backends.cuda.sdp_kernel(enable_math=False):
|
| 158 |
+
attn_output = F.scaled_dot_product_attention(
|
| 159 |
+
query_states, key_states, value_states, is_causal=is_causal
|
| 160 |
+
)
|
| 161 |
+
del query_states, key_states, value_states
|
| 162 |
+
|
| 163 |
+
attn_output = attn_output.transpose(1, 2).reshape(bsz, q_len, self.hidden_size)
|
| 164 |
+
attn_output = self.o_proj(attn_output)
|
| 165 |
+
|
| 166 |
+
return attn_output, None, past_key_value
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
class QuantLlamaAttentionFused(nn.Module):
|
| 170 |
+
def __init__(
|
| 171 |
+
self, hidden_size, num_heads, kv_max_seq_len, qkv_layer, o_proj, dev, args
|
| 172 |
+
):
|
| 173 |
+
super().__init__()
|
| 174 |
+
|
| 175 |
+
self.args = args
|
| 176 |
+
self.n_local_heads = args.num_attention_heads
|
| 177 |
+
self.hidden_size = args.hidden_size
|
| 178 |
+
self.num_heads = args.num_attention_heads
|
| 179 |
+
self.head_dim = self.hidden_size // self.num_heads
|
| 180 |
+
|
| 181 |
+
self.num_key_value_heads = args.num_key_value_heads
|
| 182 |
+
self.num_key_value_groups = self.num_heads // self.num_key_value_heads
|
| 183 |
+
self.max_position_embeddings = args.max_position_embeddings
|
| 184 |
+
self.rope_theta = args.rope_theta
|
| 185 |
+
self.rope_scaling = args.rope_scaling
|
| 186 |
+
if self.rope_scaling is None:
|
| 187 |
+
self.rope_scaling = 1.0
|
| 188 |
+
if isinstance(self.rope_scaling, dict):
|
| 189 |
+
self.rope_scaling = self.rope_scaling.get("factor", 1.0)
|
| 190 |
+
|
| 191 |
+
self.qkv_proj = qkv_layer
|
| 192 |
+
self.o_proj = o_proj
|
| 193 |
+
|
| 194 |
+
self.kv_max_seq_len = kv_max_seq_len
|
| 195 |
+
|
| 196 |
+
# following fastertransformer definition
|
| 197 |
+
self.cache_v = (
|
| 198 |
+
torch.zeros(
|
| 199 |
+
(
|
| 200 |
+
max_batch_size,
|
| 201 |
+
self.num_key_value_heads,
|
| 202 |
+
# args.max_position_embeddings,
|
| 203 |
+
self.kv_max_seq_len,
|
| 204 |
+
self.head_dim,
|
| 205 |
+
)
|
| 206 |
+
)
|
| 207 |
+
.to(dev)
|
| 208 |
+
.half()
|
| 209 |
+
) # added to half
|
| 210 |
+
# 8: pack 8 fp16 in FT, if fp32 then use 4
|
| 211 |
+
self.cache_k = (
|
| 212 |
+
torch.zeros(
|
| 213 |
+
(
|
| 214 |
+
max_batch_size,
|
| 215 |
+
self.num_key_value_heads,
|
| 216 |
+
self.head_dim // 8,
|
| 217 |
+
# args.max_position_embeddings,
|
| 218 |
+
self.kv_max_seq_len,
|
| 219 |
+
8,
|
| 220 |
+
)
|
| 221 |
+
)
|
| 222 |
+
.to(dev)
|
| 223 |
+
.half()
|
| 224 |
+
) # added to half
|
| 225 |
+
|
| 226 |
+
def forward(
|
| 227 |
+
self,
|
| 228 |
+
x: torch.Tensor,
|
| 229 |
+
start_pos: int,
|
| 230 |
+
freqs: torch.Tensor,
|
| 231 |
+
mask: Optional[torch.Tensor],
|
| 232 |
+
chunk_prefilling: bool = False,
|
| 233 |
+
):
|
| 234 |
+
bsz, seqlen, _ = x.shape
|
| 235 |
+
xqkv = self.qkv_proj(x)
|
| 236 |
+
xqkv = xqkv.view(
|
| 237 |
+
bsz,
|
| 238 |
+
seqlen,
|
| 239 |
+
self.n_local_heads + self.num_key_value_heads * 2,
|
| 240 |
+
self.head_dim,
|
| 241 |
+
)
|
| 242 |
+
xq = xqkv[:, :, 0 : self.n_local_heads]
|
| 243 |
+
xk = xqkv[
|
| 244 |
+
:, :, self.n_local_heads : (self.n_local_heads + self.num_key_value_heads)
|
| 245 |
+
]
|
| 246 |
+
xv = xqkv[:, :, -self.num_key_value_heads :]
|
| 247 |
+
|
| 248 |
+
if seqlen > 1:
|
| 249 |
+
xq = xq.view(bsz, seqlen, self.n_local_heads, self.head_dim)
|
| 250 |
+
xk = xk.view(bsz, seqlen, self.num_key_value_heads, self.head_dim)
|
| 251 |
+
xv = xv.view(bsz, seqlen, self.num_key_value_heads, self.head_dim)
|
| 252 |
+
|
| 253 |
+
xq = awq_inference_engine.fused_rope_with_pos_forward_func(xq, freqs, True)
|
| 254 |
+
xk = awq_inference_engine.fused_rope_with_pos_forward_func(xk, freqs, True)
|
| 255 |
+
|
| 256 |
+
self.cache_k = self.cache_k.to(xq)
|
| 257 |
+
self.cache_v = self.cache_v.to(xq)
|
| 258 |
+
|
| 259 |
+
values_store = xv.transpose(2, 1)
|
| 260 |
+
keys_store = (
|
| 261 |
+
xk.reshape(bsz, seqlen, self.num_key_value_heads, self.head_dim // 8, 8)
|
| 262 |
+
.permute(0, 2, 3, 1, 4)
|
| 263 |
+
.contiguous()
|
| 264 |
+
)
|
| 265 |
+
|
| 266 |
+
self.cache_v[:bsz, :, start_pos : start_pos + seqlen, :] = values_store
|
| 267 |
+
self.cache_k[:bsz, :, :, start_pos : start_pos + seqlen, :] = keys_store
|
| 268 |
+
if chunk_prefilling:
|
| 269 |
+
keys = self.cache_k[:, :, :, 0:start_pos, :]
|
| 270 |
+
keys = (
|
| 271 |
+
keys.permute(0, 3, 1, 2, 4)
|
| 272 |
+
.reshape(bsz, start_pos, self.num_key_value_heads, self.head_dim)
|
| 273 |
+
.contiguous()
|
| 274 |
+
)
|
| 275 |
+
keys = torch.cat((keys, xk), dim=1)
|
| 276 |
+
values = self.cache_v[:, :, 0:start_pos, :]
|
| 277 |
+
values = (
|
| 278 |
+
values.transpose(2, 1)
|
| 279 |
+
.reshape(bsz, start_pos, self.num_key_value_heads, self.head_dim)
|
| 280 |
+
.contiguous()
|
| 281 |
+
)
|
| 282 |
+
values = torch.cat((values, xv), dim=1)
|
| 283 |
+
else:
|
| 284 |
+
keys = xk
|
| 285 |
+
values = xv
|
| 286 |
+
|
| 287 |
+
keys = torch.repeat_interleave(
|
| 288 |
+
keys, dim=2, repeats=self.num_key_value_groups
|
| 289 |
+
)
|
| 290 |
+
values = torch.repeat_interleave(
|
| 291 |
+
values, dim=2, repeats=self.num_key_value_groups
|
| 292 |
+
)
|
| 293 |
+
|
| 294 |
+
xq = xq.transpose(1, 2)
|
| 295 |
+
keys = keys.transpose(1, 2)
|
| 296 |
+
values = values.transpose(1, 2)
|
| 297 |
+
scores = torch.matmul(xq, keys.transpose(2, 3)) / math.sqrt(self.head_dim)
|
| 298 |
+
if mask is not None:
|
| 299 |
+
scores = scores + mask # (bs, n_local_heads, slen, cache_len + slen)
|
| 300 |
+
scores = F.softmax(scores.float(), dim=-1).type_as(xq)
|
| 301 |
+
output = torch.matmul(scores, values) # (bs, n_local_heads, slen, head_dim)
|
| 302 |
+
output = output.transpose(1, 2).contiguous().view(bsz, seqlen, -1)
|
| 303 |
+
else:
|
| 304 |
+
xq = xq.view(bsz, self.n_local_heads, self.head_dim)
|
| 305 |
+
xk = xk.view(bsz, self.num_key_value_heads, self.head_dim)
|
| 306 |
+
xv = xv.view(bsz, self.num_key_value_heads, self.head_dim)
|
| 307 |
+
|
| 308 |
+
output = awq_inference_engine.single_query_attention(
|
| 309 |
+
xq,
|
| 310 |
+
xk,
|
| 311 |
+
xv,
|
| 312 |
+
self.cache_k,
|
| 313 |
+
self.cache_v,
|
| 314 |
+
None,
|
| 315 |
+
None,
|
| 316 |
+
start_pos,
|
| 317 |
+
self.head_dim,
|
| 318 |
+
self.rope_theta,
|
| 319 |
+
self.rope_scaling,
|
| 320 |
+
True,
|
| 321 |
+
)
|
| 322 |
+
output = output.reshape(bsz, 1, -1)
|
| 323 |
+
|
| 324 |
+
return self.o_proj(output)
|
| 325 |
+
|
| 326 |
+
|
| 327 |
+
class QuantLlamaAttentionFusedFlash(nn.Module):
|
| 328 |
+
"""Flash_attn_func from 'Flash{A}ttention-2: Faster Attention with Better Parallelism and Work Partitioning' paper"""
|
| 329 |
+
|
| 330 |
+
"""This function is faster than the varlen one but only supports single-batch inference"""
|
| 331 |
+
|
| 332 |
+
def __init__(
|
| 333 |
+
self, hidden_size, num_heads, kv_max_seq_len, qkv_layer, o_proj, dev, args
|
| 334 |
+
):
|
| 335 |
+
super().__init__()
|
| 336 |
+
|
| 337 |
+
self.args = args
|
| 338 |
+
self.n_local_heads = args.num_attention_heads
|
| 339 |
+
self.hidden_size = args.hidden_size
|
| 340 |
+
self.num_heads = args.num_attention_heads
|
| 341 |
+
self.head_dim = self.hidden_size // self.num_heads
|
| 342 |
+
|
| 343 |
+
self.num_key_value_heads = args.num_key_value_heads
|
| 344 |
+
self.num_key_value_groups = self.num_heads // self.num_key_value_heads
|
| 345 |
+
self.max_position_embeddings = args.max_position_embeddings
|
| 346 |
+
self.rope_theta = args.rope_theta
|
| 347 |
+
self.rope_scaling = args.rope_scaling
|
| 348 |
+
if self.rope_scaling is None:
|
| 349 |
+
self.rope_scaling = 1.0
|
| 350 |
+
elif isinstance(self.rope_scaling, dict):
|
| 351 |
+
self.rope_scaling = self.rope_scaling.get("factor", 1.0)
|
| 352 |
+
|
| 353 |
+
self.qkv_proj = qkv_layer
|
| 354 |
+
self.o_proj = o_proj
|
| 355 |
+
|
| 356 |
+
self.kv_max_seq_len = kv_max_seq_len
|
| 357 |
+
# following fastertransformer definition
|
| 358 |
+
# For short seqlence, we use fused kernel to accelerate decoding.
|
| 359 |
+
if self.kv_max_seq_len <= 8192:
|
| 360 |
+
self.cache_v = (
|
| 361 |
+
torch.zeros(
|
| 362 |
+
(
|
| 363 |
+
max_batch_size,
|
| 364 |
+
self.num_key_value_heads,
|
| 365 |
+
# args.max_position_embeddings,
|
| 366 |
+
self.kv_max_seq_len,
|
| 367 |
+
self.head_dim,
|
| 368 |
+
)
|
| 369 |
+
)
|
| 370 |
+
.to(dev)
|
| 371 |
+
.half()
|
| 372 |
+
) # added to half
|
| 373 |
+
# 8: pack 8 fp16 in FT, if fp32 then use 4
|
| 374 |
+
self.cache_k = (
|
| 375 |
+
torch.zeros(
|
| 376 |
+
(
|
| 377 |
+
max_batch_size,
|
| 378 |
+
self.num_key_value_heads,
|
| 379 |
+
self.head_dim // 8,
|
| 380 |
+
# args.max_position_embeddings,
|
| 381 |
+
kv_max_seq_len,
|
| 382 |
+
8,
|
| 383 |
+
)
|
| 384 |
+
)
|
| 385 |
+
.to(dev)
|
| 386 |
+
.half()
|
| 387 |
+
) # added to half
|
| 388 |
+
self.forward = self.short_forward
|
| 389 |
+
# For long sequence, we use flash attantion for both prefilling and decoding to avoid OOM.
|
| 390 |
+
else:
|
| 391 |
+
self.cache_v = (
|
| 392 |
+
torch.zeros(
|
| 393 |
+
(
|
| 394 |
+
max_batch_size,
|
| 395 |
+
self.kv_max_seq_len,
|
| 396 |
+
self.num_key_value_heads,
|
| 397 |
+
self.head_dim,
|
| 398 |
+
)
|
| 399 |
+
)
|
| 400 |
+
.to(dev)
|
| 401 |
+
.half()
|
| 402 |
+
) # added to half
|
| 403 |
+
self.cache_k = (
|
| 404 |
+
torch.zeros(
|
| 405 |
+
(
|
| 406 |
+
max_batch_size,
|
| 407 |
+
self.kv_max_seq_len,
|
| 408 |
+
self.num_key_value_heads,
|
| 409 |
+
self.head_dim,
|
| 410 |
+
)
|
| 411 |
+
)
|
| 412 |
+
.to(dev)
|
| 413 |
+
.half()
|
| 414 |
+
) # added to half
|
| 415 |
+
self.forward = self.long_forward
|
| 416 |
+
|
| 417 |
+
def short_forward(
|
| 418 |
+
self,
|
| 419 |
+
x: torch.Tensor,
|
| 420 |
+
start_pos: int,
|
| 421 |
+
freqs: torch.Tensor,
|
| 422 |
+
mask: Optional[torch.Tensor],
|
| 423 |
+
chunk_prefilling: bool = False,
|
| 424 |
+
):
|
| 425 |
+
bsz, seqlen, _ = x.shape
|
| 426 |
+
xqkv = self.qkv_proj(x)
|
| 427 |
+
xqkv = xqkv.view(
|
| 428 |
+
bsz,
|
| 429 |
+
seqlen,
|
| 430 |
+
self.n_local_heads + self.num_key_value_heads * 2,
|
| 431 |
+
self.head_dim,
|
| 432 |
+
)
|
| 433 |
+
xq = xqkv[:, :, 0 : self.n_local_heads]
|
| 434 |
+
xk = xqkv[
|
| 435 |
+
:, :, self.n_local_heads : (self.n_local_heads + self.num_key_value_heads)
|
| 436 |
+
]
|
| 437 |
+
xv = xqkv[:, :, -self.num_key_value_heads :]
|
| 438 |
+
|
| 439 |
+
if seqlen > 1:
|
| 440 |
+
xq = awq_inference_engine.fused_rope_with_pos_forward_func(xq, freqs, True)
|
| 441 |
+
xk = awq_inference_engine.fused_rope_with_pos_forward_func(xk, freqs, True)
|
| 442 |
+
|
| 443 |
+
self.cache_k = self.cache_k.to(xq)
|
| 444 |
+
self.cache_v = self.cache_v.to(xq)
|
| 445 |
+
|
| 446 |
+
values_store = xv.transpose(2, 1)
|
| 447 |
+
keys_store = (
|
| 448 |
+
xk.reshape(bsz, seqlen, self.num_key_value_heads, self.head_dim // 8, 8)
|
| 449 |
+
.permute(0, 2, 3, 1, 4)
|
| 450 |
+
.contiguous()
|
| 451 |
+
)
|
| 452 |
+
|
| 453 |
+
self.cache_v[:bsz, :, start_pos : start_pos + seqlen, :] = values_store
|
| 454 |
+
self.cache_k[:bsz, :, :, start_pos : start_pos + seqlen, :] = keys_store
|
| 455 |
+
|
| 456 |
+
if chunk_prefilling:
|
| 457 |
+
keys = self.cache_k[:, :, :, 0 : start_pos + seqlen, :]
|
| 458 |
+
keys = (
|
| 459 |
+
keys.permute(0, 3, 1, 2, 4)
|
| 460 |
+
.reshape(
|
| 461 |
+
bsz, start_pos + seqlen, self.num_key_value_heads, self.head_dim
|
| 462 |
+
)
|
| 463 |
+
.contiguous()
|
| 464 |
+
)
|
| 465 |
+
values = self.cache_v[:, :, 0 : start_pos + seqlen, :]
|
| 466 |
+
values = (
|
| 467 |
+
values.transpose(2, 1)
|
| 468 |
+
.reshape(
|
| 469 |
+
bsz, start_pos + seqlen, self.num_key_value_heads, self.head_dim
|
| 470 |
+
)
|
| 471 |
+
.contiguous()
|
| 472 |
+
)
|
| 473 |
+
else:
|
| 474 |
+
keys = xk
|
| 475 |
+
values = xv
|
| 476 |
+
|
| 477 |
+
output = flash_attn_func(
|
| 478 |
+
q=xq,
|
| 479 |
+
k=keys,
|
| 480 |
+
v=values,
|
| 481 |
+
causal=True,
|
| 482 |
+
)
|
| 483 |
+
output = output.contiguous().view(bsz, seqlen, -1)
|
| 484 |
+
else:
|
| 485 |
+
xq = xq.view(bsz, self.n_local_heads, self.head_dim)
|
| 486 |
+
xk = xk.view(bsz, self.num_key_value_heads, self.head_dim)
|
| 487 |
+
xv = xv.view(bsz, self.num_key_value_heads, self.head_dim)
|
| 488 |
+
output = awq_inference_engine.single_query_attention(
|
| 489 |
+
xq,
|
| 490 |
+
xk,
|
| 491 |
+
xv,
|
| 492 |
+
self.cache_k,
|
| 493 |
+
self.cache_v,
|
| 494 |
+
None,
|
| 495 |
+
None,
|
| 496 |
+
start_pos,
|
| 497 |
+
self.head_dim,
|
| 498 |
+
self.rope_theta,
|
| 499 |
+
self.rope_scaling,
|
| 500 |
+
True,
|
| 501 |
+
)
|
| 502 |
+
output = output.reshape(bsz, 1, -1)
|
| 503 |
+
return self.o_proj(output)
|
| 504 |
+
|
| 505 |
+
def long_forward(
|
| 506 |
+
self,
|
| 507 |
+
x: torch.Tensor,
|
| 508 |
+
start_pos: int,
|
| 509 |
+
freqs: torch.Tensor,
|
| 510 |
+
mask: Optional[torch.Tensor],
|
| 511 |
+
chunk_prefilling: bool = False,
|
| 512 |
+
):
|
| 513 |
+
bsz, seqlen, _ = x.shape
|
| 514 |
+
xqkv = self.qkv_proj(x)
|
| 515 |
+
xqkv = xqkv.view(
|
| 516 |
+
bsz,
|
| 517 |
+
seqlen,
|
| 518 |
+
self.n_local_heads + self.num_key_value_heads * 2,
|
| 519 |
+
self.head_dim,
|
| 520 |
+
)
|
| 521 |
+
xq = xqkv[:, :, 0 : self.n_local_heads]
|
| 522 |
+
xk = xqkv[
|
| 523 |
+
:, :, self.n_local_heads : (self.n_local_heads + self.num_key_value_heads)
|
| 524 |
+
]
|
| 525 |
+
xv = xqkv[:, :, -self.num_key_value_heads :]
|
| 526 |
+
|
| 527 |
+
xq = awq_inference_engine.fused_rope_with_pos_forward_func(xq, freqs, True)
|
| 528 |
+
xk = awq_inference_engine.fused_rope_with_pos_forward_func(xk, freqs, True)
|
| 529 |
+
|
| 530 |
+
self.cache_k = self.cache_k.to(xq)
|
| 531 |
+
self.cache_v = self.cache_v.to(xq)
|
| 532 |
+
|
| 533 |
+
self.cache_v[:bsz, start_pos : start_pos + seqlen] = xv
|
| 534 |
+
self.cache_k[:bsz, start_pos : start_pos + seqlen] = xk
|
| 535 |
+
|
| 536 |
+
keys = self.cache_k[:, 0 : start_pos + seqlen]
|
| 537 |
+
values = self.cache_v[:, 0 : start_pos + seqlen]
|
| 538 |
+
|
| 539 |
+
output = flash_attn_func(
|
| 540 |
+
q=xq,
|
| 541 |
+
k=keys,
|
| 542 |
+
v=values,
|
| 543 |
+
causal=True,
|
| 544 |
+
)
|
| 545 |
+
output = output.view(bsz, seqlen, -1)
|
| 546 |
+
return self.o_proj(output)
|
| 547 |
+
|
| 548 |
+
|
| 549 |
+
def make_quant_attn(model, dev, flash_attn=True):
|
| 550 |
+
"""
|
| 551 |
+
Replace all LlamaAttention modules with QuantLlamaAttention modules, fusing the q, k, v projections.
|
| 552 |
+
"""
|
| 553 |
+
model = model.cpu()
|
| 554 |
+
for name, m in model.named_modules():
|
| 555 |
+
if not m.__class__.__name__ in [
|
| 556 |
+
"LlamaAttention",
|
| 557 |
+
"LlamaAttentionFused",
|
| 558 |
+
"Qwen2AttentionFused",
|
| 559 |
+
]:
|
| 560 |
+
continue
|
| 561 |
+
|
| 562 |
+
q_proj = m.q_proj
|
| 563 |
+
k_proj = m.k_proj
|
| 564 |
+
v_proj = m.v_proj
|
| 565 |
+
|
| 566 |
+
qweights = torch.cat([q_proj.qweight, k_proj.qweight, v_proj.qweight], dim=0)
|
| 567 |
+
scaled_zeros = torch.cat(
|
| 568 |
+
[q_proj.scaled_zeros, k_proj.scaled_zeros, v_proj.scaled_zeros], dim=1
|
| 569 |
+
).contiguous()
|
| 570 |
+
scales = torch.cat(
|
| 571 |
+
[q_proj.scales, k_proj.scales, v_proj.scales], dim=1
|
| 572 |
+
).contiguous()
|
| 573 |
+
# g_idx = torch.cat([q_proj.g_idx, k_proj.g_idx, v_proj.g_idx], dim=0)
|
| 574 |
+
g_idx = None
|
| 575 |
+
bias = (
|
| 576 |
+
torch.cat([q_proj.bias, k_proj.bias, v_proj.bias], dim=0)
|
| 577 |
+
if q_proj.bias is not None
|
| 578 |
+
else None
|
| 579 |
+
)
|
| 580 |
+
|
| 581 |
+
qkv_layer = WQLinear(
|
| 582 |
+
q_proj.w_bit,
|
| 583 |
+
q_proj.group_size,
|
| 584 |
+
q_proj.in_features,
|
| 585 |
+
q_proj.out_features + k_proj.out_features + v_proj.out_features,
|
| 586 |
+
q_proj.bias is not None,
|
| 587 |
+
q_proj.qweight.device,
|
| 588 |
+
)
|
| 589 |
+
qkv_layer.qweight = qweights
|
| 590 |
+
qkv_layer.scaled_zeros = scaled_zeros
|
| 591 |
+
qkv_layer.scales = scales
|
| 592 |
+
|
| 593 |
+
qkv_layer.bias = bias
|
| 594 |
+
qkv_layer.split_k_iters = q_proj.split_k_iters
|
| 595 |
+
# We're dropping the rotary embedding layer m.rotary_emb here. We don't need it in the triton branch.
|
| 596 |
+
if isinstance(m, LlamaAttention):
|
| 597 |
+
attn = QuantLlamaAttention(
|
| 598 |
+
m.hidden_size, m.num_heads, qkv_layer, m.o_proj, dev
|
| 599 |
+
)
|
| 600 |
+
else:
|
| 601 |
+
if flash_attn:
|
| 602 |
+
attn = QuantLlamaAttentionFusedFlash(
|
| 603 |
+
m.args.hidden_size,
|
| 604 |
+
m.args.num_attention_heads,
|
| 605 |
+
m.kv_max_seq_len,
|
| 606 |
+
qkv_layer,
|
| 607 |
+
m.o_proj,
|
| 608 |
+
dev,
|
| 609 |
+
m.args,
|
| 610 |
+
)
|
| 611 |
+
else:
|
| 612 |
+
attn = QuantLlamaAttentionFused(
|
| 613 |
+
m.args.hidden_size,
|
| 614 |
+
m.args.num_attention_heads,
|
| 615 |
+
m.kv_max_seq_len,
|
| 616 |
+
qkv_layer,
|
| 617 |
+
m.o_proj,
|
| 618 |
+
dev,
|
| 619 |
+
m.args,
|
| 620 |
+
)
|
| 621 |
+
if "." in name:
|
| 622 |
+
parent_name = name.rsplit(".", 1)[0]
|
| 623 |
+
child_name = name[len(parent_name) + 1 :]
|
| 624 |
+
parent = model.get_submodule(parent_name)
|
| 625 |
+
else:
|
| 626 |
+
parent_name = ""
|
| 627 |
+
parent = model
|
| 628 |
+
child_name = name
|
| 629 |
+
|
| 630 |
+
# print(f"Replacing {name} with quant_attn; parent: {parent_name}, child's name: {child_name}")
|
| 631 |
+
setattr(parent, child_name, attn)
|
| 632 |
+
gc.collect()
|
| 633 |
+
torch.cuda.empty_cache()
|
| 634 |
+
model = model.to(dev)
|
llm-awq/tinychat/modules/fused_internencoder.py
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import Optional, Tuple, Union
|
| 2 |
+
|
| 3 |
+
import torch
|
| 4 |
+
import torch.nn.functional as F
|
| 5 |
+
import torch.utils.checkpoint
|
| 6 |
+
from einops import rearrange
|
| 7 |
+
from timm.layers import DropPath
|
| 8 |
+
from torch import nn
|
| 9 |
+
from transformers.activations import ACT2FN
|
| 10 |
+
from transformers.modeling_outputs import (BaseModelOutput,
|
| 11 |
+
BaseModelOutputWithPooling)
|
| 12 |
+
from transformers.modeling_utils import PreTrainedModel
|
| 13 |
+
from transformers.utils import logging
|
| 14 |
+
|
| 15 |
+
from awq.quantize import W8A8OF16LinearDynamicInputScale
|
| 16 |
+
import awq_inference_engine
|
| 17 |
+
|
| 18 |
+
from tinychat.models.internvl.internvit import (FlashAttention,
|
| 19 |
+
InternRMSNorm,
|
| 20 |
+
InternVisionEmbeddings,
|
| 21 |
+
InternAttention,
|
| 22 |
+
InternMLP,
|
| 23 |
+
InternVisionEncoderLayer,
|
| 24 |
+
InternVisionEncoder)
|
| 25 |
+
from tinychat.models.internvl.configuration_internvl import InternVisionConfig
|
| 26 |
+
|
| 27 |
+
try:
|
| 28 |
+
from flash_attn.bert_padding import pad_input, unpad_input
|
| 29 |
+
from flash_attn.flash_attn_interface import \
|
| 30 |
+
flash_attn_varlen_qkvpacked_func
|
| 31 |
+
has_flash_attn = True
|
| 32 |
+
except:
|
| 33 |
+
print('FlashAttention2 is not installed.')
|
| 34 |
+
has_flash_attn = False
|
| 35 |
+
|
| 36 |
+
logger = logging.get_logger(__name__)
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
class QuantInternVisionEncoder(nn.Module):
|
| 40 |
+
"""
|
| 41 |
+
Transformer encoder consisting of `config.num_hidden_layers` self attention layers. Each layer is a
|
| 42 |
+
[`InternEncoderLayer`].
|
| 43 |
+
|
| 44 |
+
Args:
|
| 45 |
+
config (`InternConfig`):
|
| 46 |
+
The corresponding vision configuration for the `InternEncoder`.
|
| 47 |
+
"""
|
| 48 |
+
|
| 49 |
+
def __init__(self, module: InternVisionEncoder, bsz=64, seqlen=1024):
|
| 50 |
+
super().__init__()
|
| 51 |
+
self.config = module.config
|
| 52 |
+
# stochastic depth decay rule
|
| 53 |
+
self.layers = nn.ModuleList([QuantInternVisionEncoderLayer(layer, self.config) for layer in module.layers])
|
| 54 |
+
self.gradient_checkpointing = True
|
| 55 |
+
self.bsz = bsz
|
| 56 |
+
self.seqlen = seqlen
|
| 57 |
+
|
| 58 |
+
def forward(
|
| 59 |
+
self,
|
| 60 |
+
inputs_embeds,
|
| 61 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 62 |
+
output_attentions: Optional[bool] = None,
|
| 63 |
+
output_hidden_states: Optional[bool] = None,
|
| 64 |
+
return_dict: Optional[bool] = None,
|
| 65 |
+
) -> Union[Tuple, BaseModelOutput]:
|
| 66 |
+
r"""
|
| 67 |
+
Args:
|
| 68 |
+
inputs_embeds (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`):
|
| 69 |
+
Embedded representation of the inputs. Should be float, not int tokens.
|
| 70 |
+
output_hidden_states (`bool`, *optional*):
|
| 71 |
+
Whether or not to return the hidden states of all layers. See `hidden_states` under returned tensors
|
| 72 |
+
for more detail.
|
| 73 |
+
return_dict (`bool`, *optional*):
|
| 74 |
+
Whether or not to return a [`~utils.ModelOutput`] instead of a plain tuple.
|
| 75 |
+
"""
|
| 76 |
+
output_hidden_states = (
|
| 77 |
+
output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
|
| 78 |
+
)
|
| 79 |
+
return_dict = return_dict if return_dict is not None else self.config.use_return_dict
|
| 80 |
+
|
| 81 |
+
encoder_states = () if output_hidden_states else None
|
| 82 |
+
hidden_states = inputs_embeds
|
| 83 |
+
|
| 84 |
+
for idx, encoder_layer in enumerate(self.layers):
|
| 85 |
+
if output_hidden_states:
|
| 86 |
+
encoder_states = encoder_states + (hidden_states,)
|
| 87 |
+
if self.gradient_checkpointing and self.training:
|
| 88 |
+
layer_outputs = torch.utils.checkpoint.checkpoint(
|
| 89 |
+
encoder_layer,
|
| 90 |
+
hidden_states)
|
| 91 |
+
else:
|
| 92 |
+
layer_outputs = encoder_layer(
|
| 93 |
+
hidden_states,
|
| 94 |
+
)
|
| 95 |
+
hidden_states = layer_outputs
|
| 96 |
+
|
| 97 |
+
if output_hidden_states:
|
| 98 |
+
encoder_states = encoder_states + (hidden_states,)
|
| 99 |
+
|
| 100 |
+
if not return_dict:
|
| 101 |
+
return tuple(v for v in [hidden_states, encoder_states] if v is not None)
|
| 102 |
+
return BaseModelOutput(
|
| 103 |
+
last_hidden_state=hidden_states, hidden_states=encoder_states
|
| 104 |
+
)
|
| 105 |
+
|
| 106 |
+
class QuantInternRMSNorm(nn.Module):
|
| 107 |
+
def __init__(self, module: nn.Module, use_per_token_quant=True):
|
| 108 |
+
super().__init__()
|
| 109 |
+
self.weight = nn.Parameter(module.weight.data, requires_grad=False)
|
| 110 |
+
self.bias = nn.Parameter(module.bias.data, requires_grad=False)
|
| 111 |
+
self.variance_epsilon = module.eps
|
| 112 |
+
self.use_per_token_quant = use_per_token_quant
|
| 113 |
+
|
| 114 |
+
def forward(self, hidden_states):
|
| 115 |
+
bsz, seqlen, hidden_size = hidden_states.shape
|
| 116 |
+
output = torch.empty((bsz * seqlen), hidden_size, device=hidden_states.device, dtype=torch.int8)
|
| 117 |
+
scale = torch.empty((bsz * seqlen), device=hidden_states.device, dtype=hidden_states.dtype)
|
| 118 |
+
awq_inference_engine.rms_norm_general(
|
| 119 |
+
output,
|
| 120 |
+
hidden_states,
|
| 121 |
+
self.weight,
|
| 122 |
+
self.bias,
|
| 123 |
+
scale,
|
| 124 |
+
self.variance_epsilon,
|
| 125 |
+
self.use_per_token_quant,
|
| 126 |
+
)
|
| 127 |
+
return output, scale
|
| 128 |
+
|
| 129 |
+
class QuantInternAttention(nn.Module):
|
| 130 |
+
def __init__(self, module: InternAttention, config: InternVisionConfig, init_only=False):
|
| 131 |
+
super().__init__()
|
| 132 |
+
self.config = config
|
| 133 |
+
self.embed_dim = module.embed_dim
|
| 134 |
+
self.num_heads = module.num_heads
|
| 135 |
+
self.head_dim = self.embed_dim // self.num_heads
|
| 136 |
+
self.scale = module.scale
|
| 137 |
+
self.use_flash_attn = config.use_flash_attn
|
| 138 |
+
|
| 139 |
+
self.qkv = W8A8OF16LinearDynamicInputScale.from_linear(module.qkv, init_only=init_only)
|
| 140 |
+
self.proj = W8A8OF16LinearDynamicInputScale.from_linear(module.proj, init_only=init_only)
|
| 141 |
+
|
| 142 |
+
self.qk_normalization = module.qk_normalization
|
| 143 |
+
if self.qk_normalization:
|
| 144 |
+
self.q_norm = QuantInternRMSNorm(module.q_norm)
|
| 145 |
+
self.k_norm = QuantInternRMSNorm(module.k_norm)
|
| 146 |
+
|
| 147 |
+
if self.use_flash_attn:
|
| 148 |
+
from tinychat.models.internvl.internvit import FlashAttention
|
| 149 |
+
self.inner_attn = FlashAttention(attention_dropout=config.attention_dropout)
|
| 150 |
+
|
| 151 |
+
def forward(self, hidden_states: torch.Tensor, scale_in: torch.Tensor):
|
| 152 |
+
bsz, seqlen, hidden_size = hidden_states.shape
|
| 153 |
+
|
| 154 |
+
qkv_out = torch.empty(bsz * seqlen, 3 * hidden_size, dtype=torch.float16, device=hidden_states.device)
|
| 155 |
+
self.qkv(hidden_states.reshape(-1, hidden_size), scale_in, qkv_out)
|
| 156 |
+
|
| 157 |
+
qkv = rearrange(qkv_out.view(bsz, seqlen, -1), 'b s (three h d) -> b s three h d', three=3, h=self.num_heads)
|
| 158 |
+
|
| 159 |
+
if self.qk_normalization:
|
| 160 |
+
q, k, v = qkv.unbind(2)
|
| 161 |
+
q, _ = self.q_norm(q.flatten(-2, -1)); q = q.view_as(q)
|
| 162 |
+
k, _ = self.k_norm(k.flatten(-2, -1)); k = k.view_as(k)
|
| 163 |
+
qkv = torch.stack([q, k, v], dim=2)
|
| 164 |
+
|
| 165 |
+
attn_out, _ = self.inner_attn(qkv, need_weights=False, causal=False)
|
| 166 |
+
attn_out = rearrange(attn_out, 'b s h d -> (b s) (h d)')
|
| 167 |
+
|
| 168 |
+
quant_out = torch.empty_like(attn_out, dtype=torch.int8)
|
| 169 |
+
scale_proj_in = torch.empty(bsz * seqlen, device=hidden_states.device, dtype=torch.float16)
|
| 170 |
+
awq_inference_engine.invoke_quant(quant_out, attn_out, scale_proj_in)
|
| 171 |
+
|
| 172 |
+
proj_out = torch.empty_like(attn_out)
|
| 173 |
+
self.proj(quant_out, scale_proj_in, proj_out)
|
| 174 |
+
|
| 175 |
+
return proj_out
|
| 176 |
+
|
| 177 |
+
class QuantInternMLP(nn.Module):
|
| 178 |
+
def __init__(self, module: InternMLP, config: InternVisionConfig):
|
| 179 |
+
super().__init__()
|
| 180 |
+
self.config = config
|
| 181 |
+
self.act = module.act
|
| 182 |
+
self.fc1 = W8A8OF16LinearDynamicInputScale.from_linear(module.fc1)
|
| 183 |
+
self.fc2 = W8A8OF16LinearDynamicInputScale.from_linear(module.fc2)
|
| 184 |
+
|
| 185 |
+
def forward(self, hidden_states: torch.Tensor, scale_in: torch.Tensor):
|
| 186 |
+
bsz, seqlen, hidden_size = hidden_states.shape
|
| 187 |
+
device = hidden_states.device
|
| 188 |
+
|
| 189 |
+
fc1_out = torch.empty((bsz * seqlen), self.config.intermediate_size, dtype=torch.float16, device=device)
|
| 190 |
+
self.fc1(hidden_states.reshape(-1, hidden_size), scale_in, fc1_out)
|
| 191 |
+
|
| 192 |
+
tmp = torch.empty(
|
| 193 |
+
((bsz * seqlen) * self.config.intermediate_size),
|
| 194 |
+
device=device,
|
| 195 |
+
dtype=torch.float16,
|
| 196 |
+
)
|
| 197 |
+
act_out = torch.empty_like(fc1_out, dtype=torch.int8)
|
| 198 |
+
scale_act = torch.empty(bsz * seqlen, device=device, dtype=torch.float16)
|
| 199 |
+
awq_inference_engine.gelu_and_quant(act_out, fc1_out, scale_act, tmp)
|
| 200 |
+
|
| 201 |
+
fc2_out = torch.empty((bsz * seqlen), hidden_size, dtype=torch.float16, device=device)
|
| 202 |
+
self.fc2(act_out, scale_act, fc2_out)
|
| 203 |
+
|
| 204 |
+
return fc2_out
|
| 205 |
+
|
| 206 |
+
class QuantInternVisionEncoderLayer(nn.Module):
|
| 207 |
+
def __init__(self, module: InternVisionEncoderLayer, config: InternVisionConfig):
|
| 208 |
+
super().__init__()
|
| 209 |
+
self.config = config
|
| 210 |
+
self.embed_dim = config.hidden_size
|
| 211 |
+
self.intermediate_size = config.intermediate_size
|
| 212 |
+
|
| 213 |
+
self.attn = QuantInternAttention(module.attn, config)
|
| 214 |
+
self.mlp = QuantInternMLP(module.mlp, config)
|
| 215 |
+
|
| 216 |
+
self.norm1 = QuantInternRMSNorm(module.norm1)
|
| 217 |
+
self.norm2 = QuantInternRMSNorm(module.norm2)
|
| 218 |
+
|
| 219 |
+
self.ls1 = module.ls1
|
| 220 |
+
self.ls2 = module.ls2
|
| 221 |
+
|
| 222 |
+
def forward(self, hidden_states: torch.Tensor):
|
| 223 |
+
bsz, seqlen, hidden_size = hidden_states.shape
|
| 224 |
+
|
| 225 |
+
residual = hidden_states
|
| 226 |
+
norm1_out, scale1 = self.norm1(hidden_states)
|
| 227 |
+
attn_out = self.attn(norm1_out.view(bsz, seqlen, hidden_size), scale1)
|
| 228 |
+
hidden_states = residual + attn_out.view(bsz, seqlen, hidden_size) * self.ls1
|
| 229 |
+
|
| 230 |
+
residual = hidden_states
|
| 231 |
+
norm2_out, scale2 = self.norm2(hidden_states)
|
| 232 |
+
mlp_out = self.mlp(norm2_out.view(bsz, seqlen, hidden_size), scale2)
|
| 233 |
+
hidden_states = residual + mlp_out.view(bsz, seqlen, hidden_size) * self.ls2
|
| 234 |
+
|
| 235 |
+
return hidden_states
|
| 236 |
+
|
| 237 |
+
|
llm-awq/tinychat/modules/fused_norm.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import torch
|
| 2 |
+
from torch import nn
|
| 3 |
+
from transformers.models.llama.modeling_llama import LlamaRMSNorm
|
| 4 |
+
import awq_inference_engine
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
class FTLlamaRMSNorm(nn.Module):
|
| 8 |
+
def __init__(self, weight, eps=1e-6):
|
| 9 |
+
"""
|
| 10 |
+
LlamaRMSNorm is equivalent to T5LayerNorm
|
| 11 |
+
"""
|
| 12 |
+
super().__init__()
|
| 13 |
+
self.weight = weight
|
| 14 |
+
self.variance_epsilon = eps
|
| 15 |
+
|
| 16 |
+
def forward(self, x):
|
| 17 |
+
output = torch.empty_like(x)
|
| 18 |
+
awq_inference_engine.layernorm_forward_cuda(
|
| 19 |
+
x, self.weight, output, self.variance_epsilon
|
| 20 |
+
)
|
| 21 |
+
return output
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
def make_quant_norm(model):
|
| 25 |
+
"""
|
| 26 |
+
Replace all LlamaRMSNorm modules with FTLlamaRMSNorm modules
|
| 27 |
+
"""
|
| 28 |
+
|
| 29 |
+
for name, m in model.named_modules():
|
| 30 |
+
if not isinstance(m, LlamaRMSNorm):
|
| 31 |
+
continue
|
| 32 |
+
|
| 33 |
+
norm = FTLlamaRMSNorm(m.weight, m.variance_epsilon)
|
| 34 |
+
|
| 35 |
+
if "." in name:
|
| 36 |
+
parent_name = name.rsplit(".", 1)[0]
|
| 37 |
+
child_name = name[len(parent_name) + 1 :]
|
| 38 |
+
parent = model.get_submodule(parent_name)
|
| 39 |
+
else:
|
| 40 |
+
parent_name = ""
|
| 41 |
+
parent = model
|
| 42 |
+
child_name = name
|
| 43 |
+
|
| 44 |
+
# print(f"Replacing {name} with quant_attn; parent: {parent_name}, child's name: {child_name}")
|
| 45 |
+
|
| 46 |
+
setattr(parent, child_name, norm)
|
llm-awq/tinychat/modules/fused_siglipdecoder.py
ADDED
|
@@ -0,0 +1,282 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import numpy as np
|
| 2 |
+
import torch
|
| 3 |
+
import torch.nn as nn
|
| 4 |
+
import torch.nn.functional as F
|
| 5 |
+
from awq.quantize import W8A8OF16LinearDynamicInputScale
|
| 6 |
+
from llava.model.multimodal_encoder.siglip.modeling_siglip import (
|
| 7 |
+
SiglipMLP,
|
| 8 |
+
SiglipEncoder,
|
| 9 |
+
SiglipAttention,
|
| 10 |
+
SiglipEncoderLayer,
|
| 11 |
+
)
|
| 12 |
+
from tinychat.utils.input_metadata import ActivationBuffer
|
| 13 |
+
from transformers.modeling_outputs import BaseModelOutput
|
| 14 |
+
from typing import Optional, Tuple, Union
|
| 15 |
+
from flash_attn import flash_attn_func
|
| 16 |
+
import time
|
| 17 |
+
|
| 18 |
+
CLIP_RANGE = 5
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
import awq_inference_engine
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
class QuantSiglipEncoder(nn.Module):
|
| 25 |
+
def __init__(self, module: SiglipEncoder, bsz=64, seqlen=1024):
|
| 26 |
+
super().__init__()
|
| 27 |
+
self.config = module.config
|
| 28 |
+
self.layers = [QuantSiglipEncoderLayer(layer) for layer in module.layers]
|
| 29 |
+
self.buffer = ActivationBuffer(module)
|
| 30 |
+
self.bsz = bsz
|
| 31 |
+
self.seqlen = seqlen
|
| 32 |
+
self.buffer.allocate_activation_buffer(self.bsz * self.seqlen)
|
| 33 |
+
|
| 34 |
+
# Ignore copy
|
| 35 |
+
def forward(
|
| 36 |
+
self,
|
| 37 |
+
inputs_embeds,
|
| 38 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 39 |
+
output_attentions: Optional[bool] = None, # dummy
|
| 40 |
+
output_hidden_states: Optional[bool] = None,
|
| 41 |
+
return_dict: Optional[bool] = None,
|
| 42 |
+
) -> Union[Tuple, BaseModelOutput]:
|
| 43 |
+
# TODO Find why this code is necessary
|
| 44 |
+
# torch.sum(inputs_embeds!=inputs_embeds)
|
| 45 |
+
bsz, seqlen, _ = inputs_embeds.shape
|
| 46 |
+
if self.bsz != bsz or self.seqlen != seqlen:
|
| 47 |
+
self.buffer.allocate_activation_buffer(bsz * seqlen)
|
| 48 |
+
self.bsz = bsz
|
| 49 |
+
self.seqlen = seqlen
|
| 50 |
+
|
| 51 |
+
output_hidden_states = (
|
| 52 |
+
output_hidden_states
|
| 53 |
+
if output_hidden_states is not None
|
| 54 |
+
else self.config.output_hidden_states
|
| 55 |
+
)
|
| 56 |
+
return_dict = (
|
| 57 |
+
return_dict if return_dict is not None else self.config.use_return_dict
|
| 58 |
+
)
|
| 59 |
+
|
| 60 |
+
encoder_states = () if output_hidden_states else None
|
| 61 |
+
|
| 62 |
+
hidden_states = inputs_embeds
|
| 63 |
+
for i, encoder_layer in enumerate(self.layers):
|
| 64 |
+
if output_hidden_states:
|
| 65 |
+
encoder_states = encoder_states + (
|
| 66 |
+
hidden_states.reshape(bsz, seqlen, -1),
|
| 67 |
+
)
|
| 68 |
+
hidden_states = encoder_layer(
|
| 69 |
+
hidden_states, self.buffer, attention_mask, bsz, seqlen
|
| 70 |
+
)
|
| 71 |
+
|
| 72 |
+
if output_hidden_states:
|
| 73 |
+
encoder_states = encoder_states + (hidden_states.reshape(bsz, seqlen, -1),)
|
| 74 |
+
if not return_dict:
|
| 75 |
+
return tuple(v for v in [hidden_states, encoder_states] if v is not None)
|
| 76 |
+
return BaseModelOutput(
|
| 77 |
+
last_hidden_state=hidden_states.reshape(bsz, seqlen, -1),
|
| 78 |
+
hidden_states=encoder_states,
|
| 79 |
+
attentions=None,
|
| 80 |
+
)
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
class QuantSiglipMLP(nn.Module):
|
| 84 |
+
def __init__(self, siglipmlp, init_only=False):
|
| 85 |
+
super().__init__()
|
| 86 |
+
self.config = siglipmlp.config
|
| 87 |
+
self.activation_fn = siglipmlp.activation_fn
|
| 88 |
+
self.fc1 = W8A8OF16LinearDynamicInputScale.from_linear(
|
| 89 |
+
siglipmlp.fc1, init_only=init_only, fc1=False
|
| 90 |
+
)
|
| 91 |
+
self.fc2 = W8A8OF16LinearDynamicInputScale.from_linear(
|
| 92 |
+
siglipmlp.fc2, init_only=init_only
|
| 93 |
+
)
|
| 94 |
+
self.invoke_quant = self.invoke_quant_mlp
|
| 95 |
+
|
| 96 |
+
def invoke_quant_mlp(self, buffer, actfn_output):
|
| 97 |
+
awq_inference_engine.invoke_quant(
|
| 98 |
+
buffer.quantized_mlp_act_buffer,
|
| 99 |
+
actfn_output,
|
| 100 |
+
buffer.quantized_scale_buffer,
|
| 101 |
+
)
|
| 102 |
+
|
| 103 |
+
def forward(self, buffer: ActivationBuffer) -> torch.Tensor:
|
| 104 |
+
# INT8 in, FP16 out
|
| 105 |
+
self.fc1(
|
| 106 |
+
buffer.quantized_hidden_states_buffer,
|
| 107 |
+
buffer.quantized_scale_buffer,
|
| 108 |
+
buffer.fc1_buffer,
|
| 109 |
+
)
|
| 110 |
+
# Act & quantization
|
| 111 |
+
awq_inference_engine.gelu_and_quant(
|
| 112 |
+
buffer.quantized_mlp_act_buffer,
|
| 113 |
+
buffer.fc1_buffer,
|
| 114 |
+
buffer.quantized_scale_buffer,
|
| 115 |
+
buffer.tmp,
|
| 116 |
+
)
|
| 117 |
+
# INT8 in, FP16 out
|
| 118 |
+
self.fc2(
|
| 119 |
+
buffer.quantized_mlp_act_buffer,
|
| 120 |
+
buffer.quantized_scale_buffer,
|
| 121 |
+
buffer.in_out_fc2_act_buffer,
|
| 122 |
+
)
|
| 123 |
+
|
| 124 |
+
|
| 125 |
+
class QuantSiglipFlashAttention2(nn.Module):
|
| 126 |
+
def __init__(
|
| 127 |
+
self,
|
| 128 |
+
module: SiglipAttention,
|
| 129 |
+
init_only=False,
|
| 130 |
+
):
|
| 131 |
+
super().__init__()
|
| 132 |
+
self.config = module.config
|
| 133 |
+
self.embed_dim = module.embed_dim
|
| 134 |
+
self.num_heads = module.num_heads
|
| 135 |
+
self.head_dim = self.embed_dim // self.num_heads
|
| 136 |
+
|
| 137 |
+
self.qkv_proj = W8A8OF16LinearDynamicInputScale.from_qkv(
|
| 138 |
+
module.q_proj, module.k_proj, module.v_proj, init_only=init_only
|
| 139 |
+
)
|
| 140 |
+
self.out_proj = W8A8OF16LinearDynamicInputScale.from_linear(
|
| 141 |
+
module.out_proj, init_only=init_only
|
| 142 |
+
)
|
| 143 |
+
self.invoke_quant = self.invoke_quant_wo
|
| 144 |
+
|
| 145 |
+
def invoke_quant_wo(self, buffer, attn_output):
|
| 146 |
+
awq_inference_engine.invoke_quant(
|
| 147 |
+
buffer.quantized_hidden_states_buffer,
|
| 148 |
+
attn_output,
|
| 149 |
+
buffer.quantized_scale_buffer,
|
| 150 |
+
)
|
| 151 |
+
|
| 152 |
+
# Adapted from transformers.models.llama.modeling_llama.LlamaFlashAttention2.forward
|
| 153 |
+
def forward(
|
| 154 |
+
self, buffer: ActivationBuffer, bsz=64, seqlen=1024
|
| 155 |
+
) -> Tuple[torch.Tensor, Optional[torch.Tensor], Optional[Tuple[torch.Tensor]]]:
|
| 156 |
+
# qkv
|
| 157 |
+
self.qkv_proj(
|
| 158 |
+
buffer.quantized_hidden_states_buffer,
|
| 159 |
+
buffer.quantized_scale_buffer,
|
| 160 |
+
buffer.qkv_proj_act_buffer,
|
| 161 |
+
)
|
| 162 |
+
q, k, v = buffer.qkv_proj_act_buffer.split(
|
| 163 |
+
[self.embed_dim, self.embed_dim, self.embed_dim], dim=-1
|
| 164 |
+
)
|
| 165 |
+
q = q.reshape(bsz, seqlen, self.num_heads, self.head_dim)
|
| 166 |
+
k = k.reshape(bsz, seqlen, self.num_heads, self.head_dim)
|
| 167 |
+
v = v.reshape(bsz, seqlen, self.num_heads, self.head_dim)
|
| 168 |
+
attn_output = flash_attn_func(q, k, v, softmax_scale=None, causal=False)
|
| 169 |
+
attn_output = attn_output.reshape(bsz * seqlen, -1)
|
| 170 |
+
# FP16 -> int8
|
| 171 |
+
self.invoke_quant(buffer, attn_output)
|
| 172 |
+
# INT8 in, FP16 out
|
| 173 |
+
self.out_proj(
|
| 174 |
+
buffer.quantized_hidden_states_buffer,
|
| 175 |
+
buffer.quantized_scale_buffer,
|
| 176 |
+
buffer.in_out_fc2_act_buffer,
|
| 177 |
+
)
|
| 178 |
+
|
| 179 |
+
|
| 180 |
+
class QuantSiglipEncoderLayer(nn.Module):
|
| 181 |
+
def __init__(self, module: SiglipEncoderLayer):
|
| 182 |
+
super().__init__()
|
| 183 |
+
self.embed_dim = module.embed_dim
|
| 184 |
+
self.self_attn = QuantSiglipFlashAttention2(module.self_attn)
|
| 185 |
+
self.layer_norm1 = RMSNormGeneral(
|
| 186 |
+
module.layer_norm1.weight.data,
|
| 187 |
+
module.layer_norm1.bias.data,
|
| 188 |
+
module.layer_norm1.eps,
|
| 189 |
+
True,
|
| 190 |
+
).cuda()
|
| 191 |
+
self.mlp = QuantSiglipMLP(module.mlp)
|
| 192 |
+
self.layer_norm2 = RMSNormGeneral(
|
| 193 |
+
module.layer_norm2.weight.data,
|
| 194 |
+
module.layer_norm2.bias.data,
|
| 195 |
+
module.layer_norm2.eps,
|
| 196 |
+
True,
|
| 197 |
+
).cuda()
|
| 198 |
+
self.quant = self.invoke_quant_norm
|
| 199 |
+
|
| 200 |
+
def invoke_quant_norm(self, buffer, normfn_output):
|
| 201 |
+
awq_inference_engine.invoke_quant(
|
| 202 |
+
buffer.quantized_hidden_states_buffer,
|
| 203 |
+
normfn_output,
|
| 204 |
+
buffer.quantized_scale_buffer,
|
| 205 |
+
)
|
| 206 |
+
|
| 207 |
+
def forward(
|
| 208 |
+
self,
|
| 209 |
+
hidden_states: torch.Tensor,
|
| 210 |
+
buffer: ActivationBuffer,
|
| 211 |
+
attention_mask,
|
| 212 |
+
bsz,
|
| 213 |
+
seqlen,
|
| 214 |
+
) -> Tuple[torch.FloatTensor]:
|
| 215 |
+
# Attention block
|
| 216 |
+
# FP16 in int8 out, layernorm & quantization
|
| 217 |
+
residual = hidden_states
|
| 218 |
+
self.layer_norm1(
|
| 219 |
+
hidden_states.reshape(-1, self.embed_dim),
|
| 220 |
+
buffer.quantized_hidden_states_buffer,
|
| 221 |
+
buffer.quantized_scale_buffer,
|
| 222 |
+
)
|
| 223 |
+
|
| 224 |
+
# INT8 -> FP16
|
| 225 |
+
self.self_attn(buffer, bsz, seqlen)
|
| 226 |
+
hidden_states = (
|
| 227 |
+
residual.reshape(-1, self.embed_dim) + buffer.in_out_fc2_act_buffer
|
| 228 |
+
)
|
| 229 |
+
# Fully Connected
|
| 230 |
+
residual = hidden_states
|
| 231 |
+
# FP16 in int8 out, layernorm & quantization
|
| 232 |
+
self.layer_norm2(
|
| 233 |
+
hidden_states.reshape(-1, self.embed_dim),
|
| 234 |
+
buffer.quantized_hidden_states_buffer,
|
| 235 |
+
buffer.quantized_scale_buffer,
|
| 236 |
+
)
|
| 237 |
+
|
| 238 |
+
# INT8 -> FP16
|
| 239 |
+
self.mlp(buffer)
|
| 240 |
+
hidden_states = (
|
| 241 |
+
residual.reshape(-1, self.embed_dim) + buffer.in_out_fc2_act_buffer
|
| 242 |
+
)
|
| 243 |
+
return hidden_states
|
| 244 |
+
|
| 245 |
+
|
| 246 |
+
class RMSNormGeneral(nn.Module):
|
| 247 |
+
"""Root mean square normalization (w/ per-token or per-tensor quant).
|
| 248 |
+
|
| 249 |
+
Computes x -> w * x / sqrt(E[x^2] + eps) where w is the learned weight.
|
| 250 |
+
Refer to https://arxiv.org/abs/1910.07467
|
| 251 |
+
"""
|
| 252 |
+
|
| 253 |
+
def __init__(
|
| 254 |
+
self,
|
| 255 |
+
weight: torch.tensor,
|
| 256 |
+
bias: torch.tensor,
|
| 257 |
+
eps: float = 1e-6,
|
| 258 |
+
use_per_token_quant: bool = True,
|
| 259 |
+
) -> None:
|
| 260 |
+
super().__init__()
|
| 261 |
+
self.weight = nn.Parameter(weight, requires_grad=False)
|
| 262 |
+
self.bias = nn.Parameter(bias, requires_grad=False)
|
| 263 |
+
self.variance_epsilon = eps
|
| 264 |
+
self.use_per_token_quant = use_per_token_quant
|
| 265 |
+
|
| 266 |
+
def forward(
|
| 267 |
+
self,
|
| 268 |
+
x: torch.Tensor,
|
| 269 |
+
quantized_hidden_states_buffer: torch.Tensor,
|
| 270 |
+
quantized_scale_buffer: torch.Tensor,
|
| 271 |
+
quantized_sum_buffer: torch.Tensor = None,
|
| 272 |
+
) -> torch.Tensor:
|
| 273 |
+
# quantized_sum_buffer is not used, only to keep the consistency of the interface
|
| 274 |
+
awq_inference_engine.rms_norm_general(
|
| 275 |
+
quantized_hidden_states_buffer,
|
| 276 |
+
x,
|
| 277 |
+
self.weight.data,
|
| 278 |
+
self.bias.data,
|
| 279 |
+
quantized_scale_buffer,
|
| 280 |
+
self.variance_epsilon,
|
| 281 |
+
self.use_per_token_quant,
|
| 282 |
+
)
|
llm-awq/tinychat/modules/fused_vision_attn.py
ADDED
|
@@ -0,0 +1,272 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import math
|
| 2 |
+
import torch
|
| 3 |
+
import torch.nn as nn
|
| 4 |
+
from torch.nn import functional as F
|
| 5 |
+
from typing import Optional, Tuple
|
| 6 |
+
|
| 7 |
+
# from awq.quantize.qmodule import WQLinear
|
| 8 |
+
# import awq_inference_engine
|
| 9 |
+
# from tinychat.models.llama import apply_rotary_emb
|
| 10 |
+
import gc
|
| 11 |
+
|
| 12 |
+
import tinychat.utils.constants
|
| 13 |
+
|
| 14 |
+
max_batch_size = tinychat.utils.constants.max_batch_size
|
| 15 |
+
max_seq_len = tinychat.utils.constants.max_seq_len
|
| 16 |
+
|
| 17 |
+
from transformers.activations import ACT2FN
|
| 18 |
+
from transformers.models.clip.configuration_clip import (
|
| 19 |
+
CLIPConfig,
|
| 20 |
+
CLIPTextConfig,
|
| 21 |
+
CLIPVisionConfig,
|
| 22 |
+
)
|
| 23 |
+
from transformers.models.clip.modeling_clip import CLIPAttention
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
class CLIPAttentionFused(nn.Module):
|
| 27 |
+
"""Multi-headed attention from 'Attention Is All You Need' paper"""
|
| 28 |
+
|
| 29 |
+
def __init__(
|
| 30 |
+
self, hidden_size, num_heads, qkv_proj, out_proj, dev, attention_dropout=0.0
|
| 31 |
+
):
|
| 32 |
+
super().__init__()
|
| 33 |
+
self.embed_dim = hidden_size
|
| 34 |
+
self.num_heads = num_heads
|
| 35 |
+
self.head_dim = hidden_size // num_heads
|
| 36 |
+
self.scale = self.head_dim**-0.5
|
| 37 |
+
self.dropout = attention_dropout
|
| 38 |
+
|
| 39 |
+
if (self.head_dim * num_heads) != self.embed_dim:
|
| 40 |
+
raise ValueError(
|
| 41 |
+
f"hidden_size must be divisible by num_heads (got `hidden_size`: {self.hidden_size}"
|
| 42 |
+
f" and `num_heads`: {num_heads})."
|
| 43 |
+
)
|
| 44 |
+
self.qkv_proj = qkv_proj
|
| 45 |
+
self.out_proj = out_proj
|
| 46 |
+
|
| 47 |
+
def _shape(self, tensor: torch.Tensor, seq_len: int, bsz: int):
|
| 48 |
+
return (
|
| 49 |
+
tensor.view(bsz, seq_len, self.num_heads, self.head_dim)
|
| 50 |
+
.transpose(1, 2)
|
| 51 |
+
.contiguous()
|
| 52 |
+
)
|
| 53 |
+
|
| 54 |
+
def forward(
|
| 55 |
+
self,
|
| 56 |
+
hidden_states: torch.Tensor,
|
| 57 |
+
attention_mask: Optional[torch.Tensor] = None,
|
| 58 |
+
causal_attention_mask: Optional[torch.Tensor] = None,
|
| 59 |
+
output_attentions: Optional[bool] = False,
|
| 60 |
+
) -> Tuple[torch.Tensor, Optional[torch.Tensor], Optional[Tuple[torch.Tensor]]]:
|
| 61 |
+
"""Input shape: Batch x Time x Channel"""
|
| 62 |
+
|
| 63 |
+
bsz, tgt_len, embed_dim = hidden_states.size()
|
| 64 |
+
|
| 65 |
+
qkv_states = self.qkv_proj(hidden_states)
|
| 66 |
+
qkv_states = qkv_states.view(bsz, tgt_len, 3, self.num_heads, self.head_dim)
|
| 67 |
+
|
| 68 |
+
# This updates the query and key states in-place, saving VRAM.
|
| 69 |
+
query_states, key_states, value_states = torch.split(qkv_states, 1, dim=2)
|
| 70 |
+
del qkv_states
|
| 71 |
+
|
| 72 |
+
proj_shape = (bsz * self.num_heads, -1, self.head_dim)
|
| 73 |
+
|
| 74 |
+
query_states = (
|
| 75 |
+
query_states.view(bsz, tgt_len, self.num_heads, self.head_dim)
|
| 76 |
+
.transpose(1, 2)
|
| 77 |
+
.view(*proj_shape)
|
| 78 |
+
* self.scale
|
| 79 |
+
)
|
| 80 |
+
key_states = (
|
| 81 |
+
key_states.view(bsz, tgt_len, self.num_heads, self.head_dim)
|
| 82 |
+
.transpose(1, 2)
|
| 83 |
+
.view(*proj_shape)
|
| 84 |
+
)
|
| 85 |
+
value_states = (
|
| 86 |
+
value_states.view(bsz, tgt_len, self.num_heads, self.head_dim)
|
| 87 |
+
.transpose(1, 2)
|
| 88 |
+
.view(*proj_shape)
|
| 89 |
+
)
|
| 90 |
+
|
| 91 |
+
src_len = key_states.size(1)
|
| 92 |
+
attn_weights = torch.bmm(query_states, key_states.transpose(1, 2))
|
| 93 |
+
|
| 94 |
+
if attn_weights.size() != (bsz * self.num_heads, tgt_len, src_len):
|
| 95 |
+
raise ValueError(
|
| 96 |
+
f"Attention weights should be of size {(bsz * self.num_heads, tgt_len, src_len)}, but is"
|
| 97 |
+
f" {attn_weights.size()}"
|
| 98 |
+
)
|
| 99 |
+
|
| 100 |
+
# apply the causal_attention_mask first
|
| 101 |
+
if causal_attention_mask is not None:
|
| 102 |
+
if causal_attention_mask.size() != (bsz, 1, tgt_len, src_len):
|
| 103 |
+
raise ValueError(
|
| 104 |
+
f"Attention mask should be of size {(bsz, 1, tgt_len, src_len)}, but is"
|
| 105 |
+
f" {causal_attention_mask.size()}"
|
| 106 |
+
)
|
| 107 |
+
attn_weights = (
|
| 108 |
+
attn_weights.view(bsz, self.num_heads, tgt_len, src_len)
|
| 109 |
+
+ causal_attention_mask
|
| 110 |
+
)
|
| 111 |
+
attn_weights = attn_weights.view(bsz * self.num_heads, tgt_len, src_len)
|
| 112 |
+
|
| 113 |
+
if attention_mask is not None:
|
| 114 |
+
if attention_mask.size() != (bsz, 1, tgt_len, src_len):
|
| 115 |
+
raise ValueError(
|
| 116 |
+
f"Attention mask should be of size {(bsz, 1, tgt_len, src_len)}, but is {attention_mask.size()}"
|
| 117 |
+
)
|
| 118 |
+
attn_weights = (
|
| 119 |
+
attn_weights.view(bsz, self.num_heads, tgt_len, src_len)
|
| 120 |
+
+ attention_mask
|
| 121 |
+
)
|
| 122 |
+
attn_weights = attn_weights.view(bsz * self.num_heads, tgt_len, src_len)
|
| 123 |
+
|
| 124 |
+
attn_weights = nn.functional.softmax(attn_weights, dim=-1)
|
| 125 |
+
|
| 126 |
+
if output_attentions:
|
| 127 |
+
# this operation is a bit akward, but it's required to
|
| 128 |
+
# make sure that attn_weights keeps its gradient.
|
| 129 |
+
# In order to do so, attn_weights have to reshaped
|
| 130 |
+
# twice and have to be reused in the following
|
| 131 |
+
attn_weights_reshaped = attn_weights.view(
|
| 132 |
+
bsz, self.num_heads, tgt_len, src_len
|
| 133 |
+
)
|
| 134 |
+
attn_weights = attn_weights_reshaped.view(
|
| 135 |
+
bsz * self.num_heads, tgt_len, src_len
|
| 136 |
+
)
|
| 137 |
+
else:
|
| 138 |
+
attn_weights_reshaped = None
|
| 139 |
+
|
| 140 |
+
attn_probs = nn.functional.dropout(
|
| 141 |
+
attn_weights, p=self.dropout, training=self.training
|
| 142 |
+
)
|
| 143 |
+
|
| 144 |
+
attn_output = torch.bmm(attn_probs, value_states)
|
| 145 |
+
|
| 146 |
+
if attn_output.size() != (bsz * self.num_heads, tgt_len, self.head_dim):
|
| 147 |
+
raise ValueError(
|
| 148 |
+
f"`attn_output` should be of size {(bsz, self.num_heads, tgt_len, self.head_dim)}, but is"
|
| 149 |
+
f" {attn_output.size()}"
|
| 150 |
+
)
|
| 151 |
+
|
| 152 |
+
attn_output = attn_output.view(bsz, self.num_heads, tgt_len, self.head_dim)
|
| 153 |
+
attn_output = attn_output.transpose(1, 2)
|
| 154 |
+
attn_output = attn_output.reshape(bsz, tgt_len, embed_dim)
|
| 155 |
+
|
| 156 |
+
attn_output = self.out_proj(attn_output)
|
| 157 |
+
|
| 158 |
+
return attn_output, attn_weights_reshaped
|
| 159 |
+
|
| 160 |
+
|
| 161 |
+
class CLIPMLP(nn.Module):
|
| 162 |
+
def __init__(self, config):
|
| 163 |
+
super().__init__()
|
| 164 |
+
self.config = config
|
| 165 |
+
self.activation_fn = ACT2FN[config.hidden_act]
|
| 166 |
+
self.fc1 = nn.Linear(config.hidden_size, config.intermediate_size)
|
| 167 |
+
self.fc2 = nn.Linear(config.intermediate_size, config.hidden_size)
|
| 168 |
+
|
| 169 |
+
def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
|
| 170 |
+
hidden_states = self.fc1(hidden_states)
|
| 171 |
+
hidden_states = self.activation_fn(hidden_states)
|
| 172 |
+
hidden_states = self.fc2(hidden_states)
|
| 173 |
+
return hidden_states
|
| 174 |
+
|
| 175 |
+
|
| 176 |
+
class CLIPEncoderLayer(nn.Module):
|
| 177 |
+
def __init__(self, config: CLIPConfig):
|
| 178 |
+
super().__init__()
|
| 179 |
+
self.embed_dim = config.hidden_size
|
| 180 |
+
self.self_attn = CLIPAttention(config)
|
| 181 |
+
self.layer_norm1 = nn.LayerNorm(self.embed_dim)
|
| 182 |
+
self.mlp = CLIPMLP(config)
|
| 183 |
+
self.layer_norm2 = nn.LayerNorm(self.embed_dim)
|
| 184 |
+
|
| 185 |
+
def forward(
|
| 186 |
+
self,
|
| 187 |
+
hidden_states: torch.Tensor,
|
| 188 |
+
attention_mask: torch.Tensor,
|
| 189 |
+
causal_attention_mask: torch.Tensor,
|
| 190 |
+
output_attentions: Optional[bool] = False,
|
| 191 |
+
) -> Tuple[torch.FloatTensor]:
|
| 192 |
+
"""
|
| 193 |
+
Args:
|
| 194 |
+
hidden_states (`torch.FloatTensor`): input to the layer of shape `(batch, seq_len, embed_dim)`
|
| 195 |
+
attention_mask (`torch.FloatTensor`): attention mask of size
|
| 196 |
+
`(batch, 1, tgt_len, src_len)` where padding elements are indicated by very large negative values.
|
| 197 |
+
`(config.encoder_attention_heads,)`.
|
| 198 |
+
output_attentions (`bool`, *optional*):
|
| 199 |
+
Whether or not to return the attentions tensors of all attention layers. See `attentions` under
|
| 200 |
+
returned tensors for more detail.
|
| 201 |
+
"""
|
| 202 |
+
residual = hidden_states
|
| 203 |
+
|
| 204 |
+
hidden_states = self.layer_norm1(hidden_states)
|
| 205 |
+
hidden_states, attn_weights = self.self_attn(
|
| 206 |
+
hidden_states=hidden_states,
|
| 207 |
+
attention_mask=attention_mask,
|
| 208 |
+
causal_attention_mask=causal_attention_mask,
|
| 209 |
+
output_attentions=output_attentions,
|
| 210 |
+
)
|
| 211 |
+
hidden_states = residual + hidden_states
|
| 212 |
+
|
| 213 |
+
residual = hidden_states
|
| 214 |
+
hidden_states = self.layer_norm2(hidden_states)
|
| 215 |
+
hidden_states = self.mlp(hidden_states)
|
| 216 |
+
hidden_states = residual + hidden_states
|
| 217 |
+
|
| 218 |
+
outputs = (hidden_states,)
|
| 219 |
+
|
| 220 |
+
if output_attentions:
|
| 221 |
+
outputs += (attn_weights,)
|
| 222 |
+
|
| 223 |
+
return outputs
|
| 224 |
+
|
| 225 |
+
|
| 226 |
+
def make_fused_vision_attn(model, dev):
|
| 227 |
+
"""
|
| 228 |
+
Replace all LlamaAttention modules with QuantLlamaAttention modules, fusing the q, k, v projections.
|
| 229 |
+
"""
|
| 230 |
+
model = model.cpu()
|
| 231 |
+
for name, m in model.named_modules():
|
| 232 |
+
if not m.__class__.__name__ in ["CLIPAttention", "CLIPAttentionFused"]:
|
| 233 |
+
continue
|
| 234 |
+
|
| 235 |
+
q_proj = m.q_proj
|
| 236 |
+
k_proj = m.k_proj
|
| 237 |
+
v_proj = m.v_proj
|
| 238 |
+
|
| 239 |
+
weights = torch.cat([q_proj.weight, k_proj.weight, v_proj.weight], dim=0)
|
| 240 |
+
bias = (
|
| 241 |
+
torch.cat([q_proj.bias, k_proj.bias, v_proj.bias], dim=0)
|
| 242 |
+
if q_proj.bias is not None
|
| 243 |
+
else None
|
| 244 |
+
)
|
| 245 |
+
|
| 246 |
+
qkv_layer = nn.Linear(
|
| 247 |
+
q_proj.in_features,
|
| 248 |
+
q_proj.out_features + k_proj.out_features + v_proj.out_features,
|
| 249 |
+
q_proj.bias is not None,
|
| 250 |
+
q_proj.weight.device,
|
| 251 |
+
)
|
| 252 |
+
qkv_layer.weight.data = weights
|
| 253 |
+
|
| 254 |
+
qkv_layer.bias.data = bias
|
| 255 |
+
if isinstance(m, CLIPAttention):
|
| 256 |
+
attn = CLIPAttentionFused(
|
| 257 |
+
m.embed_dim, m.num_heads, qkv_layer, m.out_proj, dev
|
| 258 |
+
)
|
| 259 |
+
if "." in name:
|
| 260 |
+
parent_name = name.rsplit(".", 1)[0]
|
| 261 |
+
child_name = name[len(parent_name) + 1 :]
|
| 262 |
+
parent = model.get_submodule(parent_name)
|
| 263 |
+
else:
|
| 264 |
+
parent_name = ""
|
| 265 |
+
parent = model
|
| 266 |
+
child_name = name
|
| 267 |
+
|
| 268 |
+
# print(f"Replacing {name} with quant_attn; parent: {parent_name}, child's name: {child_name}")
|
| 269 |
+
setattr(parent, child_name, attn)
|
| 270 |
+
gc.collect()
|
| 271 |
+
torch.cuda.empty_cache()
|
| 272 |
+
model = model.to(dev)
|