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
- baselines_1/Llama-2-7b-hf_bi_idx_10.json +34 -0
- baselines_1/Llama-2-7b-hf_bi_idx_5.json +34 -0
- baselines_1/Llama-2-7b-hf_zd_idx_10.json +34 -0
- baselines_1/Llama-2-7b-hf_zd_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/.gitignore +173 -0
- llm-awq/LICENSE +21 -0
- llm-awq/README.md +292 -0
- llm-awq/awq.egg-info/PKG-INFO +319 -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.h +185 -0
- llm-awq/awq/kernels/csrc/attention/decoder_masked_multihead_attention_template.hpp +1608 -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/attention/setup.py +159 -0
- llm-awq/awq/kernels/csrc/layernorm/layernorm.cu +131 -0
- llm-awq/awq/kernels/csrc/layernorm/layernorm.h +3 -0
- llm-awq/awq/kernels/csrc/layernorm/reduction.cuh +82 -0
- llm-awq/awq/kernels/csrc/position_embedding/pos_encoding.h +9 -0
- llm-awq/awq/kernels/csrc/position_embedding/pos_encoding_kernels.cu +88 -0
- llm-awq/awq/kernels/csrc/pybind.cpp +38 -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 |
+
]
|
baselines_1/Llama-2-7b-hf_bi_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 |
+
2,
|
| 29 |
+
2,
|
| 30 |
+
2,
|
| 31 |
+
2,
|
| 32 |
+
4,
|
| 33 |
+
4
|
| 34 |
+
]
|
baselines_1/Llama-2-7b-hf_bi_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 |
+
4,
|
| 23 |
+
4,
|
| 24 |
+
4,
|
| 25 |
+
4,
|
| 26 |
+
2,
|
| 27 |
+
2,
|
| 28 |
+
2,
|
| 29 |
+
2,
|
| 30 |
+
2,
|
| 31 |
+
4,
|
| 32 |
+
4,
|
| 33 |
+
4
|
| 34 |
+
]
|
baselines_1/Llama-2-7b-hf_zd_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 |
+
2,
|
| 20 |
+
2,
|
| 21 |
+
4,
|
| 22 |
+
2,
|
| 23 |
+
2,
|
| 24 |
+
2,
|
| 25 |
+
2,
|
| 26 |
+
4,
|
| 27 |
+
2,
|
| 28 |
+
2,
|
| 29 |
+
2,
|
| 30 |
+
2,
|
| 31 |
+
4,
|
| 32 |
+
4,
|
| 33 |
+
4
|
| 34 |
+
]
|
baselines_1/Llama-2-7b-hf_zd_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 |
+
4,
|
| 23 |
+
4,
|
| 24 |
+
2,
|
| 25 |
+
2,
|
| 26 |
+
4,
|
| 27 |
+
2,
|
| 28 |
+
4,
|
| 29 |
+
2,
|
| 30 |
+
2,
|
| 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/.gitignore
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.DS_Store
|
| 2 |
+
|
| 3 |
+
data/
|
| 4 |
+
checkpoints
|
| 5 |
+
demo_images
|
| 6 |
+
serve_images
|
| 7 |
+
# Byte-compiled / optimized / DLL files
|
| 8 |
+
__pycache__/
|
| 9 |
+
*.py[cod]
|
| 10 |
+
*$py.class
|
| 11 |
+
|
| 12 |
+
# C extensions
|
| 13 |
+
*.so
|
| 14 |
+
|
| 15 |
+
# Distribution / packaging
|
| 16 |
+
.Python
|
| 17 |
+
*.pyc
|
| 18 |
+
build/
|
| 19 |
+
develop-eggs/
|
| 20 |
+
dist/
|
| 21 |
+
downloads/
|
| 22 |
+
eggs/
|
| 23 |
+
.eggs/
|
| 24 |
+
lib/
|
| 25 |
+
lib64/
|
| 26 |
+
parts/
|
| 27 |
+
sdist/
|
| 28 |
+
var/
|
| 29 |
+
wheels/
|
| 30 |
+
share/python-wheels/
|
| 31 |
+
*.egg-info/
|
| 32 |
+
.installed.cfg
|
| 33 |
+
*.egg
|
| 34 |
+
MANIFEST
|
| 35 |
+
|
| 36 |
+
# PyInstaller
|
| 37 |
+
# Usually these files are written by a python script from a template
|
| 38 |
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
| 39 |
+
*.manifest
|
| 40 |
+
*.spec
|
| 41 |
+
|
| 42 |
+
# Installer logs
|
| 43 |
+
pip-log.txt
|
| 44 |
+
pip-delete-this-directory.txt
|
| 45 |
+
|
| 46 |
+
# Unit test / coverage reports
|
| 47 |
+
htmlcov/
|
| 48 |
+
.tox/
|
| 49 |
+
.nox/
|
| 50 |
+
.coverage
|
| 51 |
+
.coverage.*
|
| 52 |
+
.cache
|
| 53 |
+
nosetests.xml
|
| 54 |
+
coverage.xml
|
| 55 |
+
*.cover
|
| 56 |
+
*.py,cover
|
| 57 |
+
.hypothesis/
|
| 58 |
+
.pytest_cache/
|
| 59 |
+
cover/
|
| 60 |
+
|
| 61 |
+
# Translations
|
| 62 |
+
*.mo
|
| 63 |
+
*.pot
|
| 64 |
+
|
| 65 |
+
# Django stuff:
|
| 66 |
+
*.log
|
| 67 |
+
local_settings.py
|
| 68 |
+
db.sqlite3
|
| 69 |
+
db.sqlite3-journal
|
| 70 |
+
|
| 71 |
+
# Flask stuff:
|
| 72 |
+
instance/
|
| 73 |
+
.webassets-cache
|
| 74 |
+
|
| 75 |
+
# Scrapy stuff:
|
| 76 |
+
.scrapy
|
| 77 |
+
|
| 78 |
+
# Sphinx documentation
|
| 79 |
+
docs/_build/
|
| 80 |
+
|
| 81 |
+
# PyBuilder
|
| 82 |
+
.pybuilder/
|
| 83 |
+
target/
|
| 84 |
+
|
| 85 |
+
# Jupyter Notebook
|
| 86 |
+
.ipynb_checkpoints
|
| 87 |
+
|
| 88 |
+
# IPython
|
| 89 |
+
profile_default/
|
| 90 |
+
ipython_config.py
|
| 91 |
+
|
| 92 |
+
# pyenv
|
| 93 |
+
# For a library or package, you might want to ignore these files since the code is
|
| 94 |
+
# intended to run in multiple environments; otherwise, check them in:
|
| 95 |
+
# .python-version
|
| 96 |
+
|
| 97 |
+
# pipenv
|
| 98 |
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
| 99 |
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
| 100 |
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
| 101 |
+
# install all needed dependencies.
|
| 102 |
+
#Pipfile.lock
|
| 103 |
+
|
| 104 |
+
# poetry
|
| 105 |
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
| 106 |
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
| 107 |
+
# commonly ignored for libraries.
|
| 108 |
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
| 109 |
+
#poetry.lock
|
| 110 |
+
|
| 111 |
+
# pdm
|
| 112 |
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
| 113 |
+
#pdm.lock
|
| 114 |
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
| 115 |
+
# in version control.
|
| 116 |
+
# https://pdm.fming.dev/#use-with-ide
|
| 117 |
+
.pdm.toml
|
| 118 |
+
|
| 119 |
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
| 120 |
+
__pypackages__/
|
| 121 |
+
|
| 122 |
+
# Celery stuff
|
| 123 |
+
celerybeat-schedule
|
| 124 |
+
celerybeat.pid
|
| 125 |
+
|
| 126 |
+
# SageMath parsed files
|
| 127 |
+
*.sage.py
|
| 128 |
+
|
| 129 |
+
# Environments
|
| 130 |
+
.env
|
| 131 |
+
.venv
|
| 132 |
+
env/
|
| 133 |
+
venv/
|
| 134 |
+
ENV/
|
| 135 |
+
env.bak/
|
| 136 |
+
venv.bak/
|
| 137 |
+
|
| 138 |
+
# Spyder project settings
|
| 139 |
+
.spyderproject
|
| 140 |
+
.spyproject
|
| 141 |
+
|
| 142 |
+
# Rope project settings
|
| 143 |
+
.ropeproject
|
| 144 |
+
|
| 145 |
+
# mkdocs documentation
|
| 146 |
+
/site
|
| 147 |
+
|
| 148 |
+
# mypy
|
| 149 |
+
.mypy_cache/
|
| 150 |
+
.dmypy.json
|
| 151 |
+
dmypy.json
|
| 152 |
+
|
| 153 |
+
# Pyre type checker
|
| 154 |
+
.pyre/
|
| 155 |
+
|
| 156 |
+
# pytype static type analyzer
|
| 157 |
+
.pytype/
|
| 158 |
+
|
| 159 |
+
# Cython debug symbols
|
| 160 |
+
cython_debug/
|
| 161 |
+
|
| 162 |
+
# PyCharm
|
| 163 |
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
| 164 |
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
| 165 |
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
| 166 |
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
| 167 |
+
#.idea/
|
| 168 |
+
|
| 169 |
+
*.pt
|
| 170 |
+
**/*.pt
|
| 171 |
+
**/*.pyc
|
| 172 |
+
*.json
|
| 173 |
+
__pycache__
|
llm-awq/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
MIT License
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2023 MIT HAN Lab
|
| 4 |
+
|
| 5 |
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
| 6 |
+
of this software and associated documentation files (the "Software"), to deal
|
| 7 |
+
in the Software without restriction, including without limitation the rights
|
| 8 |
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
| 9 |
+
copies of the Software, and to permit persons to whom the Software is
|
| 10 |
+
furnished to do so, subject to the following conditions:
|
| 11 |
+
|
| 12 |
+
The above copyright notice and this permission notice shall be included in all
|
| 13 |
+
copies or substantial portions of the Software.
|
| 14 |
+
|
| 15 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 16 |
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 17 |
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
| 18 |
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
| 19 |
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
| 20 |
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
| 21 |
+
SOFTWARE.
|
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.egg-info/PKG-INFO
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Metadata-Version: 2.4
|
| 2 |
+
Name: awq
|
| 3 |
+
Version: 0.1.0
|
| 4 |
+
Summary: An efficient and accurate low-bit weight quantization(INT3/4) method for LLMs.
|
| 5 |
+
Classifier: Programming Language :: Python :: 3
|
| 6 |
+
Classifier: License :: OSI Approved :: Apache Software License
|
| 7 |
+
Requires-Python: >=3.8
|
| 8 |
+
Description-Content-Type: text/markdown
|
| 9 |
+
License-File: LICENSE
|
| 10 |
+
Requires-Dist: accelerate==0.34.2
|
| 11 |
+
Requires-Dist: sentencepiece
|
| 12 |
+
Requires-Dist: tokenizers>=0.12.1
|
| 13 |
+
Requires-Dist: torch==2.3.0
|
| 14 |
+
Requires-Dist: torchvision==0.18.0
|
| 15 |
+
Requires-Dist: transformers==4.46.0
|
| 16 |
+
Requires-Dist: lm_eval==0.3.0
|
| 17 |
+
Requires-Dist: texttable
|
| 18 |
+
Requires-Dist: toml
|
| 19 |
+
Requires-Dist: attributedict
|
| 20 |
+
Requires-Dist: protobuf
|
| 21 |
+
Requires-Dist: gradio==3.35.2
|
| 22 |
+
Requires-Dist: gradio_client==0.2.9
|
| 23 |
+
Requires-Dist: fastapi
|
| 24 |
+
Requires-Dist: uvicorn
|
| 25 |
+
Requires-Dist: pydantic==1.10.19
|
| 26 |
+
Dynamic: license-file
|
| 27 |
+
|
| 28 |
+
# AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration
|
| 29 |
+
[[Paper](https://arxiv.org/abs/2306.00978)][[Website](https://hanlab.mit.edu/projects/awq)]
|
| 30 |
+
|
| 31 |
+
**Efficient and accurate** low-bit weight quantization (INT3/4) for LLMs, supporting **instruction-tuned** models and **multi-modal** LMs.
|
| 32 |
+
|
| 33 |
+

|
| 34 |
+
|
| 35 |
+
The current release supports:
|
| 36 |
+
|
| 37 |
+
- AWQ search for accurate quantization.
|
| 38 |
+
- Pre-computed AWQ model zoo for LLMs (Llama-1/2/3, OPT, CodeLlama, StarCoder, Vicuna, VILA, LLaVA; load to generate quantized weights).
|
| 39 |
+
- Memory-efficient 4-bit Linear in PyTorch.
|
| 40 |
+
- Efficient CUDA kernel implementation for fast inference (support context and decoding stage).
|
| 41 |
+
- Examples on 4-bit inference of an instruction-tuned model (Vicuna) and **multi-modal LM** (VILA).
|
| 42 |
+
- Chunk prefilling for faster prefilling in multi-round Q&A setting.
|
| 43 |
+
- State-of-the-art prefilling speed of LLMs/VLMs on edge devices: [TinyChat 2.0](./tinychat).
|
| 44 |
+
|
| 45 |
+
**Thanks to AWQ, TinyChat can deliver more efficient responses with LLM/VLM chatbots through 4-bit inference.**
|
| 46 |
+
|
| 47 |
+
* TinyChat with LLaMA-3-8b on RTX 4090 (2.7x faster than FP16):
|
| 48 |
+
|
| 49 |
+

|
| 50 |
+
|
| 51 |
+
* TinyChat with LLaMA-3-8b on Jetson Orin (2.9x faster than FP16):
|
| 52 |
+
|
| 53 |
+

|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
**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.**
|
| 57 |
+
|
| 58 |
+
* TinyChat with NVILA-8B on RTX 4090 (single-image inputs):
|
| 59 |
+
|
| 60 |
+

|
| 61 |
+
|
| 62 |
+
* TinyChat with NVILA-8B on RTX 4090 (multi-image inputs):
|
| 63 |
+
|
| 64 |
+

|
| 65 |
+
|
| 66 |
+
<!-- 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! -->
|
| 67 |
+
|
| 68 |
+
* TinyChat with video reasoning:
|
| 69 |
+
|
| 70 |
+
https://github.com/user-attachments/assets/b68a7a0d-5175-4030-985b-5ae0ae94f874
|
| 71 |
+
|
| 72 |
+
**Prompt:** What might be the next step according to the video?
|
| 73 |
+
|
| 74 |
+
**Answer:** The next step in the video could be to place the shaped dough onto a baking sheet and let it rise before baking.
|
| 75 |
+
|
| 76 |
+
**Online demo:** https://vila.hanlab.ai
|
| 77 |
+
|
| 78 |
+
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!
|
| 79 |
+
|
| 80 |
+
|
| 81 |
+
## News
|
| 82 |
+
- [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)!
|
| 83 |
+
- [2025/02] AWQ now supports BF16 precision. See example [here](https://github.com/mit-han-lab/llm-awq/blob/main/scripts/qwen_example.sh).
|
| 84 |
+
- [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.
|
| 85 |
+
- [2024/05] 🏆 AWQ receives the **Best Paper Award** at **MLSys 2024**. 🎉
|
| 86 |
+
- [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).
|
| 87 |
+
- [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.
|
| 88 |
+
- [2024/04] 🔥 We released AWQ and TinyChat support for The **Llama-3** model family! Check out our example [here](scripts/llama3_example.sh).
|
| 89 |
+
- [2024/02] 🔥 AWQ has been accepted to **MLSys 2024**!
|
| 90 |
+
- [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!
|
| 91 |
+
- [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!
|
| 92 |
+
- [2024/01] 🔥 AWQ has been integrated by [Google Vertex AI](https://console.cloud.google.com/vertex-ai/publishers/meta/model-garden/llama-2-quantized)!
|
| 93 |
+
- [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/)!
|
| 94 |
+
- [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)!
|
| 95 |
+
- [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.
|
| 96 |
+
- [2023/10] AWQ is integrated into NVIDIA [TensorRT-LLM](https://github.com/NVIDIA/TensorRT-LLM/)
|
| 97 |
+
- [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).
|
| 98 |
+
- [2023/09] ⚡ Check out our latest [**TinyChat**](tinychat), which is ~2x faster than the first release on Orin!
|
| 99 |
+
- [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.
|
| 100 |
+
- [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).
|
| 101 |
+
- [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)!
|
| 102 |
+
- [2023/07] We extended the support for more LLM models including MPT, Falcon, and BLOOM.
|
| 103 |
+
|
| 104 |
+
## Contents
|
| 105 |
+
|
| 106 |
+
- [AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration](#awq-activation-aware-weight-quantization-for-llm-compression-and-acceleration)
|
| 107 |
+
- [News](#news)
|
| 108 |
+
- [Contents](#contents)
|
| 109 |
+
- [Helpful Links](#helpful-links)
|
| 110 |
+
- [Install](#install)
|
| 111 |
+
- [AWQ Model Zoo](#awq-model-zoo)
|
| 112 |
+
- [Examples](#examples)
|
| 113 |
+
- [Usage](#usage)
|
| 114 |
+
- [Results on Visual Language Models](#results-on-visual-language-models)
|
| 115 |
+
- [Reference](#reference)
|
| 116 |
+
- [Related Projects](#related-projects)
|
| 117 |
+
|
| 118 |
+
## Helpful Links
|
| 119 |
+
|
| 120 |
+
- [VILA online demo](vila.hanlab.ai): Visual Language Models efficiently supported by AWQ & TinyChat.
|
| 121 |
+
- [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.
|
| 122 |
+
- [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.
|
| 123 |
+
- [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!
|
| 124 |
+
- [QServe](https://github.com/mit-han-lab/qserve): 🔥 **[New]** Efficient and accurate serving system for large-scale LLM inference.
|
| 125 |
+
|
| 126 |
+
## Install
|
| 127 |
+
|
| 128 |
+
1. Clone this repository and navigate to AWQ folder
|
| 129 |
+
```
|
| 130 |
+
git clone https://github.com/mit-han-lab/llm-awq
|
| 131 |
+
cd llm-awq
|
| 132 |
+
```
|
| 133 |
+
|
| 134 |
+
2. Install Package
|
| 135 |
+
```
|
| 136 |
+
conda create -n awq python=3.10 -y
|
| 137 |
+
conda activate awq
|
| 138 |
+
pip install --upgrade pip # enable PEP 660 support
|
| 139 |
+
pip install -e .
|
| 140 |
+
```
|
| 141 |
+
|
| 142 |
+
* For **edge devices** like Orin, before running the commands above, please:
|
| 143 |
+
|
| 144 |
+
1. Modify [pyproject.toml](pyproject.toml) by commenting out [this line](https://github.com/mit-han-lab/llm-awq/blob/3fce69061682fdd528824e5da3d03a8a8b545f2a/pyproject.toml#L17).
|
| 145 |
+
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.
|
| 146 |
+
3. Set the appropriate Python version for conda environment (e.g., `conda create -n awq python=3.8 -y` for JetPack 5).
|
| 147 |
+
|
| 148 |
+
3. Install efficient W4A16 (4-bit weight, 16-bit activation) CUDA kernel and optimized FP16 kernels (e.g. layernorm, positional encodings).
|
| 149 |
+
```
|
| 150 |
+
cd awq/kernels
|
| 151 |
+
python setup.py install
|
| 152 |
+
```
|
| 153 |
+
|
| 154 |
+
4. Install Flash Attention
|
| 155 |
+
```
|
| 156 |
+
pip install flash-attn --no-build-isolation
|
| 157 |
+
```
|
| 158 |
+
|
| 159 |
+
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:
|
| 160 |
+
|
| 161 |
+
- PyTorch version needs to exactly match with the version specified in the `.whl` name;
|
| 162 |
+
- Check out both `cxx11abiTRUE` and `cxx11abiFALSE` wheels if one of them does not work;
|
| 163 |
+
- 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.
|
| 164 |
+
|
| 165 |
+
|
| 166 |
+
5. [Optional] In order to run AWQ and TinyChat with NVILA model family, please install VILA:
|
| 167 |
+
|
| 168 |
+
```bash
|
| 169 |
+
git clone https://github.com/NVlabs/VILA.git
|
| 170 |
+
cd VILA
|
| 171 |
+
pip install -e .
|
| 172 |
+
```
|
| 173 |
+
|
| 174 |
+
## AWQ Model Zoo
|
| 175 |
+
|
| 176 |
+
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:
|
| 177 |
+
|
| 178 |
+
```bash
|
| 179 |
+
# git lfs install # install git lfs if not already
|
| 180 |
+
git clone https://huggingface.co/datasets/mit-han-lab/awq-model-zoo awq_cache
|
| 181 |
+
```
|
| 182 |
+
|
| 183 |
+
The detailed support list:
|
| 184 |
+
|
| 185 |
+
| Models | Sizes | INT4-g128 | INT3-g128 |
|
| 186 |
+
| ------ | --------------------------- | --------- | --------- |
|
| 187 |
+
| [DeepSeek-R1-Distill](/scripts/DeepSeek_R1_Distill_example.sh) | 1.5B/7B/8B | ✅ | |
|
| 188 |
+
| [Qwen-2.5](/scripts/qwen_example.sh) | 7B/72B | ✅ | |
|
| 189 |
+
| [NVILA](/scripts/nvila_example.sh) | 3B/8B | ✅ | |
|
| 190 |
+
| [VILA-1.5](/scripts/vila15_example.sh) | 3B/8B/13B/40B | ✅ | ✅ |
|
| 191 |
+
| [Llama3](/scripts/llama_example.sh) | 8B/70B | ✅ | ✅ |
|
| 192 |
+
| [VILA](/scripts/vila_example.sh) | 7B/13B | ✅ | |
|
| 193 |
+
| [Llama2](/scripts/llama_example.sh) | 7B/13B/70B | ✅ | ✅ |
|
| 194 |
+
| [LLaMA](/scripts/llama2_example.sh) | 7B/13B/30B/65B | ✅ | ✅ |
|
| 195 |
+
| [OPT](/scripts/opt_example.sh) | 125m/1.3B/2.7B/6.7B/13B/30B | ✅ | ✅ |
|
| 196 |
+
| [CodeLlama](/scripts/codellama_example.sh) | 7B/13B/34B | ✅ | ✅ |
|
| 197 |
+
| [StarCoder](/scripts/starcoder_example.sh) | 15.5B | ✅ | ✅ |
|
| 198 |
+
| [Vicuna-v1.1](/scripts/vicuna_example.sh) | 7B/13B | ✅ | |
|
| 199 |
+
| [LLaVA-v0](/scripts/llava_example.sh) | 13B | ✅ | |
|
| 200 |
+
|
| 201 |
+
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).
|
| 202 |
+
|
| 203 |
+
## Examples
|
| 204 |
+
|
| 205 |
+
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.
|
| 206 |
+
|
| 207 |
+
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.
|
| 208 |
+
|
| 209 |
+
Note that we perform AWQ using only textual calibration data, depsite we are running on multi-modal input. Please refer to `./examples` for details.
|
| 210 |
+
|
| 211 |
+

|
| 212 |
+
|
| 213 |
+
## Usage
|
| 214 |
+
|
| 215 |
+
We provide several sample script to run AWQ (please refer to `./scripts`). We use Llama3-8B as an example.
|
| 216 |
+
|
| 217 |
+
1. Perform AWQ search and save search results (we already did it for you):
|
| 218 |
+
```bash
|
| 219 |
+
python -m awq.entry --model_path /PATH/TO/LLAMA3/llama3-8b \
|
| 220 |
+
--w_bit 4 --q_group_size 128 \
|
| 221 |
+
--run_awq --dump_awq awq_cache/llama3-8b-w4-g128.pt
|
| 222 |
+
```
|
| 223 |
+
|
| 224 |
+
2. Evaluate the AWQ quantized model on WikiText-2 (simulated pseudo quantization)
|
| 225 |
+
```bash
|
| 226 |
+
python -m awq.entry --model_path /PATH/TO/LLAMA3/llama3-8b \
|
| 227 |
+
--tasks wikitext \
|
| 228 |
+
--w_bit 4 --q_group_size 128 \
|
| 229 |
+
--load_awq awq_cache/llama3-8b-w4-g128.pt \
|
| 230 |
+
--q_backend fake
|
| 231 |
+
```
|
| 232 |
+
|
| 233 |
+
3. Generate real quantized weights (INT4)
|
| 234 |
+
```bash
|
| 235 |
+
mkdir quant_cache
|
| 236 |
+
python -m awq.entry --model_path /PATH/TO/LLAMA3/llama3-8b \
|
| 237 |
+
--w_bit 4 --q_group_size 128 \
|
| 238 |
+
--load_awq awq_cache/llama3-8b-w4-g128.pt \
|
| 239 |
+
--q_backend real --dump_quant quant_cache/llama3-8b-w4-g128-awq.pt
|
| 240 |
+
```
|
| 241 |
+
|
| 242 |
+
4. Load and evaluate the real quantized model (now you can see smaller gpu memory usage)
|
| 243 |
+
```bash
|
| 244 |
+
python -m awq.entry --model_path /PATH/TO/LLAMA3/llama3-8b \
|
| 245 |
+
--tasks wikitext \
|
| 246 |
+
--w_bit 4 --q_group_size 128 \
|
| 247 |
+
--load_quant quant_cache/llama3-8b-w4-g128-awq.pt
|
| 248 |
+
```
|
| 249 |
+
## Results on Visual Language Models
|
| 250 |
+
|
| 251 |
+
AWQ also seamlessly supports large multi-modal models (LMMs). Please refer to [TinyChat](./tinychat/README.md) for more details.
|
| 252 |
+
|
| 253 |
+
|
| 254 |
+
<!-- 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. -->
|
| 255 |
+
|
| 256 |
+
<!--
|
| 257 |
+
| VILA-1.5-3B | VQA-v2 | GQA | VizWiz | ScienceQA | TextVQA | POPE | MME | MMBench | MMBench-CN | SEED |
|
| 258 |
+
| ----------- |:-----------------:|:-----------------:|:-------:|:-----------------:|:-----------------:|:-------:|:-------:|:-----------------:|:-------------:|:-------:|
|
| 259 |
+
| FP16 | 80.4 | 61.5 | 53.5 | 69.0 | 60.4 | 85.9 | 1442.4 | 63.4 | 52.7 | 60.9 |
|
| 260 |
+
| AWQ-INT4 | 80.0 | 61.1 | 53.8 | 67.8 | 60.4 | 85.9 | 1437.3 | 63.3 | 51.4 | 59.8 |
|
| 261 |
+
|
| 262 |
+
| VILA-1.5-8B | VQA-v2 | GQA | VizWiz | ScienceQA | TextVQA | POPE | MME | MMBench | MMBench-CN | SEED |
|
| 263 |
+
| ----------- |:-----------------:|:-----------------:|:-------:|:-----------------:|:-----------------:|:-------:|:-------:|:-----------------:|:-------------:|:-------:|
|
| 264 |
+
| FP16 | 80.9 | 61.9 | 58.7 | 79.9 | 66.3 | 84.4 | 1577.01 | 72.3 | 66.2 | 64.2 |
|
| 265 |
+
| AWQ-INT4 | 80.3 | 61.7 | 59.3 | 79.0 | 65.4 | 82.9 | 1593.65 | 71.0 | 64.9 | 64.0 |
|
| 266 |
+
|
| 267 |
+
| VILA-1.5-13B | VQA-v2 | GQA | VizWiz | ScienceQA | TextVQA | POPE | MME | MMBench | MMBench-CN | SEED |
|
| 268 |
+
| ----------- |:-----------------:|:-----------------:|:-------:|:-----------------:|:-----------------:|:-------:|:-------:|:-----------------:|:-------------:|:-------:|
|
| 269 |
+
| FP16 | 82.8 | 64.3 | 62.6 | 80.1 | 65.0 | 86.3 | 1569.55 | 74.9 | 66.3 | 65.1 |
|
| 270 |
+
| AWQ-INT4 | 82.7 | 64.5 | 63.3 | 79.7 | 64.7 | 86.7 | 1531.35 | 74.7 | 66.7 | 65.1 |
|
| 271 |
+
|
| 272 |
+
|
| 273 |
+
| VILA-1.5-40B | VQA-v2 | GQA | VizWiz | ScienceQA | TextVQA | POPE | MME | MMBench | MMBench-CN | SEED |
|
| 274 |
+
| ----------- |:-----------------:|:-----------------:|:-------:|:-----------------:|:-----------------:|:-------:|:-------:|:-----------------:|:-------------:|:-------:|
|
| 275 |
+
| FP16 | 84.3 | 64.6 | 62.2 | 87.2 | 73.6 | 87.3 | 1726.82 | 82.4 | 80.2 | 69.1 |
|
| 276 |
+
| AWQ-INT4 | 84.1 | 64.4 | 61.3 | 86.7 | 73.2 | 88.2 | 1714.79 | 83.2 | 79.6 | 68.9 |
|
| 277 |
+
|
| 278 |
+
|
| 279 |
+
## Inference speed ( Token/sec )
|
| 280 |
+
|
| 281 |
+
| $~~~~~~$ | Precision | A100 | 4090 | Orin |
|
| 282 |
+
| ---------------------- | --------- | ----- | ----- | ---- |
|
| 283 |
+
| VILA1.5-3B | fp16 | 104.6 | 137.6 | 25.4 |
|
| 284 |
+
| VILA1.5-3B-AWQ | int4 | 182.8 | 215.5 | 42.5 |
|
| 285 |
+
| VILA1.5-3B-S2 | fp16 | 104.3 | 137.2 | 24.6 |
|
| 286 |
+
| VILA1.5-3B-S2-AWQ | int4 | 180.2 | 219.3 | 40.1 |
|
| 287 |
+
| Llama-3-VILA1.5-8B | fp16 | 74.9 | 57.4 | 10.2 |
|
| 288 |
+
| Llama-3-VILA1.5-8B-AWQ | int4 | 168.9 | 150.2 | 28.7 |
|
| 289 |
+
| VILA1.5-13B | fp16 | 50.9 | OOM | 6.1 |
|
| 290 |
+
| VILA1.5-13B-AWQ | int4 | 115.9 | 105.7 | 20.6 |
|
| 291 |
+
| VILA1.5-40B | fp16 | OOM | OOM | -- |
|
| 292 |
+
| VILA1.5-40B-AWQ | int4 | 57.0 | OOM | -- | -->
|
| 293 |
+
|
| 294 |
+
|
| 295 |
+
## Reference
|
| 296 |
+
|
| 297 |
+
If you find AWQ useful or relevant to your research, please kindly cite our paper:
|
| 298 |
+
|
| 299 |
+
```
|
| 300 |
+
@inproceedings{lin2023awq,
|
| 301 |
+
title={AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration},
|
| 302 |
+
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},
|
| 303 |
+
booktitle={MLSys},
|
| 304 |
+
year={2024}
|
| 305 |
+
}
|
| 306 |
+
```
|
| 307 |
+
|
| 308 |
+
## Related Projects
|
| 309 |
+
|
| 310 |
+
[SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models](https://github.com/mit-han-lab/smoothquant)
|
| 311 |
+
|
| 312 |
+
[GPTQ: Accurate Post-training Compression for Generative Pretrained Transformers](https://arxiv.org/abs/2210.17323)
|
| 313 |
+
|
| 314 |
+
[Vicuna and FastChat](https://github.com/lm-sys/FastChat#readme)
|
| 315 |
+
|
| 316 |
+
[LLaVA: Large Language and Vision Assistant](https://github.com/haotian-liu/LLaVA)
|
| 317 |
+
|
| 318 |
+
[VILA: On Pre-training for Visual Language Models](https://github.com/Efficient-Large-Model/VILA)
|
| 319 |
+
|
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.h
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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.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_fp16.h>
|
| 23 |
+
#include <cuda_runtime_api.h>
|
| 24 |
+
#include <stdint.h>
|
| 25 |
+
#include <stdio.h>
|
| 26 |
+
#include <stdlib.h>
|
| 27 |
+
|
| 28 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 29 |
+
|
| 30 |
+
#define CHECK_CUDA(call) \
|
| 31 |
+
do { \
|
| 32 |
+
cudaError_t status_ = call; \
|
| 33 |
+
if (status_ != cudaSuccess) { \
|
| 34 |
+
fprintf(stderr, "CUDA error (%s:%d): %s\n", __FILE__, __LINE__, cudaGetErrorString(status_)); \
|
| 35 |
+
exit(1); \
|
| 36 |
+
} \
|
| 37 |
+
} while (0)
|
| 38 |
+
|
| 39 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 40 |
+
|
| 41 |
+
// The structure of parameters for the masked multihead attention kernel.
|
| 42 |
+
//
|
| 43 |
+
// We use the following terminology to describe the different dimensions.
|
| 44 |
+
//
|
| 45 |
+
// B: Batch size (number of sequences),
|
| 46 |
+
// L: Sequence length,
|
| 47 |
+
// D: Hidden dimension,
|
| 48 |
+
// H: Number of heads,
|
| 49 |
+
// Dh: Hidden dimension per head - Dh = D / H.
|
| 50 |
+
|
| 51 |
+
template<typename T>
|
| 52 |
+
struct Multihead_attention_params_base {
|
| 53 |
+
|
| 54 |
+
// The output buffer. Dimensions B x D.
|
| 55 |
+
T* out = nullptr;
|
| 56 |
+
|
| 57 |
+
// The input Qs and the associated bias. Dimensions B x D and D, resp.
|
| 58 |
+
const T *q = nullptr, *q_bias = nullptr;
|
| 59 |
+
// The input Ks and the associated bias. Dimensions B x D and D, resp.
|
| 60 |
+
const T *k = nullptr, *k_bias = nullptr;
|
| 61 |
+
// The input Vs and the associated bias. Dimensions B x D and D, resp.
|
| 62 |
+
const T *v = nullptr, *v_bias = nullptr;
|
| 63 |
+
|
| 64 |
+
// The cache for the Ks. The size must be at least B x L x D.
|
| 65 |
+
T* k_cache = nullptr;
|
| 66 |
+
// The cache for the Vs. The size must be at least B x L x D.
|
| 67 |
+
T* v_cache = nullptr;
|
| 68 |
+
// The indirections to use for cache when beam sampling.
|
| 69 |
+
const int* cache_indir = nullptr;
|
| 70 |
+
|
| 71 |
+
// Stride to handle the case when KQV is a single buffer
|
| 72 |
+
int stride = 0;
|
| 73 |
+
|
| 74 |
+
// The batch size.
|
| 75 |
+
int batch_size = 0;
|
| 76 |
+
// The beam width
|
| 77 |
+
int beam_width = 0;
|
| 78 |
+
// The sequence length.
|
| 79 |
+
int memory_max_len = 0;
|
| 80 |
+
// The number of heads (H).
|
| 81 |
+
int num_heads = 0;
|
| 82 |
+
// The number of heads for KV cache.
|
| 83 |
+
int num_kv_heads = 0;
|
| 84 |
+
// The hidden dimension per head (Dh).
|
| 85 |
+
int hidden_size_per_head = 0;
|
| 86 |
+
// The per-head latent space reserved for rotary embeddings.
|
| 87 |
+
int rotary_embedding_dim = 0;
|
| 88 |
+
bool neox_rotary_style = false;
|
| 89 |
+
float rotary_base = 0.0f;
|
| 90 |
+
float rotary_scale = 1.0f;
|
| 91 |
+
// The maximum length of input sentences.
|
| 92 |
+
int max_input_length = 0;
|
| 93 |
+
// The current timestep. TODO(bhsueh) Check that do we only this param in cross attention?
|
| 94 |
+
int timestep = 0;
|
| 95 |
+
// The current timestep of each sentences (support different timestep for different sentences)
|
| 96 |
+
|
| 97 |
+
// The 1.f / sqrt(Dh). Computed on the host.
|
| 98 |
+
float inv_sqrt_dh = 0.0f;
|
| 99 |
+
|
| 100 |
+
// Used when we have some input context like gpt
|
| 101 |
+
const int* total_padding_tokens = nullptr;
|
| 102 |
+
|
| 103 |
+
const bool* masked_tokens = nullptr;
|
| 104 |
+
const int* prefix_prompt_lengths = nullptr;
|
| 105 |
+
int max_prefix_prompt_length = 0;
|
| 106 |
+
|
| 107 |
+
const T* relative_attention_bias = nullptr;
|
| 108 |
+
int relative_attention_bias_stride = 0;
|
| 109 |
+
// The slope per head of linear position bias to attention score (H).
|
| 110 |
+
const float* linear_bias_slopes = nullptr;
|
| 111 |
+
|
| 112 |
+
const T* ia3_key_weights = nullptr;
|
| 113 |
+
const T* ia3_value_weights = nullptr;
|
| 114 |
+
const int* ia3_tasks = nullptr;
|
| 115 |
+
|
| 116 |
+
const float* qkv_scale_out = nullptr;
|
| 117 |
+
const float* attention_out_scale = nullptr;
|
| 118 |
+
int int8_mode = 0;
|
| 119 |
+
};
|
| 120 |
+
|
| 121 |
+
template<typename T, bool CROSS_ATTENTION>
|
| 122 |
+
struct Multihead_attention_params: public Multihead_attention_params_base<T> {
|
| 123 |
+
// output cross attentions
|
| 124 |
+
float* cross_attention_out = nullptr;
|
| 125 |
+
int max_decoder_seq_len = 0;
|
| 126 |
+
bool is_return_cross_attentions = false;
|
| 127 |
+
|
| 128 |
+
// allows to exist attention eary
|
| 129 |
+
bool* finished = nullptr;
|
| 130 |
+
|
| 131 |
+
// required in case of cross attention
|
| 132 |
+
// will need it here till if constexpr in c++17
|
| 133 |
+
int* memory_length_per_sample = nullptr;
|
| 134 |
+
|
| 135 |
+
// required in case of masked attention with different length
|
| 136 |
+
const int* length_per_sample = nullptr;
|
| 137 |
+
};
|
| 138 |
+
|
| 139 |
+
template<typename T>
|
| 140 |
+
struct Multihead_attention_params<T, true>: public Multihead_attention_params_base<T> {
|
| 141 |
+
// output cross attentions
|
| 142 |
+
float* cross_attention_out = nullptr;
|
| 143 |
+
int max_decoder_seq_len = 0;
|
| 144 |
+
bool is_return_cross_attentions = false;
|
| 145 |
+
|
| 146 |
+
// allows to exist attention eary
|
| 147 |
+
bool* finished = nullptr;
|
| 148 |
+
|
| 149 |
+
// required in case of cross attention
|
| 150 |
+
int* memory_length_per_sample = nullptr;
|
| 151 |
+
|
| 152 |
+
// required in case of masked attention with different length
|
| 153 |
+
const int* length_per_sample = nullptr;
|
| 154 |
+
};
|
| 155 |
+
|
| 156 |
+
template<class T>
|
| 157 |
+
using Masked_multihead_attention_params = Multihead_attention_params<T, false>;
|
| 158 |
+
|
| 159 |
+
template<class T>
|
| 160 |
+
using Cross_multihead_attention_params = Multihead_attention_params<T, true>;
|
| 161 |
+
|
| 162 |
+
template<typename T>
|
| 163 |
+
struct outputCrossAttentionParam {
|
| 164 |
+
// max decoder output length
|
| 165 |
+
int max_decoder_seq_len = 0;
|
| 166 |
+
T* cross_attention_out = nullptr;
|
| 167 |
+
bool is_return_cross_attentions = false;
|
| 168 |
+
};
|
| 169 |
+
|
| 170 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 171 |
+
|
| 172 |
+
void masked_multihead_attention(const Masked_multihead_attention_params<float>& params, const cudaStream_t& stream);
|
| 173 |
+
void masked_multihead_attention(const Masked_multihead_attention_params<uint16_t>& params, const cudaStream_t& stream);
|
| 174 |
+
#ifdef ENABLE_BF16
|
| 175 |
+
void masked_multihead_attention(const Masked_multihead_attention_params<__nv_bfloat16>& params,
|
| 176 |
+
const cudaStream_t& stream);
|
| 177 |
+
#endif
|
| 178 |
+
void cross_multihead_attention(const Cross_multihead_attention_params<float>& params, const cudaStream_t& stream);
|
| 179 |
+
void cross_multihead_attention(const Cross_multihead_attention_params<uint16_t>& params, const cudaStream_t& stream);
|
| 180 |
+
#ifdef ENABLE_BF16
|
| 181 |
+
void cross_multihead_attention(const Cross_multihead_attention_params<__nv_bfloat16>& params,
|
| 182 |
+
const cudaStream_t& stream);
|
| 183 |
+
#endif
|
| 184 |
+
|
| 185 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
llm-awq/awq/kernels/csrc/attention/decoder_masked_multihead_attention_template.hpp
ADDED
|
@@ -0,0 +1,1608 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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/decoder_masked_multihead_attention_template.hpp
|
| 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 |
+
#pragma once
|
| 19 |
+
|
| 20 |
+
#include "decoder_masked_multihead_attention.h"
|
| 21 |
+
#include "decoder_masked_multihead_attention_utils.h"
|
| 22 |
+
#include "cuda_bf16_wrapper.h"
|
| 23 |
+
#include "cuda_bf16_fallbacks.cuh"
|
| 24 |
+
#include <assert.h>
|
| 25 |
+
#include <float.h>
|
| 26 |
+
#include <type_traits>
|
| 27 |
+
|
| 28 |
+
// #define MMHA_USE_HMMA_FOR_REDUCTION
|
| 29 |
+
|
| 30 |
+
// Below are knobs to extend FP32 accumulation for higher FP16 accuracy
|
| 31 |
+
|
| 32 |
+
// Does not seem to affect the accuracy that much
|
| 33 |
+
#define MMHA_USE_FP32_ACUM_FOR_FMA
|
| 34 |
+
|
| 35 |
+
// Seems to slightly improve the accuracy
|
| 36 |
+
#define MMHA_USE_FP32_ACUM_FOR_OUT
|
| 37 |
+
|
| 38 |
+
#if 0 && defined(MMHA_USE_FP32_ACUM_FOR_OUT)
|
| 39 |
+
// Does not seem to improve the accuracy
|
| 40 |
+
//#define MMHA_USE_FP32_ACUM_FOR_LOGITS
|
| 41 |
+
#endif
|
| 42 |
+
|
| 43 |
+
namespace mmha {
|
| 44 |
+
|
| 45 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 46 |
+
|
| 47 |
+
//
|
| 48 |
+
// We use the following terminology to describe the different dimensions.
|
| 49 |
+
//
|
| 50 |
+
// B: Batch size (number of sequences),
|
| 51 |
+
// L: Sequence length,
|
| 52 |
+
// D: Hidden dimension,
|
| 53 |
+
// H: Number of heads,
|
| 54 |
+
// Dh: Hidden dimension per head - Dh = D / H.
|
| 55 |
+
//
|
| 56 |
+
// The different kernels assign a threadblock for B x H pair. The grid has size (1, B, H). We use
|
| 57 |
+
// 64, 128 and 256 threads per block.
|
| 58 |
+
//
|
| 59 |
+
// Each threadblock loads Dh values from Q and its associated bias. The kernels run a loop to
|
| 60 |
+
// compute Q * K^T where K is loaded from a cache buffer -- except for the current timestep. The
|
| 61 |
+
// cache buffer helps with memory accesses and contains keys with bias.
|
| 62 |
+
//
|
| 63 |
+
// The layout of the cache buffer for the keys is [B, H, Dh/x, L, x] where x == 8 for FP16 and
|
| 64 |
+
// x == 4 for FP32 where the fastest moving dimension (contiguous data) is the rightmost one. The
|
| 65 |
+
// values for x are chosen to create chunks of 16 bytes.
|
| 66 |
+
//
|
| 67 |
+
// The different kernels use 1, 2 or 4 threads per key (THREADS_PER_KEY). The size of the LDGs
|
| 68 |
+
// depends on the number of threads per key. Each thread sums Dh / THREADS_PER_KEY elements. At
|
| 69 |
+
// the end of each iteration of the Q * K^T loop, we perform a reduction between lanes using an
|
| 70 |
+
// HMMA instruction (Tensor Core). Each Q * K^T valuey is stored in shared memory in FP32.
|
| 71 |
+
//
|
| 72 |
+
// After that loop, a parallel softmax is computed across the different Q * K^T values stored in
|
| 73 |
+
// shared memory.
|
| 74 |
+
//
|
| 75 |
+
// The kernel ends with a loop over the values in V. We use THREADS_PER_VALUE to control how many
|
| 76 |
+
// timesteps are computed by loop iteration. As with the keys, the values are read from a cache
|
| 77 |
+
// except for the current timestep. The layout of the cache buffer for the values is much simpler
|
| 78 |
+
// as it is [B, H, L, Dh].
|
| 79 |
+
//
|
| 80 |
+
|
| 81 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 82 |
+
|
| 83 |
+
template<typename T, int Dh>
|
| 84 |
+
struct Qk_vec_ {
|
| 85 |
+
};
|
| 86 |
+
|
| 87 |
+
template<>
|
| 88 |
+
struct Qk_vec_<float, 32> {
|
| 89 |
+
using Type = float;
|
| 90 |
+
};
|
| 91 |
+
template<>
|
| 92 |
+
struct Qk_vec_<float, 64> {
|
| 93 |
+
using Type = float2;
|
| 94 |
+
};
|
| 95 |
+
template<>
|
| 96 |
+
struct Qk_vec_<float, 128> {
|
| 97 |
+
using Type = float4;
|
| 98 |
+
};
|
| 99 |
+
template<>
|
| 100 |
+
struct Qk_vec_<float, 256> {
|
| 101 |
+
using Type = float4;
|
| 102 |
+
};
|
| 103 |
+
template<>
|
| 104 |
+
struct Qk_vec_<uint16_t, 32> {
|
| 105 |
+
using Type = uint32_t;
|
| 106 |
+
};
|
| 107 |
+
template<>
|
| 108 |
+
struct Qk_vec_<uint16_t, 64> {
|
| 109 |
+
using Type = uint32_t;
|
| 110 |
+
};
|
| 111 |
+
template<>
|
| 112 |
+
struct Qk_vec_<uint16_t, 128> {
|
| 113 |
+
using Type = uint2;
|
| 114 |
+
};
|
| 115 |
+
template<>
|
| 116 |
+
struct Qk_vec_<uint16_t, 256> {
|
| 117 |
+
using Type = uint4;
|
| 118 |
+
};
|
| 119 |
+
#ifdef ENABLE_BF16
|
| 120 |
+
template<>
|
| 121 |
+
struct Qk_vec_<__nv_bfloat16, 32> {
|
| 122 |
+
using Type = __nv_bfloat162;
|
| 123 |
+
};
|
| 124 |
+
template<>
|
| 125 |
+
struct Qk_vec_<__nv_bfloat16, 64> {
|
| 126 |
+
using Type = __nv_bfloat162;
|
| 127 |
+
};
|
| 128 |
+
template<>
|
| 129 |
+
struct Qk_vec_<__nv_bfloat16, 128> {
|
| 130 |
+
using Type = bf16_4_t;
|
| 131 |
+
};
|
| 132 |
+
template<>
|
| 133 |
+
struct Qk_vec_<__nv_bfloat16, 256> {
|
| 134 |
+
using Type = bf16_8_t;
|
| 135 |
+
};
|
| 136 |
+
#endif // ENABLE_BF16
|
| 137 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 138 |
+
|
| 139 |
+
template<typename T, int THREADS_PER_KEY>
|
| 140 |
+
struct K_vec_ {
|
| 141 |
+
};
|
| 142 |
+
|
| 143 |
+
template<>
|
| 144 |
+
struct K_vec_<float, 4> {
|
| 145 |
+
using Type = float;
|
| 146 |
+
};
|
| 147 |
+
template<>
|
| 148 |
+
struct K_vec_<float, 2> {
|
| 149 |
+
using Type = float2;
|
| 150 |
+
};
|
| 151 |
+
template<>
|
| 152 |
+
struct K_vec_<float, 1> {
|
| 153 |
+
using Type = float4;
|
| 154 |
+
};
|
| 155 |
+
template<>
|
| 156 |
+
struct K_vec_<uint16_t, 4> {
|
| 157 |
+
using Type = uint32_t;
|
| 158 |
+
};
|
| 159 |
+
template<>
|
| 160 |
+
struct K_vec_<uint16_t, 2> {
|
| 161 |
+
using Type = uint2;
|
| 162 |
+
};
|
| 163 |
+
template<>
|
| 164 |
+
struct K_vec_<uint16_t, 1> {
|
| 165 |
+
using Type = uint4;
|
| 166 |
+
};
|
| 167 |
+
#ifdef ENABLE_BF16
|
| 168 |
+
template<>
|
| 169 |
+
struct K_vec_<__nv_bfloat16, 4> {
|
| 170 |
+
using Type = __nv_bfloat162;
|
| 171 |
+
};
|
| 172 |
+
template<>
|
| 173 |
+
struct K_vec_<__nv_bfloat16, 2> {
|
| 174 |
+
using Type = bf16_4_t;
|
| 175 |
+
};
|
| 176 |
+
template<>
|
| 177 |
+
struct K_vec_<__nv_bfloat16, 1> {
|
| 178 |
+
using Type = bf16_8_t;
|
| 179 |
+
};
|
| 180 |
+
#endif // ENABLE_BF16
|
| 181 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 182 |
+
|
| 183 |
+
template<typename T, int V_VEC_SIZE>
|
| 184 |
+
struct V_vec_ {
|
| 185 |
+
};
|
| 186 |
+
|
| 187 |
+
template<>
|
| 188 |
+
struct V_vec_<float, 1> {
|
| 189 |
+
using Type = float;
|
| 190 |
+
};
|
| 191 |
+
template<>
|
| 192 |
+
struct V_vec_<float, 2> {
|
| 193 |
+
using Type = float2;
|
| 194 |
+
};
|
| 195 |
+
template<>
|
| 196 |
+
struct V_vec_<float, 4> {
|
| 197 |
+
using Type = float4;
|
| 198 |
+
};
|
| 199 |
+
template<>
|
| 200 |
+
struct V_vec_<uint16_t, 2> {
|
| 201 |
+
using Type = uint32_t;
|
| 202 |
+
};
|
| 203 |
+
template<>
|
| 204 |
+
struct V_vec_<uint16_t, 4> {
|
| 205 |
+
using Type = uint2;
|
| 206 |
+
};
|
| 207 |
+
template<>
|
| 208 |
+
struct V_vec_<uint16_t, 8> {
|
| 209 |
+
using Type = uint4;
|
| 210 |
+
};
|
| 211 |
+
#ifdef ENABLE_BF16
|
| 212 |
+
template<>
|
| 213 |
+
struct V_vec_<__nv_bfloat16, 2> {
|
| 214 |
+
using Type = __nv_bfloat162;
|
| 215 |
+
};
|
| 216 |
+
template<>
|
| 217 |
+
struct V_vec_<__nv_bfloat16, 4> {
|
| 218 |
+
using Type = bf16_4_t;
|
| 219 |
+
};
|
| 220 |
+
template<>
|
| 221 |
+
struct V_vec_<__nv_bfloat16, 8> {
|
| 222 |
+
using Type = bf16_8_t;
|
| 223 |
+
};
|
| 224 |
+
#endif // ENABLE_BF16
|
| 225 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 226 |
+
|
| 227 |
+
#ifdef MMHA_USE_FP32_ACUM_FOR_FMA
|
| 228 |
+
template<typename T>
|
| 229 |
+
struct Qk_vec_acum_fp32_ {
|
| 230 |
+
};
|
| 231 |
+
|
| 232 |
+
template<>
|
| 233 |
+
struct Qk_vec_acum_fp32_<float> {
|
| 234 |
+
using Type = float;
|
| 235 |
+
};
|
| 236 |
+
template<>
|
| 237 |
+
struct Qk_vec_acum_fp32_<float2> {
|
| 238 |
+
using Type = float2;
|
| 239 |
+
};
|
| 240 |
+
template<>
|
| 241 |
+
struct Qk_vec_acum_fp32_<float4> {
|
| 242 |
+
using Type = float4;
|
| 243 |
+
};
|
| 244 |
+
// template<> struct Qk_vec_acum_fp32_<uint16_t> { using Type = float; };
|
| 245 |
+
template<>
|
| 246 |
+
struct Qk_vec_acum_fp32_<uint32_t> {
|
| 247 |
+
using Type = float2;
|
| 248 |
+
};
|
| 249 |
+
template<>
|
| 250 |
+
struct Qk_vec_acum_fp32_<uint2> {
|
| 251 |
+
using Type = Float4_;
|
| 252 |
+
};
|
| 253 |
+
template<>
|
| 254 |
+
struct Qk_vec_acum_fp32_<uint4> {
|
| 255 |
+
using Type = Float8_;
|
| 256 |
+
};
|
| 257 |
+
template<>
|
| 258 |
+
struct Qk_vec_acum_fp32_<__nv_bfloat16> {
|
| 259 |
+
using Type = float;
|
| 260 |
+
};
|
| 261 |
+
template<>
|
| 262 |
+
struct Qk_vec_acum_fp32_<__nv_bfloat162> {
|
| 263 |
+
using Type = float2;
|
| 264 |
+
};
|
| 265 |
+
template<>
|
| 266 |
+
struct Qk_vec_acum_fp32_<bf16_4_t> {
|
| 267 |
+
using Type = Float4_;
|
| 268 |
+
};
|
| 269 |
+
template<>
|
| 270 |
+
struct Qk_vec_acum_fp32_<bf16_8_t> {
|
| 271 |
+
using Type = Float8_;
|
| 272 |
+
};
|
| 273 |
+
|
| 274 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 275 |
+
|
| 276 |
+
template<typename T>
|
| 277 |
+
struct K_vec_acum_fp32_ {
|
| 278 |
+
};
|
| 279 |
+
|
| 280 |
+
template<>
|
| 281 |
+
struct K_vec_acum_fp32_<float> {
|
| 282 |
+
using Type = float;
|
| 283 |
+
};
|
| 284 |
+
template<>
|
| 285 |
+
struct K_vec_acum_fp32_<float2> {
|
| 286 |
+
using Type = float2;
|
| 287 |
+
};
|
| 288 |
+
template<>
|
| 289 |
+
struct K_vec_acum_fp32_<float4> {
|
| 290 |
+
using Type = float4;
|
| 291 |
+
};
|
| 292 |
+
template<>
|
| 293 |
+
struct K_vec_acum_fp32_<uint32_t> {
|
| 294 |
+
using Type = float2;
|
| 295 |
+
};
|
| 296 |
+
template<>
|
| 297 |
+
struct K_vec_acum_fp32_<uint2> {
|
| 298 |
+
using Type = Float4_;
|
| 299 |
+
};
|
| 300 |
+
template<>
|
| 301 |
+
struct K_vec_acum_fp32_<uint4> {
|
| 302 |
+
using Type = Float8_;
|
| 303 |
+
};
|
| 304 |
+
template<>
|
| 305 |
+
struct K_vec_acum_fp32_<__nv_bfloat16> {
|
| 306 |
+
using Type = float;
|
| 307 |
+
};
|
| 308 |
+
template<>
|
| 309 |
+
struct K_vec_acum_fp32_<__nv_bfloat162> {
|
| 310 |
+
using Type = float2;
|
| 311 |
+
};
|
| 312 |
+
template<>
|
| 313 |
+
struct K_vec_acum_fp32_<bf16_4_t> {
|
| 314 |
+
using Type = Float4_;
|
| 315 |
+
};
|
| 316 |
+
template<>
|
| 317 |
+
struct K_vec_acum_fp32_<bf16_8_t> {
|
| 318 |
+
using Type = Float8_;
|
| 319 |
+
};
|
| 320 |
+
#endif
|
| 321 |
+
|
| 322 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 323 |
+
|
| 324 |
+
#ifdef MMHA_USE_FP32_ACUM_FOR_OUT
|
| 325 |
+
template<typename T>
|
| 326 |
+
struct V_vec_acum_fp32_ {
|
| 327 |
+
};
|
| 328 |
+
|
| 329 |
+
template<>
|
| 330 |
+
struct V_vec_acum_fp32_<float> {
|
| 331 |
+
using Type = float;
|
| 332 |
+
};
|
| 333 |
+
template<>
|
| 334 |
+
struct V_vec_acum_fp32_<float2> {
|
| 335 |
+
using Type = float2;
|
| 336 |
+
};
|
| 337 |
+
template<>
|
| 338 |
+
struct V_vec_acum_fp32_<float4> {
|
| 339 |
+
using Type = float4;
|
| 340 |
+
};
|
| 341 |
+
template<>
|
| 342 |
+
struct V_vec_acum_fp32_<uint32_t> {
|
| 343 |
+
using Type = float2;
|
| 344 |
+
};
|
| 345 |
+
template<>
|
| 346 |
+
struct V_vec_acum_fp32_<uint2> {
|
| 347 |
+
using Type = Float4_;
|
| 348 |
+
};
|
| 349 |
+
template<>
|
| 350 |
+
struct V_vec_acum_fp32_<uint4> {
|
| 351 |
+
using Type = Float8_;
|
| 352 |
+
};
|
| 353 |
+
#ifdef ENABLE_BF16
|
| 354 |
+
template<>
|
| 355 |
+
struct V_vec_acum_fp32_<__nv_bfloat162> {
|
| 356 |
+
using Type = float2;
|
| 357 |
+
};
|
| 358 |
+
template<>
|
| 359 |
+
struct V_vec_acum_fp32_<bf16_4_t> {
|
| 360 |
+
using Type = Float4_;
|
| 361 |
+
};
|
| 362 |
+
template<>
|
| 363 |
+
struct V_vec_acum_fp32_<bf16_8_t> {
|
| 364 |
+
using Type = Float8_;
|
| 365 |
+
};
|
| 366 |
+
#endif // ENABLE_BF16
|
| 367 |
+
#endif
|
| 368 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 369 |
+
|
| 370 |
+
template<int THREADS_PER_KEY, typename K_vec, int N>
|
| 371 |
+
inline __device__ float qk_dot_(const K_vec (&q)[N], const K_vec (&k)[N])
|
| 372 |
+
{
|
| 373 |
+
#ifdef MMHA_USE_FP32_ACUM_FOR_FMA
|
| 374 |
+
using K_vec_acum = typename K_vec_acum_fp32_<K_vec>::Type;
|
| 375 |
+
#else
|
| 376 |
+
using K_vec_acum = K_vec;
|
| 377 |
+
#endif
|
| 378 |
+
// Compute the parallel products for Q*K^T (treat vector lanes separately).
|
| 379 |
+
K_vec_acum qk_vec = mul<K_vec_acum, K_vec, K_vec>(q[0], k[0]);
|
| 380 |
+
#pragma unroll
|
| 381 |
+
for (int ii = 1; ii < N; ++ii) {
|
| 382 |
+
qk_vec = fma(q[ii], k[ii], qk_vec);
|
| 383 |
+
}
|
| 384 |
+
|
| 385 |
+
// Finalize the reduction across lanes.
|
| 386 |
+
float qk = sum(qk_vec);
|
| 387 |
+
#pragma unroll
|
| 388 |
+
for (int mask = THREADS_PER_KEY / 2; mask >= 1; mask /= 2) {
|
| 389 |
+
qk += __shfl_xor_sync(uint32_t(-1), qk, mask);
|
| 390 |
+
}
|
| 391 |
+
return qk;
|
| 392 |
+
}
|
| 393 |
+
|
| 394 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 395 |
+
|
| 396 |
+
template<typename T, int THREADS_PER_KEY>
|
| 397 |
+
struct Qk_dot {
|
| 398 |
+
template<typename K_vec, int N>
|
| 399 |
+
static inline __device__ float dot(const K_vec (&q)[N], const K_vec (&k)[N])
|
| 400 |
+
{
|
| 401 |
+
return qk_dot_<THREADS_PER_KEY>(q, k);
|
| 402 |
+
}
|
| 403 |
+
};
|
| 404 |
+
|
| 405 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 406 |
+
|
| 407 |
+
inline __device__ float4 hmma_fp32(const uint2& a, uint32_t b)
|
| 408 |
+
{
|
| 409 |
+
float4 c;
|
| 410 |
+
float zero = 0.f;
|
| 411 |
+
asm volatile("mma.sync.aligned.m16n8k8.row.col.f32.f16.f16.f32 \n"
|
| 412 |
+
" {%0, %1, %2, %3}, \n"
|
| 413 |
+
" {%4, %5}, \n"
|
| 414 |
+
" {%6}, \n"
|
| 415 |
+
" {%7, %7, %7, %7}; \n"
|
| 416 |
+
|
| 417 |
+
: "=f"(c.x), "=f"(c.y), "=f"(c.z), "=f"(c.w)
|
| 418 |
+
: "r"(a.x) "r"(a.y), "r"(b), "f"(zero));
|
| 419 |
+
return c;
|
| 420 |
+
}
|
| 421 |
+
|
| 422 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 423 |
+
|
| 424 |
+
template<int N>
|
| 425 |
+
inline __device__ float qk_hmma_dot_(const uint32_t (&q)[N], const uint32_t (&k)[N])
|
| 426 |
+
{
|
| 427 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 750
|
| 428 |
+
#ifdef MMHA_USE_FP32_ACUM_FOR_FMA
|
| 429 |
+
using K_vec_acum = typename K_vec_acum_fp32_<uint32_t>::Type;
|
| 430 |
+
#else
|
| 431 |
+
using K_vec_acum = uint32_t;
|
| 432 |
+
#endif
|
| 433 |
+
K_vec_acum qk_vec = mul<K_vec_acum, uint32_t, uint32_t>(q[0], k[0]);
|
| 434 |
+
#pragma unroll
|
| 435 |
+
for (int ii = 1; ii < N; ++ii) {
|
| 436 |
+
qk_vec = fma(q[ii], k[ii], qk_vec);
|
| 437 |
+
}
|
| 438 |
+
#ifdef MMHA_USE_FP32_ACUM_FOR_FMA
|
| 439 |
+
uint32_t qk_vec_ = float2_to_half2(qk_vec);
|
| 440 |
+
return hmma_fp32(make_uint2(qk_vec_, 0u), 0x3c003c00u).x;
|
| 441 |
+
#else
|
| 442 |
+
return hmma_fp32(make_uint2(qk_vec, 0u), 0x3c003c00u).x;
|
| 443 |
+
#endif
|
| 444 |
+
#else
|
| 445 |
+
return 0.f;
|
| 446 |
+
#endif
|
| 447 |
+
}
|
| 448 |
+
|
| 449 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 450 |
+
|
| 451 |
+
template<>
|
| 452 |
+
struct Qk_dot<uint16_t, 4> {
|
| 453 |
+
template<int N>
|
| 454 |
+
static inline __device__ float dot(const uint32_t (&q)[N], const uint32_t (&k)[N])
|
| 455 |
+
{
|
| 456 |
+
#if __CUDA_ARCH__ >= 750 && defined(MMHA_USE_HMMA_FOR_REDUCTION)
|
| 457 |
+
return qk_hmma_dot_(q, k);
|
| 458 |
+
#else
|
| 459 |
+
return qk_dot_<4>(q, k);
|
| 460 |
+
#endif // defined MMHA_USE_HMMA_FOR_REDUCTION
|
| 461 |
+
}
|
| 462 |
+
};
|
| 463 |
+
|
| 464 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 465 |
+
|
| 466 |
+
template<int WARPS_PER_BLOCK, int WARP_SIZE = 32>
|
| 467 |
+
inline __device__ float block_sum(float* red_smem, float sum)
|
| 468 |
+
{
|
| 469 |
+
|
| 470 |
+
// Decompose the thread index into warp / lane.
|
| 471 |
+
int warp = threadIdx.x / WARP_SIZE;
|
| 472 |
+
int lane = threadIdx.x % WARP_SIZE;
|
| 473 |
+
|
| 474 |
+
// Compute the sum per warp.
|
| 475 |
+
#pragma unroll
|
| 476 |
+
for (int mask = WARP_SIZE / 2; mask >= 1; mask /= 2) {
|
| 477 |
+
sum += __shfl_xor_sync(uint32_t(-1), sum, mask);
|
| 478 |
+
}
|
| 479 |
+
|
| 480 |
+
// Warp leaders store the data to shared memory.
|
| 481 |
+
if (lane == 0) {
|
| 482 |
+
red_smem[warp] = sum;
|
| 483 |
+
}
|
| 484 |
+
|
| 485 |
+
// Make sure the data is in shared memory.
|
| 486 |
+
__syncthreads();
|
| 487 |
+
|
| 488 |
+
// The warps compute the final sums.
|
| 489 |
+
if (lane < WARPS_PER_BLOCK) {
|
| 490 |
+
sum = red_smem[lane];
|
| 491 |
+
}
|
| 492 |
+
|
| 493 |
+
// Parallel reduction inside the warp.
|
| 494 |
+
#pragma unroll
|
| 495 |
+
for (int mask = WARPS_PER_BLOCK / 2; mask >= 1; mask /= 2) {
|
| 496 |
+
sum += __shfl_xor_sync(uint32_t(-1), sum, mask);
|
| 497 |
+
}
|
| 498 |
+
|
| 499 |
+
// Broadcast to other threads.
|
| 500 |
+
return __shfl_sync(uint32_t(-1), sum, 0);
|
| 501 |
+
}
|
| 502 |
+
|
| 503 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 504 |
+
|
| 505 |
+
inline __device__ void convert_from_float(float& dst, float src)
|
| 506 |
+
{
|
| 507 |
+
dst = src;
|
| 508 |
+
}
|
| 509 |
+
|
| 510 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 511 |
+
|
| 512 |
+
inline __device__ void convert_from_float(uint16_t& dst, float src)
|
| 513 |
+
{
|
| 514 |
+
dst = float_to_half(src);
|
| 515 |
+
}
|
| 516 |
+
|
| 517 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 518 |
+
|
| 519 |
+
inline __device__ void convert_from_float(uint32_t& dst, float2 src)
|
| 520 |
+
{
|
| 521 |
+
dst = float2_to_half2(src);
|
| 522 |
+
}
|
| 523 |
+
|
| 524 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 525 |
+
#ifdef ENABLE_BF16
|
| 526 |
+
inline __device__ void convert_from_float(__nv_bfloat16& dst, float src)
|
| 527 |
+
{
|
| 528 |
+
dst = __float2bfloat16(src);
|
| 529 |
+
}
|
| 530 |
+
|
| 531 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 532 |
+
|
| 533 |
+
inline __device__ void convert_from_float(__nv_bfloat162& dst, float2 src)
|
| 534 |
+
{
|
| 535 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 800
|
| 536 |
+
dst = __float22bfloat162_rn(src);
|
| 537 |
+
#else
|
| 538 |
+
dst = __floats2bfloat162_rn(src.x, src.y);
|
| 539 |
+
#endif
|
| 540 |
+
}
|
| 541 |
+
#endif // ENABLE_BF16
|
| 542 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 543 |
+
|
| 544 |
+
inline __device__ void convert_from_float(uint2& dst, Float4_ src)
|
| 545 |
+
{
|
| 546 |
+
dst.x = float2_to_half2(src.x);
|
| 547 |
+
dst.y = float2_to_half2(src.y);
|
| 548 |
+
}
|
| 549 |
+
|
| 550 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 551 |
+
|
| 552 |
+
inline __device__ void convert_from_float(uint2& dst, float4 src)
|
| 553 |
+
{
|
| 554 |
+
convert_from_float(dst, Float4_{make_float2(src.x, src.y), make_float2(src.z, src.w)});
|
| 555 |
+
}
|
| 556 |
+
|
| 557 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 558 |
+
|
| 559 |
+
inline __device__ void convert_from_float(uint4& dst, Float8_ src)
|
| 560 |
+
{
|
| 561 |
+
dst.x = float2_to_half2(src.x);
|
| 562 |
+
dst.y = float2_to_half2(src.y);
|
| 563 |
+
dst.z = float2_to_half2(src.z);
|
| 564 |
+
dst.w = float2_to_half2(src.w);
|
| 565 |
+
}
|
| 566 |
+
|
| 567 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 568 |
+
|
| 569 |
+
#ifdef ENABLE_BF16
|
| 570 |
+
inline __device__ void convert_from_float(bf16_4_t& dst, Float4_ src)
|
| 571 |
+
{
|
| 572 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 800
|
| 573 |
+
dst.x = __float22bfloat162_rn(src.x);
|
| 574 |
+
dst.y = __float22bfloat162_rn(src.y);
|
| 575 |
+
#else
|
| 576 |
+
dst.x = __floats2bfloat162_rn(src.x.x, src.x.y);
|
| 577 |
+
dst.y = __floats2bfloat162_rn(src.y.x, src.y.y);
|
| 578 |
+
#endif
|
| 579 |
+
}
|
| 580 |
+
|
| 581 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 582 |
+
|
| 583 |
+
inline __device__ void convert_from_float(bf16_4_t& dst, float4 src)
|
| 584 |
+
{
|
| 585 |
+
convert_from_float(dst, Float4_{make_float2(src.x, src.y), make_float2(src.z, src.w)});
|
| 586 |
+
}
|
| 587 |
+
|
| 588 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 589 |
+
|
| 590 |
+
inline __device__ void convert_from_float(bf16_8_t& dst, Float8_ src)
|
| 591 |
+
{
|
| 592 |
+
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 800
|
| 593 |
+
dst.x = __float22bfloat162_rn(src.x);
|
| 594 |
+
dst.y = __float22bfloat162_rn(src.y);
|
| 595 |
+
dst.z = __float22bfloat162_rn(src.z);
|
| 596 |
+
dst.w = __float22bfloat162_rn(src.w);
|
| 597 |
+
#else
|
| 598 |
+
dst.x = __floats2bfloat162_rn(src.x.x, src.x.y);
|
| 599 |
+
dst.y = __floats2bfloat162_rn(src.y.x, src.y.y);
|
| 600 |
+
dst.z = __floats2bfloat162_rn(src.z.x, src.z.y);
|
| 601 |
+
dst.w = __floats2bfloat162_rn(src.w.x, src.w.y);
|
| 602 |
+
#endif
|
| 603 |
+
}
|
| 604 |
+
#endif // ENABLE_BF16
|
| 605 |
+
|
| 606 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 607 |
+
|
| 608 |
+
inline __device__ void convert_from_float(float2& dst, float2 src)
|
| 609 |
+
{
|
| 610 |
+
dst = src;
|
| 611 |
+
}
|
| 612 |
+
|
| 613 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 614 |
+
|
| 615 |
+
inline __device__ void convert_from_float(float4& dst, float4 src)
|
| 616 |
+
{
|
| 617 |
+
dst = src;
|
| 618 |
+
}
|
| 619 |
+
|
| 620 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 621 |
+
|
| 622 |
+
inline __device__ float convert_to_float(float4 u)
|
| 623 |
+
{
|
| 624 |
+
return u.x;
|
| 625 |
+
}
|
| 626 |
+
|
| 627 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 628 |
+
|
| 629 |
+
inline __device__ float convert_to_float(uint4 u)
|
| 630 |
+
{
|
| 631 |
+
float2 tmp = half2_to_float2(u.x);
|
| 632 |
+
return tmp.x;
|
| 633 |
+
}
|
| 634 |
+
|
| 635 |
+
#if defined(MMHA_USE_FP32_ACUM_FOR_LOGITS)
|
| 636 |
+
|
| 637 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 638 |
+
|
| 639 |
+
inline __device__ float cast_to_float(float u)
|
| 640 |
+
{
|
| 641 |
+
return u;
|
| 642 |
+
}
|
| 643 |
+
|
| 644 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 645 |
+
|
| 646 |
+
inline __device__ float2 cast_to_float(float2 u)
|
| 647 |
+
{
|
| 648 |
+
return u;
|
| 649 |
+
}
|
| 650 |
+
|
| 651 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 652 |
+
|
| 653 |
+
inline __device__ float4 cast_to_float(float4 u)
|
| 654 |
+
{
|
| 655 |
+
return u;
|
| 656 |
+
}
|
| 657 |
+
|
| 658 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 659 |
+
|
| 660 |
+
inline __device__ Float4_ cast_to_float(Float4_ u)
|
| 661 |
+
{
|
| 662 |
+
return u;
|
| 663 |
+
}
|
| 664 |
+
|
| 665 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 666 |
+
|
| 667 |
+
inline __device__ Float8_ cast_to_float(Float8_ u)
|
| 668 |
+
{
|
| 669 |
+
return u;
|
| 670 |
+
}
|
| 671 |
+
|
| 672 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 673 |
+
|
| 674 |
+
inline __device__ float2 cast_to_float(uint32_t u)
|
| 675 |
+
{
|
| 676 |
+
return half2_to_float2(u);
|
| 677 |
+
}
|
| 678 |
+
|
| 679 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 680 |
+
|
| 681 |
+
inline __device__ Float4_ cast_to_float(uint2 u)
|
| 682 |
+
{
|
| 683 |
+
Float4_ tmp;
|
| 684 |
+
tmp.x = half2_to_float2(u.x);
|
| 685 |
+
tmp.y = half2_to_float2(u.y);
|
| 686 |
+
return tmp;
|
| 687 |
+
}
|
| 688 |
+
|
| 689 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 690 |
+
|
| 691 |
+
inline __device__ Float8_ cast_to_float(uint4 u)
|
| 692 |
+
{
|
| 693 |
+
Float8_ tmp;
|
| 694 |
+
tmp.x = half2_to_float2(u.x);
|
| 695 |
+
tmp.y = half2_to_float2(u.y);
|
| 696 |
+
tmp.z = half2_to_float2(u.z);
|
| 697 |
+
tmp.w = half2_to_float2(u.w);
|
| 698 |
+
return tmp;
|
| 699 |
+
}
|
| 700 |
+
|
| 701 |
+
#endif
|
| 702 |
+
|
| 703 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 704 |
+
|
| 705 |
+
inline __device__ float float_from_int8(int8_t u)
|
| 706 |
+
{
|
| 707 |
+
return u;
|
| 708 |
+
}
|
| 709 |
+
|
| 710 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 711 |
+
|
| 712 |
+
inline __device__ float2 float_from_int8(int16_t u)
|
| 713 |
+
{
|
| 714 |
+
union {
|
| 715 |
+
int16_t int16;
|
| 716 |
+
int8_t int8[2];
|
| 717 |
+
};
|
| 718 |
+
int16 = u;
|
| 719 |
+
return make_float2(int8[0], int8[1]);
|
| 720 |
+
}
|
| 721 |
+
|
| 722 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 723 |
+
|
| 724 |
+
inline __device__ float4 float_from_int8(int32_t u)
|
| 725 |
+
{
|
| 726 |
+
union {
|
| 727 |
+
int32_t int32;
|
| 728 |
+
int8_t int8[4];
|
| 729 |
+
};
|
| 730 |
+
int32 = u;
|
| 731 |
+
return make_float4(int8[0], int8[1], int8[2], int8[3]);
|
| 732 |
+
}
|
| 733 |
+
|
| 734 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 735 |
+
|
| 736 |
+
// clang-format off
|
| 737 |
+
inline __device__ Float8_ float_from_int8(int64_t u)
|
| 738 |
+
{
|
| 739 |
+
union {
|
| 740 |
+
int64_t int64;
|
| 741 |
+
int16_t int16[4];
|
| 742 |
+
};
|
| 743 |
+
int64 = u;
|
| 744 |
+
return Float8_ {float_from_int8(int16[0]),
|
| 745 |
+
float_from_int8(int16[1]),
|
| 746 |
+
float_from_int8(int16[2]),
|
| 747 |
+
float_from_int8(int16[3])};
|
| 748 |
+
}
|
| 749 |
+
// clang-format on
|
| 750 |
+
|
| 751 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 752 |
+
|
| 753 |
+
inline __device__ int8_t cast_to_int8(float val)
|
| 754 |
+
{
|
| 755 |
+
union {
|
| 756 |
+
int8_t int8[2];
|
| 757 |
+
int16_t int16;
|
| 758 |
+
};
|
| 759 |
+
asm volatile("cvt.rni.sat.s8.f32 %0, %1;" : "=h"(int16) : "f"(val));
|
| 760 |
+
return int8[0];
|
| 761 |
+
}
|
| 762 |
+
|
| 763 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 764 |
+
|
| 765 |
+
inline __device__ int32_t cast_to_int8(float4 val)
|
| 766 |
+
{
|
| 767 |
+
union {
|
| 768 |
+
int8_t int8[4];
|
| 769 |
+
int32_t int32;
|
| 770 |
+
};
|
| 771 |
+
int8[0] = cast_to_int8(val.x);
|
| 772 |
+
int8[1] = cast_to_int8(val.y);
|
| 773 |
+
int8[2] = cast_to_int8(val.z);
|
| 774 |
+
int8[3] = cast_to_int8(val.w);
|
| 775 |
+
return int32;
|
| 776 |
+
}
|
| 777 |
+
|
| 778 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 779 |
+
|
| 780 |
+
inline __device__ int64_t cast_to_int8(Float8_ val)
|
| 781 |
+
{
|
| 782 |
+
union {
|
| 783 |
+
int8_t int8[8];
|
| 784 |
+
int64_t int64;
|
| 785 |
+
};
|
| 786 |
+
int8[0] = cast_to_int8(val.x.x);
|
| 787 |
+
int8[1] = cast_to_int8(val.x.y);
|
| 788 |
+
int8[2] = cast_to_int8(val.y.x);
|
| 789 |
+
int8[3] = cast_to_int8(val.y.y);
|
| 790 |
+
int8[4] = cast_to_int8(val.z.x);
|
| 791 |
+
int8[5] = cast_to_int8(val.z.y);
|
| 792 |
+
int8[6] = cast_to_int8(val.w.x);
|
| 793 |
+
int8[7] = cast_to_int8(val.w.y);
|
| 794 |
+
return int64;
|
| 795 |
+
}
|
| 796 |
+
|
| 797 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 798 |
+
|
| 799 |
+
template<typename T>
|
| 800 |
+
inline __device__ __host__ T div_up(T m, T n)
|
| 801 |
+
{
|
| 802 |
+
return (m + n - 1) / n;
|
| 803 |
+
}
|
| 804 |
+
|
| 805 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 806 |
+
|
| 807 |
+
template<typename T, bool DO_CROSS_ATTENTION>
|
| 808 |
+
inline size_t smem_size_in_bytes(const Multihead_attention_params<T, DO_CROSS_ATTENTION>& params,
|
| 809 |
+
int threads_per_value,
|
| 810 |
+
int threads_per_block)
|
| 811 |
+
{
|
| 812 |
+
// The amount of shared memory needed to store the Q*K^T values in float.
|
| 813 |
+
const int max_timesteps = min(params.timestep, params.memory_max_len);
|
| 814 |
+
size_t qk_sz = (DO_CROSS_ATTENTION) ? div_up(params.memory_max_len + 1, 4) * 16 : div_up(max_timesteps + 1, 4) * 16;
|
| 815 |
+
|
| 816 |
+
// The extra memory needed if we are not using floats for the final logits.
|
| 817 |
+
size_t logits_sz = 0;
|
| 818 |
+
#ifndef MMHA_USE_FP32_ACUM_FOR_LOGITS
|
| 819 |
+
if (sizeof(T) != 4) {
|
| 820 |
+
// TDOD
|
| 821 |
+
logits_sz = (DO_CROSS_ATTENTION) ? div_up(params.memory_max_len + 1, 4) * 4 * sizeof(T) :
|
| 822 |
+
div_up(max_timesteps + 1, 4) * 4 * sizeof(T);
|
| 823 |
+
}
|
| 824 |
+
#endif
|
| 825 |
+
|
| 826 |
+
// The total size needed during softmax.
|
| 827 |
+
size_t softmax_sz = qk_sz + logits_sz;
|
| 828 |
+
|
| 829 |
+
// The number of partial rows to reduce in the final reduction.
|
| 830 |
+
int rows_per_red = threads_per_block / threads_per_value;
|
| 831 |
+
// The amount of storage needed to finalize the outputs.
|
| 832 |
+
size_t red_sz = rows_per_red * params.hidden_size_per_head * sizeof(T) / 2;
|
| 833 |
+
|
| 834 |
+
size_t transpose_rotary_size = 0;
|
| 835 |
+
if (params.rotary_embedding_dim > 0 && params.neox_rotary_style) {
|
| 836 |
+
transpose_rotary_size = 2 * params.rotary_embedding_dim * sizeof(T);
|
| 837 |
+
}
|
| 838 |
+
|
| 839 |
+
// The max.
|
| 840 |
+
return max(max(softmax_sz, red_sz), transpose_rotary_size);
|
| 841 |
+
}
|
| 842 |
+
|
| 843 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 844 |
+
|
| 845 |
+
inline __device__ constexpr uint32_t shfl_mask(int threads)
|
| 846 |
+
{
|
| 847 |
+
return threads == 32 ? uint32_t(-1) : (1u << threads) - 1u;
|
| 848 |
+
}
|
| 849 |
+
|
| 850 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 851 |
+
|
| 852 |
+
template<
|
| 853 |
+
// The type of the inputs. Supported types: float and half.
|
| 854 |
+
typename T,
|
| 855 |
+
// The hidden dimension per head.
|
| 856 |
+
int Dh,
|
| 857 |
+
int Dh_MAX,
|
| 858 |
+
// The number of threads per key.
|
| 859 |
+
int THREADS_PER_KEY,
|
| 860 |
+
// The number of threads per value.
|
| 861 |
+
int THREADS_PER_VALUE,
|
| 862 |
+
// The number of threads in a threadblock.
|
| 863 |
+
int THREADS_PER_BLOCK,
|
| 864 |
+
bool DO_CROSS_ATTENTION>
|
| 865 |
+
__global__ void masked_multihead_attention_kernel(Multihead_attention_params<T, DO_CROSS_ATTENTION> params)
|
| 866 |
+
{
|
| 867 |
+
|
| 868 |
+
// Make sure the hidden dimension per head is a multiple of the number of threads per key.
|
| 869 |
+
static_assert(Dh_MAX % THREADS_PER_KEY == 0, "");
|
| 870 |
+
// Make sure the hidden dimension per head is a multiple of the number of threads per value.
|
| 871 |
+
static_assert(Dh_MAX % THREADS_PER_VALUE == 0, "");
|
| 872 |
+
|
| 873 |
+
// The size of a warp.
|
| 874 |
+
constexpr int WARP_SIZE = 32;
|
| 875 |
+
// The number of warps in a threadblock.
|
| 876 |
+
constexpr int WARPS_PER_BLOCK = THREADS_PER_BLOCK / WARP_SIZE;
|
| 877 |
+
|
| 878 |
+
// Use smem_size_in_bytes (above) to determine the amount of shared memory.
|
| 879 |
+
extern __shared__ char smem_[];
|
| 880 |
+
|
| 881 |
+
// The shared memory for the Q*K^T values and partial logits in softmax.
|
| 882 |
+
float* qk_smem = reinterpret_cast<float*>(smem_);
|
| 883 |
+
|
| 884 |
+
// The shared memory for the logits. For FP32, that's the same buffer as qk_smem.
|
| 885 |
+
char* logits_smem_ = smem_;
|
| 886 |
+
#ifndef MMHA_USE_FP32_ACUM_FOR_LOGITS
|
| 887 |
+
if (sizeof(T) != 4) {
|
| 888 |
+
// TODO - change to tlength
|
| 889 |
+
const int max_timesteps = min(params.timestep, params.memory_max_len);
|
| 890 |
+
logits_smem_ +=
|
| 891 |
+
(DO_CROSS_ATTENTION) ? div_up(params.memory_max_len + 1, 4) * 16 : div_up(max_timesteps + 1, 4) * 16;
|
| 892 |
+
}
|
| 893 |
+
T* logits_smem = reinterpret_cast<T*>(logits_smem_);
|
| 894 |
+
#else
|
| 895 |
+
float* logits_smem = reinterpret_cast<float*>(logits_smem_);
|
| 896 |
+
#endif
|
| 897 |
+
|
| 898 |
+
// The shared memory to do the final reduction for the output values. Reuse qk_smem.
|
| 899 |
+
T* out_smem = reinterpret_cast<T*>(smem_);
|
| 900 |
+
|
| 901 |
+
// The shared memory buffers for the block-wide reductions. One for max, one for sum.
|
| 902 |
+
__shared__ float red_smem[WARPS_PER_BLOCK * 2];
|
| 903 |
+
|
| 904 |
+
// A vector of Q or K elements for the current timestep.
|
| 905 |
+
using Qk_vec = typename Qk_vec_<T, Dh_MAX>::Type;
|
| 906 |
+
|
| 907 |
+
// Use alignment for safely casting the shared buffers as Qk_vec.
|
| 908 |
+
// Shared memory to store Q inputs.
|
| 909 |
+
__shared__ __align__(sizeof(Qk_vec)) T q_smem[Dh_MAX];
|
| 910 |
+
|
| 911 |
+
// This is one of the reasons we should have a separate kernel for cross attention
|
| 912 |
+
__shared__ __align__(sizeof(Qk_vec)) T bias_smem[DO_CROSS_ATTENTION ? Dh_MAX : 1];
|
| 913 |
+
|
| 914 |
+
// A vector of Q or K elements for the current timestep.
|
| 915 |
+
using Qk_vec = typename Qk_vec_<T, Dh_MAX>::Type;
|
| 916 |
+
// The number of elements per vector.
|
| 917 |
+
constexpr int QK_VEC_SIZE = sizeof(Qk_vec) / sizeof(T);
|
| 918 |
+
// Make sure the hidden size per head is a multiple of the vector size.
|
| 919 |
+
static_assert(Dh_MAX % QK_VEC_SIZE == 0, "");
|
| 920 |
+
// We will use block wide reduction if needed
|
| 921 |
+
// static_assert(Dh_MAX / QK_VEC_SIZE <= WARP_SIZE, "");
|
| 922 |
+
// The number of vectors per warp.
|
| 923 |
+
constexpr int QK_VECS_PER_WARP = Dh_MAX / QK_VEC_SIZE;
|
| 924 |
+
|
| 925 |
+
// The layout of the cache is [B, H, Dh/x, L, x] with x == 4/8 for FP32/FP16. Since each thread
|
| 926 |
+
// owns x elements, we have to decompose the linear index into chunks of x values and the posi-
|
| 927 |
+
// tion of the thread in that chunk.
|
| 928 |
+
|
| 929 |
+
// The number of elements in a chunk of 16B (that's the x in the above formula).
|
| 930 |
+
constexpr int QK_ELTS_IN_16B = 16 / sizeof(T);
|
| 931 |
+
// The number of K vectors in 16B.
|
| 932 |
+
constexpr int QK_VECS_IN_16B = 16 / sizeof(Qk_vec);
|
| 933 |
+
|
| 934 |
+
// The batch/beam idx
|
| 935 |
+
const int bi = blockIdx.y;
|
| 936 |
+
if (params.finished != nullptr && params.finished[bi] == true) {
|
| 937 |
+
return;
|
| 938 |
+
}
|
| 939 |
+
// The beam idx
|
| 940 |
+
const int beami = bi % params.beam_width;
|
| 941 |
+
// The "beam-aware" batch idx
|
| 942 |
+
const int bbi = bi / params.beam_width;
|
| 943 |
+
// The head.
|
| 944 |
+
const int num_kv_heads = params.num_kv_heads;
|
| 945 |
+
const int kv_rep = (params.num_heads / num_kv_heads);
|
| 946 |
+
const int hi = blockIdx.x;
|
| 947 |
+
const int hi_kv = hi / kv_rep;
|
| 948 |
+
|
| 949 |
+
// Combine the batch and the head indices.
|
| 950 |
+
const int bhi = bi * params.num_heads + hi;
|
| 951 |
+
const int bhi_kv = bi * (params.num_heads / kv_rep) + hi_kv;
|
| 952 |
+
// Combine the "beam-aware" batch idx and the head indices.
|
| 953 |
+
const int bbhi = bbi * params.beam_width * params.num_heads + hi;
|
| 954 |
+
const int bbhi_kv = bbi * params.beam_width * (params.num_heads / kv_rep) + hi_kv;
|
| 955 |
+
// The thread in the block.
|
| 956 |
+
const int tidx = threadIdx.x;
|
| 957 |
+
|
| 958 |
+
const bool handle_kv = !DO_CROSS_ATTENTION || (DO_CROSS_ATTENTION && params.timestep == 0);
|
| 959 |
+
// Every kv_rep threads have the same kv_cache values. So only the first one writes back.
|
| 960 |
+
const int write_kv_cache = handle_kv && (hi % kv_rep == 0);
|
| 961 |
+
|
| 962 |
+
// While doing the product Q*K^T for the different keys we track the max.
|
| 963 |
+
float qk_max = -FLT_MAX;
|
| 964 |
+
|
| 965 |
+
float qk = 0.0F;
|
| 966 |
+
|
| 967 |
+
// int qkv_base_offset = (params.stride == 0) ? bhi * Dh : bi * params.stride + hi * Dh;
|
| 968 |
+
const int q_base_offset = bi * params.stride + hi * Dh;
|
| 969 |
+
const int k_base_offset = bi * params.stride + hi_kv * Dh;
|
| 970 |
+
const int v_base_offset = k_base_offset;
|
| 971 |
+
|
| 972 |
+
const size_t bi_seq_len_offset = bi * params.memory_max_len;
|
| 973 |
+
|
| 974 |
+
// int tlength = (DO_CROSS_ATTENTION)? params.memory_length_per_sample[bi] - 1 : params.timestep;
|
| 975 |
+
int tlength = (DO_CROSS_ATTENTION) ? params.memory_length_per_sample[bi] - 1 :
|
| 976 |
+
(params.length_per_sample == nullptr) ?
|
| 977 |
+
params.timestep :
|
| 978 |
+
params.length_per_sample[bi] + params.max_prefix_prompt_length;
|
| 979 |
+
const int first_step = max(0, tlength + 1 - params.memory_max_len);
|
| 980 |
+
const int tlength_circ = tlength % params.memory_max_len;
|
| 981 |
+
|
| 982 |
+
// First QK_VECS_PER_WARP load Q and K + the bias values for the current timestep.
|
| 983 |
+
const bool is_masked = tidx >= QK_VECS_PER_WARP;
|
| 984 |
+
|
| 985 |
+
// The offset in the Q and K buffer also accounts for the batch.
|
| 986 |
+
// int qk_offset = qkv_base_offset + tidx * QK_VEC_SIZE;
|
| 987 |
+
int q_offset = q_base_offset + tidx * QK_VEC_SIZE;
|
| 988 |
+
int k_offset = k_base_offset + tidx * QK_VEC_SIZE;
|
| 989 |
+
int v_offset = k_offset;
|
| 990 |
+
|
| 991 |
+
// The offset in the bias buffer.
|
| 992 |
+
// int qk_bias_offset = hi * Dh + tidx * QK_VEC_SIZE;
|
| 993 |
+
int q_bias_offset = hi * Dh + tidx * QK_VEC_SIZE;
|
| 994 |
+
int k_bias_offset = hi_kv * Dh + tidx * QK_VEC_SIZE;
|
| 995 |
+
int v_bias_offset = k_bias_offset;
|
| 996 |
+
|
| 997 |
+
const bool do_ia3 = handle_kv && params.ia3_tasks != nullptr;
|
| 998 |
+
const int ia3_task_id = do_ia3 ? params.ia3_tasks[bbi] : 0;
|
| 999 |
+
|
| 1000 |
+
// Trigger the loads from the Q and K buffers.
|
| 1001 |
+
Qk_vec q;
|
| 1002 |
+
zero(q);
|
| 1003 |
+
if (!is_masked && (Dh == Dh_MAX || tidx * QK_VEC_SIZE < Dh)) {
|
| 1004 |
+
if (params.int8_mode == 2) {
|
| 1005 |
+
using Packed_Int8_t = typename packed_type<int8_t, num_elems<Qk_vec>::value>::type;
|
| 1006 |
+
using Packed_Float_t = typename packed_type<float, num_elems<Qk_vec>::value>::type;
|
| 1007 |
+
const auto q_scaling = params.qkv_scale_out[0];
|
| 1008 |
+
const auto q_quant =
|
| 1009 |
+
*reinterpret_cast<const Packed_Int8_t*>(&reinterpret_cast<const int8_t*>(params.q)[q_offset]);
|
| 1010 |
+
|
| 1011 |
+
convert_from_float(q, mul<Packed_Float_t, float>(q_scaling, float_from_int8(q_quant)));
|
| 1012 |
+
}
|
| 1013 |
+
else {
|
| 1014 |
+
q = *reinterpret_cast<const Qk_vec*>(¶ms.q[q_offset]);
|
| 1015 |
+
}
|
| 1016 |
+
}
|
| 1017 |
+
|
| 1018 |
+
Qk_vec k;
|
| 1019 |
+
zero(k);
|
| 1020 |
+
if (DO_CROSS_ATTENTION) {
|
| 1021 |
+
// The 16B chunk written by the thread.
|
| 1022 |
+
int co = tidx / QK_VECS_IN_16B;
|
| 1023 |
+
// The position of the thread in that 16B chunk.
|
| 1024 |
+
int ci = tidx % QK_VECS_IN_16B * QK_VEC_SIZE;
|
| 1025 |
+
|
| 1026 |
+
// Two chunks are separated by L * x elements. A thread write QK_VEC_SIZE elements.
|
| 1027 |
+
int offset = bhi_kv * params.memory_max_len * Dh + co * params.memory_max_len * QK_ELTS_IN_16B +
|
| 1028 |
+
// params.timestep*QK_ELTS_IN_16B +
|
| 1029 |
+
tlength * QK_ELTS_IN_16B + ci;
|
| 1030 |
+
k = !is_masked && (Dh == Dh_MAX || tidx * QK_VEC_SIZE < Dh) ?
|
| 1031 |
+
*reinterpret_cast<const Qk_vec*>(¶ms.k_cache[offset]) :
|
| 1032 |
+
k;
|
| 1033 |
+
}
|
| 1034 |
+
else {
|
| 1035 |
+
if (!is_masked && (Dh == Dh_MAX || tidx * QK_VEC_SIZE < Dh)) {
|
| 1036 |
+
if (params.int8_mode == 2) {
|
| 1037 |
+
using Packed_Int8_t = typename packed_type<int8_t, num_elems<Qk_vec>::value>::type;
|
| 1038 |
+
using Packed_Float_t = typename packed_type<float, num_elems<Qk_vec>::value>::type;
|
| 1039 |
+
const auto k_scaling = params.qkv_scale_out[1];
|
| 1040 |
+
const auto k_quant =
|
| 1041 |
+
*reinterpret_cast<const Packed_Int8_t*>(&reinterpret_cast<const int8_t*>(params.k)[k_offset]);
|
| 1042 |
+
|
| 1043 |
+
convert_from_float(k, mul<Packed_Float_t, float>(k_scaling, float_from_int8(k_quant)));
|
| 1044 |
+
}
|
| 1045 |
+
else {
|
| 1046 |
+
k = *reinterpret_cast<const Qk_vec*>(¶ms.k[k_offset]);
|
| 1047 |
+
}
|
| 1048 |
+
}
|
| 1049 |
+
}
|
| 1050 |
+
|
| 1051 |
+
// Trigger the loads from the Q and K bias buffers.
|
| 1052 |
+
Qk_vec q_bias;
|
| 1053 |
+
zero(q_bias);
|
| 1054 |
+
q_bias = (!is_masked && Dh == Dh_MAX || tidx * QK_VEC_SIZE < Dh) && params.q_bias != nullptr ?
|
| 1055 |
+
*reinterpret_cast<const Qk_vec*>(¶ms.q_bias[q_bias_offset]) :
|
| 1056 |
+
q_bias;
|
| 1057 |
+
|
| 1058 |
+
Qk_vec k_bias;
|
| 1059 |
+
zero(k_bias);
|
| 1060 |
+
if (handle_kv) {
|
| 1061 |
+
k_bias = !is_masked && (Dh == Dh_MAX || tidx * QK_VEC_SIZE < Dh) && params.k_bias != nullptr ?
|
| 1062 |
+
*reinterpret_cast<const Qk_vec*>(¶ms.k_bias[k_bias_offset]) :
|
| 1063 |
+
k_bias;
|
| 1064 |
+
}
|
| 1065 |
+
|
| 1066 |
+
// Computes the Q/K values with bias.
|
| 1067 |
+
q = add(q, q_bias);
|
| 1068 |
+
if (handle_kv) {
|
| 1069 |
+
k = add(k, k_bias);
|
| 1070 |
+
}
|
| 1071 |
+
if (do_ia3 && !is_masked) {
|
| 1072 |
+
k = mul<Qk_vec, Qk_vec, Qk_vec>(
|
| 1073 |
+
k,
|
| 1074 |
+
*reinterpret_cast<const Qk_vec*>(
|
| 1075 |
+
¶ms.ia3_key_weights[(ia3_task_id * params.num_heads + hi) * Dh + tidx * QK_VEC_SIZE]));
|
| 1076 |
+
}
|
| 1077 |
+
|
| 1078 |
+
// Padded len
|
| 1079 |
+
const int padd_len = (params.total_padding_tokens == nullptr) ? 0 : params.total_padding_tokens[bi];
|
| 1080 |
+
if (params.rotary_embedding_dim > 0 && !params.neox_rotary_style) {
|
| 1081 |
+
if (handle_kv) {
|
| 1082 |
+
apply_rotary_embedding(q, k, tidx, params.rotary_embedding_dim, tlength - padd_len, params.rotary_base, params.rotary_scale);
|
| 1083 |
+
}
|
| 1084 |
+
else {
|
| 1085 |
+
apply_rotary_embedding(q, tidx, params.rotary_embedding_dim, tlength - padd_len, params.rotary_base, params.rotary_scale);
|
| 1086 |
+
}
|
| 1087 |
+
}
|
| 1088 |
+
else if (params.rotary_embedding_dim > 0 && params.neox_rotary_style) {
|
| 1089 |
+
const bool do_rotary = !is_masked && QK_VEC_SIZE * tidx < params.rotary_embedding_dim;
|
| 1090 |
+
|
| 1091 |
+
T* q_smem = reinterpret_cast<T*>(smem_);
|
| 1092 |
+
T* k_smem = q_smem + params.rotary_embedding_dim;
|
| 1093 |
+
|
| 1094 |
+
const int half_rotary_dim = params.rotary_embedding_dim / 2;
|
| 1095 |
+
const int half_idx = (tidx * QK_VEC_SIZE) / half_rotary_dim;
|
| 1096 |
+
const int intra_half_idx = (tidx * QK_VEC_SIZE) % half_rotary_dim;
|
| 1097 |
+
const int smem_pitch = half_rotary_dim; // TODO: adjust for bank conflicts
|
| 1098 |
+
|
| 1099 |
+
assert(half_rotary_dim % QK_VEC_SIZE == 0);
|
| 1100 |
+
|
| 1101 |
+
if (do_rotary) {
|
| 1102 |
+
*reinterpret_cast<Qk_vec*>(q_smem + half_idx * smem_pitch + intra_half_idx) = q;
|
| 1103 |
+
|
| 1104 |
+
if (handle_kv) {
|
| 1105 |
+
*reinterpret_cast<Qk_vec*>(k_smem + half_idx * smem_pitch + intra_half_idx) = k;
|
| 1106 |
+
}
|
| 1107 |
+
}
|
| 1108 |
+
|
| 1109 |
+
__syncthreads();
|
| 1110 |
+
|
| 1111 |
+
const int transpose_idx = half_idx * (half_rotary_dim / 2) + intra_half_idx / 2;
|
| 1112 |
+
constexpr int tidx_factor = (QK_VEC_SIZE > 1) ? QK_VEC_SIZE / 2 : 1;
|
| 1113 |
+
if (do_rotary) {
|
| 1114 |
+
mmha::vec_from_smem_transpose(q, q_smem, transpose_idx, smem_pitch);
|
| 1115 |
+
|
| 1116 |
+
if (handle_kv) {
|
| 1117 |
+
mmha::vec_from_smem_transpose(k, k_smem, transpose_idx, smem_pitch);
|
| 1118 |
+
|
| 1119 |
+
mmha::apply_rotary_embedding(
|
| 1120 |
+
q, k, transpose_idx / tidx_factor, params.rotary_embedding_dim, tlength - padd_len, params.rotary_base, params.rotary_scale);
|
| 1121 |
+
|
| 1122 |
+
mmha::write_smem_transpose(k, k_smem, transpose_idx, smem_pitch);
|
| 1123 |
+
}
|
| 1124 |
+
else {
|
| 1125 |
+
mmha::apply_rotary_embedding(
|
| 1126 |
+
q, transpose_idx / tidx_factor, params.rotary_embedding_dim, tlength, params.rotary_base, params.rotary_scale);
|
| 1127 |
+
}
|
| 1128 |
+
mmha::write_smem_transpose(q, q_smem, transpose_idx, smem_pitch);
|
| 1129 |
+
}
|
| 1130 |
+
|
| 1131 |
+
__syncthreads();
|
| 1132 |
+
|
| 1133 |
+
if (do_rotary) {
|
| 1134 |
+
q = *reinterpret_cast<Qk_vec*>(q_smem + half_idx * smem_pitch + intra_half_idx);
|
| 1135 |
+
if (handle_kv) {
|
| 1136 |
+
k = *reinterpret_cast<Qk_vec*>(k_smem + half_idx * smem_pitch + intra_half_idx);
|
| 1137 |
+
}
|
| 1138 |
+
}
|
| 1139 |
+
|
| 1140 |
+
__syncthreads();
|
| 1141 |
+
}
|
| 1142 |
+
|
| 1143 |
+
if (!is_masked) {
|
| 1144 |
+
// Store the Q values to shared memory.
|
| 1145 |
+
*reinterpret_cast<Qk_vec*>(&q_smem[tidx * QK_VEC_SIZE]) = q;
|
| 1146 |
+
|
| 1147 |
+
// Store Dh values of k_bias into smem, since will need to add later
|
| 1148 |
+
// if params.timestep == 0
|
| 1149 |
+
if (DO_CROSS_ATTENTION && params.timestep == 0) {
|
| 1150 |
+
*reinterpret_cast<Qk_vec*>(&bias_smem[tidx * QK_VEC_SIZE]) = k_bias;
|
| 1151 |
+
}
|
| 1152 |
+
|
| 1153 |
+
// Write the K values to the global memory cache.
|
| 1154 |
+
//
|
| 1155 |
+
// NOTE: The stores are uncoalesced as we have multiple chunks of 16B spread across the memory
|
| 1156 |
+
// system. We designed it this way as it allows much better memory loads (and there are many
|
| 1157 |
+
// more loads) + the stores are really "write and forget" since we won't need the ack before
|
| 1158 |
+
// the end of the kernel. There's plenty of time for the transactions to complete.
|
| 1159 |
+
|
| 1160 |
+
// The 16B chunk written by the thread.
|
| 1161 |
+
int co = tidx / QK_VECS_IN_16B;
|
| 1162 |
+
// The position of the thread in that 16B chunk.
|
| 1163 |
+
int ci = tidx % QK_VECS_IN_16B * QK_VEC_SIZE;
|
| 1164 |
+
|
| 1165 |
+
// Two chunks are separated by L * x elements. A thread write QK_VEC_SIZE elements.
|
| 1166 |
+
int offset = bhi_kv * params.memory_max_len * Dh + co * params.memory_max_len * QK_ELTS_IN_16B +
|
| 1167 |
+
// params.timestep*QK_ELTS_IN_16B +
|
| 1168 |
+
tlength_circ * QK_ELTS_IN_16B + ci;
|
| 1169 |
+
|
| 1170 |
+
if (write_kv_cache) {
|
| 1171 |
+
// Trigger the stores to global memory.
|
| 1172 |
+
if (Dh == Dh_MAX || co < Dh / QK_ELTS_IN_16B) {
|
| 1173 |
+
*reinterpret_cast<Qk_vec*>(¶ms.k_cache[offset]) = k;
|
| 1174 |
+
}
|
| 1175 |
+
}
|
| 1176 |
+
|
| 1177 |
+
// Compute \sum_i Q[i] * K^T[i] for the current timestep.
|
| 1178 |
+
#ifdef MMHA_USE_FP32_ACUM_FOR_FMA
|
| 1179 |
+
using Qk_vec_acum = typename Qk_vec_acum_fp32_<Qk_vec>::Type;
|
| 1180 |
+
#else
|
| 1181 |
+
using Qk_vec_acum = Qk_vec;
|
| 1182 |
+
#endif
|
| 1183 |
+
qk = dot<Qk_vec_acum, Qk_vec>(q, k);
|
| 1184 |
+
if (QK_VECS_PER_WARP <= WARP_SIZE) {
|
| 1185 |
+
#pragma unroll
|
| 1186 |
+
for (int mask = QK_VECS_PER_WARP / 2; mask >= 1; mask /= 2) {
|
| 1187 |
+
qk += __shfl_xor_sync(shfl_mask(QK_VECS_PER_WARP), qk, mask);
|
| 1188 |
+
}
|
| 1189 |
+
}
|
| 1190 |
+
}
|
| 1191 |
+
|
| 1192 |
+
if (QK_VECS_PER_WARP > WARP_SIZE) {
|
| 1193 |
+
constexpr int WARPS_PER_RED = (QK_VECS_PER_WARP + WARP_SIZE - 1) / WARP_SIZE;
|
| 1194 |
+
qk = block_sum<WARPS_PER_RED>(&red_smem[WARPS_PER_RED], qk);
|
| 1195 |
+
}
|
| 1196 |
+
|
| 1197 |
+
// Store that value in shared memory. Keep the Q*K^T value in register for softmax.
|
| 1198 |
+
if (tidx == 0) {
|
| 1199 |
+
// Normalize qk.
|
| 1200 |
+
qk *= params.inv_sqrt_dh;
|
| 1201 |
+
if (params.relative_attention_bias != nullptr) {
|
| 1202 |
+
// TODO (Haotian): check whether we should replace hi with hi_kv,
|
| 1203 |
+
// although params.relative_attention_bias is usually not used.
|
| 1204 |
+
qk = add(qk,
|
| 1205 |
+
params.relative_attention_bias[hi * params.relative_attention_bias_stride
|
| 1206 |
+
* params.relative_attention_bias_stride
|
| 1207 |
+
+ (tlength - padd_len) * params.relative_attention_bias_stride
|
| 1208 |
+
+ (tlength - padd_len)]);
|
| 1209 |
+
}
|
| 1210 |
+
// Add alibi positional encoding
|
| 1211 |
+
// qk += (alibi_slope != 0) ? alibi_slope * (params.timestep - params.memory_max_len) : 0;
|
| 1212 |
+
// We don't need to apply the linear position bias here since qi - ki = 0 yields the position bias 0.
|
| 1213 |
+
|
| 1214 |
+
qk_max = qk;
|
| 1215 |
+
qk_smem[tlength - first_step] = qk;
|
| 1216 |
+
// qk_smem[params.timestep] = qk;
|
| 1217 |
+
}
|
| 1218 |
+
|
| 1219 |
+
// Make sure the data is in shared memory.
|
| 1220 |
+
__syncthreads();
|
| 1221 |
+
|
| 1222 |
+
// The type of queries and keys for the math in the Q*K^T product.
|
| 1223 |
+
using K_vec = typename K_vec_<T, THREADS_PER_KEY>::Type;
|
| 1224 |
+
// The number of elements per vector.
|
| 1225 |
+
constexpr int K_VEC_SIZE = sizeof(K_vec) / sizeof(T);
|
| 1226 |
+
// Make sure the hidden size per head is a multiple of the vector size.
|
| 1227 |
+
static_assert(Dh_MAX % K_VEC_SIZE == 0, "");
|
| 1228 |
+
// The number of elements per thread.
|
| 1229 |
+
constexpr int K_ELTS_PER_THREAD = Dh_MAX / THREADS_PER_KEY;
|
| 1230 |
+
// The number of vectors per thread.
|
| 1231 |
+
constexpr int K_VECS_PER_THREAD = K_ELTS_PER_THREAD / K_VEC_SIZE;
|
| 1232 |
+
|
| 1233 |
+
// The position the first key loaded by each thread from the cache buffer (for this B * H).
|
| 1234 |
+
int ko = tidx / THREADS_PER_KEY;
|
| 1235 |
+
// The position of the thread in the chunk of keys.
|
| 1236 |
+
int ki = tidx % THREADS_PER_KEY * K_VEC_SIZE;
|
| 1237 |
+
|
| 1238 |
+
static_assert(Dh_MAX == THREADS_PER_KEY * K_VEC_SIZE * K_VECS_PER_THREAD);
|
| 1239 |
+
|
| 1240 |
+
// Load the Q values from shared memory. The values are reused during the loop on K.
|
| 1241 |
+
K_vec q_vec[K_VECS_PER_THREAD];
|
| 1242 |
+
#pragma unroll
|
| 1243 |
+
for (int ii = 0; ii < K_VECS_PER_THREAD; ++ii) {
|
| 1244 |
+
q_vec[ii] = *reinterpret_cast<const K_vec*>(&q_smem[ki + ii * THREADS_PER_KEY * K_VEC_SIZE]);
|
| 1245 |
+
}
|
| 1246 |
+
|
| 1247 |
+
K_vec k_bias_vec[DO_CROSS_ATTENTION ? K_VECS_PER_THREAD : 1];
|
| 1248 |
+
if (DO_CROSS_ATTENTION && params.timestep == 0) {
|
| 1249 |
+
#pragma unroll
|
| 1250 |
+
for (int ii = 0; ii < K_VECS_PER_THREAD; ++ii) {
|
| 1251 |
+
k_bias_vec[ii] = *reinterpret_cast<const K_vec*>(&bias_smem[ki + ii * THREADS_PER_KEY * K_VEC_SIZE]);
|
| 1252 |
+
}
|
| 1253 |
+
}
|
| 1254 |
+
|
| 1255 |
+
// The number of timesteps loaded per iteration.
|
| 1256 |
+
constexpr int K_PER_ITER = THREADS_PER_BLOCK / THREADS_PER_KEY;
|
| 1257 |
+
// The number of keys per warp.
|
| 1258 |
+
constexpr int K_PER_WARP = WARP_SIZE / THREADS_PER_KEY;
|
| 1259 |
+
|
| 1260 |
+
// The base pointer for the key in the cache buffer.
|
| 1261 |
+
T* k_cache = ¶ms.k_cache[bhi_kv * params.memory_max_len * Dh + ki];
|
| 1262 |
+
// Base pointer for the beam's batch, before offsetting with indirection buffer
|
| 1263 |
+
T* k_cache_batch = ¶ms.k_cache[bbhi_kv * params.memory_max_len * Dh + ki];
|
| 1264 |
+
|
| 1265 |
+
// Pick a number of keys to make sure all the threads of a warp enter (due to shfl_sync).
|
| 1266 |
+
// int ti_end = div_up(params.timestep, K_PER_WARP) * K_PER_WARP;
|
| 1267 |
+
int ti_end = div_up(tlength - first_step, K_PER_WARP) * K_PER_WARP + first_step;
|
| 1268 |
+
|
| 1269 |
+
// prefix prompt length if has
|
| 1270 |
+
const int prefix_prompt_length = (params.prefix_prompt_lengths == nullptr) ? 0 : params.prefix_prompt_lengths[bi];
|
| 1271 |
+
|
| 1272 |
+
// Iterate over the keys/timesteps to compute the various (Q*K^T)_{ti} values.
|
| 1273 |
+
const bool has_beams = params.cache_indir != nullptr;
|
| 1274 |
+
const int* beam_indices = has_beams ? ¶ms.cache_indir[bi_seq_len_offset] : nullptr;
|
| 1275 |
+
|
| 1276 |
+
for (int ti = first_step + ko; ti < ti_end; ti += K_PER_ITER) {
|
| 1277 |
+
const int ti_circ = ti % params.memory_max_len;
|
| 1278 |
+
|
| 1279 |
+
// The keys loaded from the key cache.
|
| 1280 |
+
K_vec k[K_VECS_PER_THREAD];
|
| 1281 |
+
K_vec k_vec_zero;
|
| 1282 |
+
zero(k_vec_zero);
|
| 1283 |
+
#pragma unroll
|
| 1284 |
+
for (int ii = 0; ii < K_VECS_PER_THREAD; ++ii) {
|
| 1285 |
+
int jj = ii * params.memory_max_len + ti_circ;
|
| 1286 |
+
// if( ti < params.timestep ) {
|
| 1287 |
+
const bool within_bounds = (Dh == Dh_MAX || jj * QK_ELTS_IN_16B < Dh * params.memory_max_len);
|
| 1288 |
+
if (ti < tlength) {
|
| 1289 |
+
if (!within_bounds) {
|
| 1290 |
+
k[ii] = k_vec_zero;
|
| 1291 |
+
}
|
| 1292 |
+
else {
|
| 1293 |
+
if (has_beams) {
|
| 1294 |
+
const int beam_offset = beam_indices[ti_circ] * params.num_heads * params.memory_max_len * Dh;
|
| 1295 |
+
k[ii] = *reinterpret_cast<const K_vec*>(&k_cache_batch[beam_offset + jj * QK_ELTS_IN_16B]);
|
| 1296 |
+
}
|
| 1297 |
+
else {
|
| 1298 |
+
k[ii] = *reinterpret_cast<const K_vec*>(&k_cache_batch[jj * QK_ELTS_IN_16B]);
|
| 1299 |
+
}
|
| 1300 |
+
}
|
| 1301 |
+
// add bias and update k_cache
|
| 1302 |
+
if (DO_CROSS_ATTENTION && params.timestep == 0) {
|
| 1303 |
+
k[ii] = add(k[ii], k_bias_vec[ii]);
|
| 1304 |
+
|
| 1305 |
+
if (do_ia3) {
|
| 1306 |
+
k[ii] = mul<K_vec, K_vec, K_vec>(
|
| 1307 |
+
k[ii],
|
| 1308 |
+
*reinterpret_cast<const K_vec*>(
|
| 1309 |
+
¶ms.ia3_key_weights[(ia3_task_id * params.num_heads + hi) * Dh + ki
|
| 1310 |
+
+ ii * THREADS_PER_KEY * K_VEC_SIZE]));
|
| 1311 |
+
}
|
| 1312 |
+
|
| 1313 |
+
if (Dh == Dh_MAX || jj * QK_ELTS_IN_16B < Dh * params.memory_max_len) {
|
| 1314 |
+
*reinterpret_cast<K_vec*>(&k_cache[jj * QK_ELTS_IN_16B]) = k[ii];
|
| 1315 |
+
}
|
| 1316 |
+
}
|
| 1317 |
+
}
|
| 1318 |
+
}
|
| 1319 |
+
|
| 1320 |
+
// Perform the dot product and normalize qk.
|
| 1321 |
+
//
|
| 1322 |
+
// WARNING: ALL THE THREADS OF A WARP MUST ENTER!!!
|
| 1323 |
+
float qk = Qk_dot<T, THREADS_PER_KEY>::dot(q_vec, k) * params.inv_sqrt_dh;
|
| 1324 |
+
bool is_mask = (params.masked_tokens != nullptr) && params.masked_tokens[bi_seq_len_offset + ti];
|
| 1325 |
+
|
| 1326 |
+
// Store the product to shared memory. There's one qk value per timestep. Update the max.
|
| 1327 |
+
// if( ti < params.timestep && tidx % THREADS_PER_KEY == 0 ) {
|
| 1328 |
+
if (ti < tlength && tidx % THREADS_PER_KEY == 0) {
|
| 1329 |
+
if (params.relative_attention_bias != nullptr) {
|
| 1330 |
+
qk = add(qk,
|
| 1331 |
+
params.relative_attention_bias[hi * params.relative_attention_bias_stride
|
| 1332 |
+
* params.relative_attention_bias_stride
|
| 1333 |
+
+ tlength * params.relative_attention_bias_stride + ti]);
|
| 1334 |
+
}
|
| 1335 |
+
if (params.linear_bias_slopes != nullptr) {
|
| 1336 |
+
// Apply the linear position bias: (ki - qi) * slope[hi].
|
| 1337 |
+
// The padding token locates between the input context and the generated tokens.
|
| 1338 |
+
// We need to remove the number of padding tokens in the distance computation.
|
| 1339 |
+
// ti : 0 1 2 3 4 5 6 7 8 9(tlength)
|
| 1340 |
+
// token: i i i i p p p o o o where i=input, p=pad, o=output.
|
| 1341 |
+
// e.g. ti = 2, dist = (9 - 3) - 2 = 4.
|
| 1342 |
+
int max_context_length = params.max_prefix_prompt_length + params.max_input_length;
|
| 1343 |
+
float dist = (ti < max_context_length ? ti + padd_len : ti) - tlength;
|
| 1344 |
+
|
| 1345 |
+
qk += mul<float, float, float>(params.linear_bias_slopes[hi], dist);
|
| 1346 |
+
}
|
| 1347 |
+
// Add alibi positional encoding
|
| 1348 |
+
// qk += (alibi_slope != 0) ? alibi_slope * (params.timestep - params.memory_max_len) : 0;
|
| 1349 |
+
qk_max = is_mask ? qk_max : fmaxf(qk_max, qk);
|
| 1350 |
+
qk_smem[ti - first_step] = qk;
|
| 1351 |
+
}
|
| 1352 |
+
}
|
| 1353 |
+
|
| 1354 |
+
// Perform the final reduction to compute the max inside each warp.
|
| 1355 |
+
//
|
| 1356 |
+
// NOTE: In a group of THREADS_PER_KEY threads, the leader already has the max value for the
|
| 1357 |
+
// group so it's not needed to run the reduction inside the group (again).
|
| 1358 |
+
#pragma unroll
|
| 1359 |
+
for (int mask = WARP_SIZE / 2; mask >= THREADS_PER_KEY; mask /= 2) {
|
| 1360 |
+
qk_max = fmaxf(qk_max, __shfl_xor_sync(uint32_t(-1), qk_max, mask));
|
| 1361 |
+
}
|
| 1362 |
+
|
| 1363 |
+
// Decompose the thread index into warp and lane.
|
| 1364 |
+
const int warp = tidx / WARP_SIZE;
|
| 1365 |
+
const int lane = tidx % WARP_SIZE;
|
| 1366 |
+
|
| 1367 |
+
// The warp leader writes the max to shared memory.
|
| 1368 |
+
if (lane == 0) {
|
| 1369 |
+
red_smem[warp] = qk_max;
|
| 1370 |
+
}
|
| 1371 |
+
|
| 1372 |
+
// Make sure the products are in shared memory.
|
| 1373 |
+
__syncthreads();
|
| 1374 |
+
|
| 1375 |
+
// The warps finalize the reduction.
|
| 1376 |
+
qk_max = lane < WARPS_PER_BLOCK ? red_smem[lane] : -FLT_MAX;
|
| 1377 |
+
#pragma unroll
|
| 1378 |
+
for (int mask = WARPS_PER_BLOCK / 2; mask >= 1; mask /= 2) {
|
| 1379 |
+
qk_max = fmaxf(qk_max, __shfl_xor_sync(uint32_t(-1), qk_max, mask));
|
| 1380 |
+
}
|
| 1381 |
+
|
| 1382 |
+
// Broadcast to all the threads in the warp.
|
| 1383 |
+
qk_max = __shfl_sync(uint32_t(-1), qk_max, 0);
|
| 1384 |
+
|
| 1385 |
+
// Compute the logits and start the sum.
|
| 1386 |
+
float sum = 0.f;
|
| 1387 |
+
// for( int ti = tidx; ti <= params.timestep; ti += THREADS_PER_BLOCK ) {
|
| 1388 |
+
for (int ti = first_step + tidx; ti <= tlength; ti += THREADS_PER_BLOCK) {
|
| 1389 |
+
bool is_mask = (params.masked_tokens != nullptr) && params.masked_tokens[bi_seq_len_offset + ti];
|
| 1390 |
+
float logit = is_mask ? 0.f : __expf(qk_smem[ti - first_step] - qk_max);
|
| 1391 |
+
sum += logit;
|
| 1392 |
+
qk_smem[ti - first_step] = logit;
|
| 1393 |
+
}
|
| 1394 |
+
|
| 1395 |
+
// Compute the sum.
|
| 1396 |
+
sum = block_sum<WARPS_PER_BLOCK>(&red_smem[WARPS_PER_BLOCK], sum);
|
| 1397 |
+
|
| 1398 |
+
// Normalize the logits.
|
| 1399 |
+
float inv_sum = __fdividef(1.f, sum + 1.e-6f);
|
| 1400 |
+
// for( int ti = tidx; ti <= params.timestep; ti += THREADS_PER_BLOCK ) {
|
| 1401 |
+
const size_t cross_attention_out_offset =
|
| 1402 |
+
params.is_return_cross_attentions ?
|
| 1403 |
+
bhi_kv * params.max_decoder_seq_len * params.memory_max_len + params.timestep * params.memory_max_len :
|
| 1404 |
+
0;
|
| 1405 |
+
for (int ti = first_step + tidx; ti <= tlength; ti += THREADS_PER_BLOCK) {
|
| 1406 |
+
float logit = qk_smem[ti - first_step] * inv_sum;
|
| 1407 |
+
if (params.is_return_cross_attentions) {
|
| 1408 |
+
params.cross_attention_out[cross_attention_out_offset + ti] = logit;
|
| 1409 |
+
}
|
| 1410 |
+
convert_from_float(logits_smem[ti - first_step], logit);
|
| 1411 |
+
}
|
| 1412 |
+
|
| 1413 |
+
// Put Values part below so we leverage __syncthreads
|
| 1414 |
+
// from the previous step
|
| 1415 |
+
|
| 1416 |
+
// The number of elements per vector.
|
| 1417 |
+
constexpr int V_VEC_SIZE = Dh_MAX / THREADS_PER_VALUE;
|
| 1418 |
+
// A vector of V elements for the current timestep.
|
| 1419 |
+
using V_vec = typename V_vec_<T, V_VEC_SIZE>::Type;
|
| 1420 |
+
|
| 1421 |
+
// The value computed by this thread.
|
| 1422 |
+
int vo = tidx / THREADS_PER_VALUE;
|
| 1423 |
+
// The hidden dimensions computed by this particular thread.
|
| 1424 |
+
int vi = tidx % THREADS_PER_VALUE * V_VEC_SIZE;
|
| 1425 |
+
|
| 1426 |
+
// The base pointer for the value in the cache buffer.
|
| 1427 |
+
T* v_cache = ¶ms.v_cache[bhi_kv * params.memory_max_len * Dh + vi];
|
| 1428 |
+
// Base pointer for the beam's batch, before offsetting with indirection buffer
|
| 1429 |
+
T* v_cache_batch = ¶ms.v_cache[bbhi_kv * params.memory_max_len * Dh + vi];
|
| 1430 |
+
|
| 1431 |
+
// The number of values processed per iteration of the loop.
|
| 1432 |
+
constexpr int V_PER_ITER = THREADS_PER_BLOCK / THREADS_PER_VALUE;
|
| 1433 |
+
|
| 1434 |
+
// One group of threads computes the product(s) for the current timestep.
|
| 1435 |
+
V_vec v_bias;
|
| 1436 |
+
zero(v_bias);
|
| 1437 |
+
// if( vo == params.timestep % V_PER_ITER ) {
|
| 1438 |
+
if (Dh == Dh_MAX || vi < Dh) {
|
| 1439 |
+
if (handle_kv) {
|
| 1440 |
+
if (vo == tlength % V_PER_ITER) {
|
| 1441 |
+
// Trigger the loads from the V bias buffer.
|
| 1442 |
+
if (params.v_bias != nullptr) {
|
| 1443 |
+
v_bias = *reinterpret_cast<const V_vec*>(¶ms.v_bias[hi_kv * Dh + vi]);
|
| 1444 |
+
}
|
| 1445 |
+
if (DO_CROSS_ATTENTION) {
|
| 1446 |
+
*reinterpret_cast<V_vec*>(&bias_smem[vi]) = v_bias;
|
| 1447 |
+
}
|
| 1448 |
+
}
|
| 1449 |
+
}
|
| 1450 |
+
}
|
| 1451 |
+
|
| 1452 |
+
// From previous, before values, step
|
| 1453 |
+
// Also make sure the logits are in shared memory.
|
| 1454 |
+
__syncthreads();
|
| 1455 |
+
|
| 1456 |
+
// Values continued
|
| 1457 |
+
#ifdef MMHA_USE_FP32_ACUM_FOR_OUT
|
| 1458 |
+
using V_vec_acum = typename V_vec_acum_fp32_<V_vec>::Type;
|
| 1459 |
+
#else
|
| 1460 |
+
using V_vec_acum = V_vec;
|
| 1461 |
+
#endif
|
| 1462 |
+
// The partial outputs computed by each thread.
|
| 1463 |
+
V_vec_acum out;
|
| 1464 |
+
zero(out);
|
| 1465 |
+
|
| 1466 |
+
// Loop over the timesteps to compute the partial outputs.
|
| 1467 |
+
// for( int ti = vo; ti < params.timestep; ti += V_PER_ITER ) {
|
| 1468 |
+
if (Dh == Dh_MAX || vi < Dh) {
|
| 1469 |
+
for (int ti = first_step + vo; ti < tlength; ti += V_PER_ITER) {
|
| 1470 |
+
const int ti_circ = ti % params.memory_max_len;
|
| 1471 |
+
|
| 1472 |
+
// Fetch offset based on cache_indir when beam sampling
|
| 1473 |
+
const int beam_src = (params.cache_indir != nullptr) ? params.cache_indir[bi_seq_len_offset + ti_circ] : 0;
|
| 1474 |
+
const int beam_offset = beam_src * params.num_heads * params.memory_max_len * Dh;
|
| 1475 |
+
// Load the values from the cache.
|
| 1476 |
+
V_vec v = *reinterpret_cast<const V_vec*>(&v_cache_batch[beam_offset + ti_circ * Dh]);
|
| 1477 |
+
if (DO_CROSS_ATTENTION && params.timestep == 0) {
|
| 1478 |
+
v = add(v, *reinterpret_cast<V_vec*>(&bias_smem[vi]));
|
| 1479 |
+
if (do_ia3) {
|
| 1480 |
+
v = mul<V_vec, V_vec, V_vec>(
|
| 1481 |
+
v,
|
| 1482 |
+
*reinterpret_cast<const V_vec*>(
|
| 1483 |
+
¶ms.ia3_value_weights[(ia3_task_id * params.num_heads + hi) * Dh + vi]));
|
| 1484 |
+
}
|
| 1485 |
+
*reinterpret_cast<V_vec*>(&v_cache[ti * Dh]) = v;
|
| 1486 |
+
}
|
| 1487 |
+
// Load the logits from shared memory.
|
| 1488 |
+
#if defined(MMHA_USE_FP32_ACUM_FOR_LOGITS)
|
| 1489 |
+
float logit = logits_smem[ti - first_step];
|
| 1490 |
+
out = fma(logit, cast_to_float(v), out);
|
| 1491 |
+
#else
|
| 1492 |
+
T logit = logits_smem[ti - first_step];
|
| 1493 |
+
|
| 1494 |
+
// Update the partial sums.
|
| 1495 |
+
out = fma(logit, v, out);
|
| 1496 |
+
#endif
|
| 1497 |
+
}
|
| 1498 |
+
}
|
| 1499 |
+
|
| 1500 |
+
// One group of threads computes the product(s) for the current timestep.
|
| 1501 |
+
// if( vo == params.timestep % V_PER_ITER ) {
|
| 1502 |
+
if (vo == tlength % V_PER_ITER && (Dh == Dh_MAX || vi < Dh)) {
|
| 1503 |
+
|
| 1504 |
+
V_vec v;
|
| 1505 |
+
if (DO_CROSS_ATTENTION) {
|
| 1506 |
+
v = *reinterpret_cast<const V_vec*>(&v_cache[tlength * Dh]);
|
| 1507 |
+
}
|
| 1508 |
+
else {
|
| 1509 |
+
// Trigger the loads from the V buffer.
|
| 1510 |
+
const auto v_offset = v_base_offset + vi;
|
| 1511 |
+
if (params.int8_mode == 2) {
|
| 1512 |
+
using Packed_Int8_t = typename packed_type<int8_t, num_elems<V_vec>::value>::type;
|
| 1513 |
+
using Packed_Float_t = typename packed_type<float, num_elems<V_vec>::value>::type;
|
| 1514 |
+
const auto v_scaling = params.qkv_scale_out[2];
|
| 1515 |
+
const auto v_quant =
|
| 1516 |
+
*reinterpret_cast<const Packed_Int8_t*>(&reinterpret_cast<const int8_t*>(params.v)[v_offset]);
|
| 1517 |
+
|
| 1518 |
+
convert_from_float(v, mul<Packed_Float_t, float>(v_scaling, float_from_int8(v_quant)));
|
| 1519 |
+
}
|
| 1520 |
+
else {
|
| 1521 |
+
v = *reinterpret_cast<const V_vec*>(¶ms.v[v_offset]);
|
| 1522 |
+
}
|
| 1523 |
+
// Trigger the loads from the V bias buffer.
|
| 1524 |
+
// V_vec v_bias = *reinterpret_cast<const V_vec*>(¶ms.v_bias[hi*Dh + vi]);
|
| 1525 |
+
}
|
| 1526 |
+
|
| 1527 |
+
// Compute the V values with bias.
|
| 1528 |
+
v = add(v, v_bias);
|
| 1529 |
+
if (write_kv_cache) {
|
| 1530 |
+
|
| 1531 |
+
if (do_ia3) {
|
| 1532 |
+
v = mul<V_vec, V_vec, V_vec>(
|
| 1533 |
+
v,
|
| 1534 |
+
*reinterpret_cast<const V_vec*>(
|
| 1535 |
+
¶ms.ia3_value_weights[(ia3_task_id * params.num_heads + hi) * Dh + vi]));
|
| 1536 |
+
}
|
| 1537 |
+
|
| 1538 |
+
// Store the values with bias back to global memory in the cache for V.
|
| 1539 |
+
//*reinterpret_cast<V_vec*>(&v_cache[params.timestep*Dh]) = v;
|
| 1540 |
+
*reinterpret_cast<V_vec*>(&v_cache[tlength_circ * Dh]) = v;
|
| 1541 |
+
}
|
| 1542 |
+
|
| 1543 |
+
// Initialize the output value with the current timestep.
|
| 1544 |
+
#if defined(MMHA_USE_FP32_ACUM_FOR_LOGITS)
|
| 1545 |
+
// out = fma(logits_smem[params.timestep], cast_to_float(v), out);
|
| 1546 |
+
out = fma(logits_smem[tlength - first_step], cast_to_float(v), out);
|
| 1547 |
+
#else
|
| 1548 |
+
// out = fma(logits_smem[params.timestep], v, out);
|
| 1549 |
+
out = fma(logits_smem[tlength - first_step], v, out);
|
| 1550 |
+
#endif
|
| 1551 |
+
}
|
| 1552 |
+
|
| 1553 |
+
// Make sure we can start writing to shared memory.
|
| 1554 |
+
__syncthreads();
|
| 1555 |
+
|
| 1556 |
+
// Run the final reduction amongst the different groups computing different partial outputs.
|
| 1557 |
+
if (Dh == Dh_MAX || vi < Dh) {
|
| 1558 |
+
#pragma unroll
|
| 1559 |
+
for (int active_groups = V_PER_ITER; active_groups >= 2; active_groups /= 2) {
|
| 1560 |
+
|
| 1561 |
+
// The midpoint in the number of active groups.
|
| 1562 |
+
int midpoint = active_groups / 2;
|
| 1563 |
+
|
| 1564 |
+
// The upper part of active threads store to shared memory.
|
| 1565 |
+
if (vo >= midpoint && vo < active_groups && (Dh == Dh_MAX || vi < Dh)) {
|
| 1566 |
+
#ifdef MMHA_USE_FP32_ACUM_FOR_OUT
|
| 1567 |
+
convert_from_float(*reinterpret_cast<V_vec*>(&out_smem[(vo - midpoint) * Dh + vi]), out);
|
| 1568 |
+
#else
|
| 1569 |
+
*reinterpret_cast<V_vec*>(&out_smem[(vo - midpoint) * Dh + vi]) = out;
|
| 1570 |
+
#endif
|
| 1571 |
+
}
|
| 1572 |
+
__syncthreads();
|
| 1573 |
+
|
| 1574 |
+
// The bottom warps update their values.
|
| 1575 |
+
if (vo < midpoint && (Dh == Dh_MAX || vi < Dh)) {
|
| 1576 |
+
out = add(*reinterpret_cast<const V_vec*>(&out_smem[vo * Dh + vi]), out);
|
| 1577 |
+
}
|
| 1578 |
+
__syncthreads();
|
| 1579 |
+
}
|
| 1580 |
+
}
|
| 1581 |
+
|
| 1582 |
+
// Output the final values.
|
| 1583 |
+
if (vo == 0 && (Dh == Dh_MAX || vi < Dh)) {
|
| 1584 |
+
#ifdef MMHA_USE_FP32_ACUM_FOR_OUT
|
| 1585 |
+
if (params.int8_mode == 2) {
|
| 1586 |
+
using Packed_Int8_t = typename packed_type<int8_t, num_elems<V_vec_acum>::value>::type;
|
| 1587 |
+
out = mul<V_vec_acum, float>(*params.attention_out_scale, out);
|
| 1588 |
+
*reinterpret_cast<Packed_Int8_t*>(&(reinterpret_cast<int8_t*>(params.out)[bhi * Dh + vi])) =
|
| 1589 |
+
cast_to_int8(out);
|
| 1590 |
+
}
|
| 1591 |
+
else {
|
| 1592 |
+
convert_from_float(*reinterpret_cast<V_vec*>(¶ms.out[bhi * Dh + vi]), out);
|
| 1593 |
+
}
|
| 1594 |
+
#else
|
| 1595 |
+
// TODO: support int8_mode?
|
| 1596 |
+
*reinterpret_cast<V_vec*>(¶ms.out[bhi * Dh + vi]) = out;
|
| 1597 |
+
#endif
|
| 1598 |
+
}
|
| 1599 |
+
}
|
| 1600 |
+
|
| 1601 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1602 |
+
|
| 1603 |
+
} // namespace mmha
|
| 1604 |
+
|
| 1605 |
+
////////////////////////////////////////////////////////////////////////////////////////////////////
|
| 1606 |
+
|
| 1607 |
+
template<typename T, int Dh, int Dh_MAX, typename KERNEL_PARAMS_TYPE>
|
| 1608 |
+
void mmha_launch_kernel(const KERNEL_PARAMS_TYPE& params, const cudaStream_t& stream);
|
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/attention/setup.py
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Adapted from https://github.com/NVIDIA/apex/blob/master/setup.py
|
| 2 |
+
import sys
|
| 3 |
+
import warnings
|
| 4 |
+
import os
|
| 5 |
+
from packaging.version import parse, Version
|
| 6 |
+
|
| 7 |
+
from setuptools import setup, find_packages
|
| 8 |
+
import subprocess
|
| 9 |
+
|
| 10 |
+
import torch
|
| 11 |
+
from torch.utils.cpp_extension import (
|
| 12 |
+
BuildExtension,
|
| 13 |
+
CppExtension,
|
| 14 |
+
CUDAExtension,
|
| 15 |
+
CUDA_HOME,
|
| 16 |
+
)
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
# ninja build does not work unless include_dirs are abs path
|
| 20 |
+
this_dir = os.path.dirname(os.path.abspath(__file__))
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
def get_cuda_bare_metal_version(cuda_dir):
|
| 24 |
+
raw_output = subprocess.check_output(
|
| 25 |
+
[cuda_dir + "/bin/nvcc", "-V"], universal_newlines=True
|
| 26 |
+
)
|
| 27 |
+
output = raw_output.split()
|
| 28 |
+
release_idx = output.index("release") + 1
|
| 29 |
+
bare_metal_version = parse(output[release_idx].split(",")[0])
|
| 30 |
+
|
| 31 |
+
return raw_output, bare_metal_version
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def check_cuda_torch_binary_vs_bare_metal(cuda_dir):
|
| 35 |
+
raw_output, bare_metal_version = get_cuda_bare_metal_version(cuda_dir)
|
| 36 |
+
torch_binary_version = parse(torch.version.cuda)
|
| 37 |
+
|
| 38 |
+
print("\nCompiling cuda extensions with")
|
| 39 |
+
print(raw_output + "from " + cuda_dir + "/bin\n")
|
| 40 |
+
|
| 41 |
+
if bare_metal_version != torch_binary_version:
|
| 42 |
+
raise RuntimeError(
|
| 43 |
+
"Cuda extensions are being compiled with a version of Cuda that does "
|
| 44 |
+
"not match the version used to compile Pytorch binaries. "
|
| 45 |
+
"Pytorch binaries were compiled with Cuda {}.\n".format(torch.version.cuda)
|
| 46 |
+
+ "In some cases, a minor-version mismatch will not cause later errors: "
|
| 47 |
+
"https://github.com/NVIDIA/apex/pull/323#discussion_r287021798. "
|
| 48 |
+
"You can try commenting out this check (at your own risk)."
|
| 49 |
+
)
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
def raise_if_cuda_home_none(global_option: str) -> None:
|
| 53 |
+
if CUDA_HOME is not None:
|
| 54 |
+
return
|
| 55 |
+
raise RuntimeError(
|
| 56 |
+
f"{global_option} was requested, but nvcc was not found. Are you sure your environment has nvcc available? "
|
| 57 |
+
"If you're installing within a container from https://hub.docker.com/r/pytorch/pytorch, "
|
| 58 |
+
"only images whose names contain 'devel' will provide nvcc."
|
| 59 |
+
)
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
def append_nvcc_threads(nvcc_extra_args):
|
| 63 |
+
_, bare_metal_version = get_cuda_bare_metal_version(CUDA_HOME)
|
| 64 |
+
if bare_metal_version >= Version("11.2"):
|
| 65 |
+
return nvcc_extra_args + ["--threads", "4"]
|
| 66 |
+
return nvcc_extra_args
|
| 67 |
+
|
| 68 |
+
|
| 69 |
+
if not torch.cuda.is_available():
|
| 70 |
+
# https://github.com/NVIDIA/apex/issues/486
|
| 71 |
+
# Extension builds after https://github.com/pytorch/pytorch/pull/23408 attempt to query torch.cuda.get_device_capability(),
|
| 72 |
+
# which will fail if you are compiling in an environment without visible GPUs (e.g. during an nvidia-docker build command).
|
| 73 |
+
print(
|
| 74 |
+
"\nWarning: Torch did not find available GPUs on this system.\n",
|
| 75 |
+
"If your intention is to cross-compile, this is not an error.\n"
|
| 76 |
+
"By default, Apex will cross-compile for Pascal (compute capabilities 6.0, 6.1, 6.2),\n"
|
| 77 |
+
"Volta (compute capability 7.0), Turing (compute capability 7.5),\n"
|
| 78 |
+
"and, if the CUDA version is >= 11.0, Ampere (compute capability 8.0).\n"
|
| 79 |
+
"If you wish to cross-compile for a single specific architecture,\n"
|
| 80 |
+
'export TORCH_CUDA_ARCH_LIST="compute capability" before running setup.py.\n',
|
| 81 |
+
)
|
| 82 |
+
if os.environ.get("TORCH_CUDA_ARCH_LIST", None) is None and CUDA_HOME is not None:
|
| 83 |
+
_, bare_metal_version = get_cuda_bare_metal_version(CUDA_HOME)
|
| 84 |
+
if bare_metal_version >= Version("11.8"):
|
| 85 |
+
os.environ["TORCH_CUDA_ARCH_LIST"] = "6.0;6.1;6.2;7.0;7.5;8.0;8.6;9.0"
|
| 86 |
+
elif bare_metal_version >= Version("11.1"):
|
| 87 |
+
os.environ["TORCH_CUDA_ARCH_LIST"] = "6.0;6.1;6.2;7.0;7.5;8.0;8.6"
|
| 88 |
+
elif bare_metal_version == Version("11.0"):
|
| 89 |
+
os.environ["TORCH_CUDA_ARCH_LIST"] = "6.0;6.1;6.2;7.0;7.5;8.0"
|
| 90 |
+
else:
|
| 91 |
+
os.environ["TORCH_CUDA_ARCH_LIST"] = "6.0;6.1;6.2;7.0;7.5"
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
print("\n\ntorch.__version__ = {}\n\n".format(torch.__version__))
|
| 95 |
+
TORCH_MAJOR = int(torch.__version__.split(".")[0])
|
| 96 |
+
TORCH_MINOR = int(torch.__version__.split(".")[1])
|
| 97 |
+
|
| 98 |
+
cmdclass = {}
|
| 99 |
+
ext_modules = []
|
| 100 |
+
|
| 101 |
+
# Check, if ATen/CUDAGeneratorImpl.h is found, otherwise use ATen/cuda/CUDAGeneratorImpl.h
|
| 102 |
+
# See https://github.com/pytorch/pytorch/pull/70650
|
| 103 |
+
generator_flag = []
|
| 104 |
+
torch_dir = torch.__path__[0]
|
| 105 |
+
if os.path.exists(os.path.join(torch_dir, "include", "ATen", "CUDAGeneratorImpl.h")):
|
| 106 |
+
generator_flag = ["-DOLD_GENERATOR_PATH"]
|
| 107 |
+
|
| 108 |
+
raise_if_cuda_home_none("--ft_attention")
|
| 109 |
+
# Check, if CUDA11 is installed for compute capability 8.0
|
| 110 |
+
cc_flag = []
|
| 111 |
+
_, bare_metal_version = get_cuda_bare_metal_version(CUDA_HOME)
|
| 112 |
+
if bare_metal_version < Version("11.0"):
|
| 113 |
+
raise RuntimeError("ft_attention is only supported on CUDA 11 and above")
|
| 114 |
+
cc_flag.append("-gencode")
|
| 115 |
+
cc_flag.append("arch=compute_70,code=sm_70")
|
| 116 |
+
cc_flag.append("-gencode")
|
| 117 |
+
cc_flag.append("arch=compute_80,code=sm_80")
|
| 118 |
+
if bare_metal_version >= Version("11.8"):
|
| 119 |
+
cc_flag.append("-gencode")
|
| 120 |
+
cc_flag.append("arch=compute_90,code=sm_90")
|
| 121 |
+
|
| 122 |
+
ext_modules.append(
|
| 123 |
+
CUDAExtension(
|
| 124 |
+
name="ft_attention",
|
| 125 |
+
sources=[
|
| 126 |
+
"ft_attention.cpp",
|
| 127 |
+
"decoder_masked_multihead_attention.cu",
|
| 128 |
+
],
|
| 129 |
+
extra_compile_args={
|
| 130 |
+
"cxx": ["-O3", "-DENABLE_BF16"] + generator_flag,
|
| 131 |
+
"nvcc": append_nvcc_threads(
|
| 132 |
+
[
|
| 133 |
+
"-DENABLE_BF16", # TODO
|
| 134 |
+
"-O3",
|
| 135 |
+
"-U__CUDA_NO_HALF_OPERATORS__",
|
| 136 |
+
"-U__CUDA_NO_HALF_CONVERSIONS__",
|
| 137 |
+
"-U__CUDA_NO_BFLOAT16_OPERATORS__",
|
| 138 |
+
"-U__CUDA_NO_BFLOAT16_CONVERSIONS__",
|
| 139 |
+
"-U__CUDA_NO_BFLOAT162_OPERATORS__",
|
| 140 |
+
"-U__CUDA_NO_BFLOAT162_CONVERSIONS__",
|
| 141 |
+
"--expt-relaxed-constexpr",
|
| 142 |
+
"--expt-extended-lambda",
|
| 143 |
+
"--use_fast_math",
|
| 144 |
+
]
|
| 145 |
+
+ generator_flag
|
| 146 |
+
+ cc_flag
|
| 147 |
+
),
|
| 148 |
+
},
|
| 149 |
+
include_dirs=[this_dir],
|
| 150 |
+
)
|
| 151 |
+
)
|
| 152 |
+
|
| 153 |
+
setup(
|
| 154 |
+
name="ft_attention",
|
| 155 |
+
version="0.1",
|
| 156 |
+
description="Attention for single query from FasterTransformer",
|
| 157 |
+
ext_modules=ext_modules,
|
| 158 |
+
cmdclass={"build_ext": BuildExtension} if ext_modules else {},
|
| 159 |
+
)
|
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/layernorm/layernorm.h
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#include <torch/extension.h>
|
| 2 |
+
|
| 3 |
+
void layernorm_forward_cuda(torch::Tensor _input, torch::Tensor _gamma, torch::Tensor _out, float eps);
|
llm-awq/awq/kernels/csrc/layernorm/reduction.cuh
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*
|
| 2 |
+
|
| 3 |
+
Adapted from NVIDIA FasterTransformer:
|
| 4 |
+
https://github.com/NVIDIA/FasterTransformer/blob/main/src/fastertransformer/kernels/reduce_kernel_utils.cuh
|
| 5 |
+
*/
|
| 6 |
+
|
| 7 |
+
#pragma once
|
| 8 |
+
#include <assert.h>
|
| 9 |
+
#if ((__CUDACC_VER_MAJOR__ > 11) || (__CUDACC_VER_MAJOR__ == 11 && __CUDACC_VER_MINOR__ >= 0))
|
| 10 |
+
#include <cooperative_groups/reduce.h>
|
| 11 |
+
#else
|
| 12 |
+
#include <cooperative_groups.h>
|
| 13 |
+
#endif
|
| 14 |
+
#include <cuda_fp16.h>
|
| 15 |
+
#include <cuda_runtime.h>
|
| 16 |
+
#include <float.h>
|
| 17 |
+
#include <type_traits>
|
| 18 |
+
|
| 19 |
+
static const float HALF_FLT_MAX = 65504.F;
|
| 20 |
+
#define FINAL_MASK 0xffffffff
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
template<typename T>
|
| 24 |
+
inline __device__ T add(T a, T b) {
|
| 25 |
+
return a + b;
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
template<>
|
| 29 |
+
inline __device__ half2 add(half2 a, half2 b) {
|
| 30 |
+
return __hadd2(a, b);
|
| 31 |
+
}
|
| 32 |
+
|
| 33 |
+
template<>
|
| 34 |
+
inline __device__ half add(half a, half b) {
|
| 35 |
+
return __hadd(a, b);
|
| 36 |
+
}
|
| 37 |
+
|
| 38 |
+
template<typename T>
|
| 39 |
+
__inline__ __device__ T warpReduceSum(T val)
|
| 40 |
+
{
|
| 41 |
+
#pragma unroll
|
| 42 |
+
for (int mask = 16; mask > 0; mask >>= 1)
|
| 43 |
+
val = add(val, __shfl_xor_sync(FINAL_MASK, val, mask, 32)); //__shfl_sync bf16 return float when sm < 80
|
| 44 |
+
return val;
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
/* Calculate the sum of all elements in a block */
|
| 48 |
+
template<typename T>
|
| 49 |
+
__inline__ __device__ T blockReduceSum(T val)
|
| 50 |
+
{
|
| 51 |
+
static __shared__ T shared[32];
|
| 52 |
+
int lane = threadIdx.x & 0x1f;
|
| 53 |
+
int wid = threadIdx.x >> 5;
|
| 54 |
+
|
| 55 |
+
val = warpReduceSum<T>(val);
|
| 56 |
+
|
| 57 |
+
if (lane == 0)
|
| 58 |
+
shared[wid] = val;
|
| 59 |
+
|
| 60 |
+
__syncthreads();
|
| 61 |
+
|
| 62 |
+
// Modify from blockDim.x << 5 to blockDim.x / 32. to prevent
|
| 63 |
+
// blockDim.x is not divided by 32
|
| 64 |
+
val = (threadIdx.x < (blockDim.x / 32.f)) ? shared[lane] : (T)(0.0f);
|
| 65 |
+
val = warpReduceSum<T>(val);
|
| 66 |
+
|
| 67 |
+
return val;
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
template<typename T>
|
| 72 |
+
__device__ __forceinline__ T clamp_inf_for_half(const float input)
|
| 73 |
+
{
|
| 74 |
+
return input;
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
template<>
|
| 78 |
+
__device__ __forceinline__ half clamp_inf_for_half(const float input)
|
| 79 |
+
{
|
| 80 |
+
// clamp inf values to enable fp16 training
|
| 81 |
+
return input > 0.0f ? __float2half(min(input, HALF_FLT_MAX - 1000)) : __float2half(max(input, -HALF_FLT_MAX + 1000));
|
| 82 |
+
}
|
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/position_embedding/pos_encoding_kernels.cu
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/*
|
| 2 |
+
|
| 3 |
+
Adapted from the VLLM project:
|
| 4 |
+
https://github.com/vllm-project/vllm/blob/main/csrc/pos_encoding_kernels.cu
|
| 5 |
+
|
| 6 |
+
*/
|
| 7 |
+
|
| 8 |
+
#include <torch/extension.h>
|
| 9 |
+
#include <ATen/cuda/CUDAContext.h>
|
| 10 |
+
#include "pos_encoding.h"
|
| 11 |
+
|
| 12 |
+
template<typename scalar_t>
|
| 13 |
+
__global__ void rotary_embedding_neox_kernel(
|
| 14 |
+
const int64_t* __restrict__ positions, // [num_tokens]
|
| 15 |
+
scalar_t* __restrict__ query, // [num_tokens, num_heads, head_size]
|
| 16 |
+
scalar_t* __restrict__ key, // [num_tokens, num_heads, head_size]
|
| 17 |
+
const scalar_t* __restrict__ cos_sin_cache, // [max_position, 2, rot_dim // 2]
|
| 18 |
+
const int rot_dim,
|
| 19 |
+
const int stride,
|
| 20 |
+
const int num_heads,
|
| 21 |
+
const int head_size) {
|
| 22 |
+
// Each thread block is responsible for one token.
|
| 23 |
+
const int token_idx = blockIdx.x;
|
| 24 |
+
int64_t pos = positions[token_idx];
|
| 25 |
+
const scalar_t* cache_ptr = cos_sin_cache + pos * rot_dim;
|
| 26 |
+
|
| 27 |
+
const int embed_dim = rot_dim / 2;
|
| 28 |
+
const int n = num_heads * embed_dim;
|
| 29 |
+
for (int i = threadIdx.x; i < n; i += blockDim.x) {
|
| 30 |
+
const int head_idx = i / embed_dim;
|
| 31 |
+
const int token_head = token_idx * stride + head_idx * head_size;
|
| 32 |
+
|
| 33 |
+
const int rot_offset = i % embed_dim;
|
| 34 |
+
const int x_index = rot_offset;
|
| 35 |
+
const int y_index = embed_dim + rot_offset;
|
| 36 |
+
|
| 37 |
+
const int out_x = token_idx * stride + head_idx * head_size + x_index;
|
| 38 |
+
const int out_y = token_idx * stride + head_idx * head_size + y_index;
|
| 39 |
+
|
| 40 |
+
const scalar_t cos = __ldg(cache_ptr + x_index);
|
| 41 |
+
const scalar_t sin = __ldg(cache_ptr + y_index);
|
| 42 |
+
|
| 43 |
+
const scalar_t q_x = query[token_head + x_index];
|
| 44 |
+
const scalar_t q_y = query[token_head + y_index];
|
| 45 |
+
query[out_x] = q_x * cos - q_y * sin;
|
| 46 |
+
query[out_y] = q_y * cos + q_x * sin;
|
| 47 |
+
|
| 48 |
+
const scalar_t k_x = key[token_head + x_index];
|
| 49 |
+
const scalar_t k_y = key[token_head + y_index];
|
| 50 |
+
key[out_x] = k_x * cos - k_y * sin;
|
| 51 |
+
key[out_y] = k_y * cos + k_x * sin;
|
| 52 |
+
}
|
| 53 |
+
}
|
| 54 |
+
|
| 55 |
+
void rotary_embedding_neox(
|
| 56 |
+
torch::Tensor& positions, // [b, num_tokens]
|
| 57 |
+
torch::Tensor& query, // [b, num_tokens, 1, num_heads, head_size]
|
| 58 |
+
torch::Tensor& key, // [b, num_tokens, 1, num_heads, head_size]
|
| 59 |
+
int head_size,
|
| 60 |
+
torch::Tensor& cos_sin_cache) // [max_position, rot_dim]
|
| 61 |
+
{
|
| 62 |
+
int num_tokens = query.size(0) * query.size(1);
|
| 63 |
+
int rot_dim = cos_sin_cache.size(1);
|
| 64 |
+
int num_heads = query.size(-2);
|
| 65 |
+
int stride = num_heads * head_size;
|
| 66 |
+
// TORCH_CHECK(stride == key.stride(0));
|
| 67 |
+
|
| 68 |
+
dim3 grid(num_tokens);
|
| 69 |
+
dim3 block(std::min(num_heads * rot_dim / 2, 512));
|
| 70 |
+
const cudaStream_t stream = at::cuda::getCurrentCUDAStream();
|
| 71 |
+
AT_DISPATCH_FLOATING_TYPES_AND2(
|
| 72 |
+
at::ScalarType::Half,
|
| 73 |
+
at::ScalarType::BFloat16,
|
| 74 |
+
query.scalar_type(),
|
| 75 |
+
"rotary_embedding_neox",
|
| 76 |
+
[&] {
|
| 77 |
+
rotary_embedding_neox_kernel<scalar_t><<<grid, block, 0, stream>>>(
|
| 78 |
+
positions.data_ptr<int64_t>(),
|
| 79 |
+
query.data_ptr<scalar_t>(),
|
| 80 |
+
key.data_ptr<scalar_t>(),
|
| 81 |
+
cos_sin_cache.data_ptr<scalar_t>(),
|
| 82 |
+
rot_dim,
|
| 83 |
+
stride,
|
| 84 |
+
num_heads,
|
| 85 |
+
head_size);
|
| 86 |
+
});
|
| 87 |
+
}
|
| 88 |
+
|
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 |
+
}
|