chen459664 commited on
Commit
1f57542
·
verified ·
1 Parent(s): 8d423ba

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .cache/torch/comm_lib_trace_rank_0 +0 -0
  2. .cache/torch/comm_lib_trace_rank_1 +0 -0
  3. .conda/aau_token +1 -0
  4. .conda/aau_token_host +1 -0
  5. LSAQ_CoreCode/lsaq_quant.py +170 -0
  6. LSAQ_CoreCode/main.ipynb +321 -0
  7. README.md +1 -0
  8. __pycache__/zscore.cpython-310.pyc +0 -0
  9. __pycache__/zscore.cpython-311.pyc +0 -0
  10. baselines/Llama-2-7b-hf_alpha_idx_10.json +34 -0
  11. baselines/Llama-2-7b-hf_alpha_idx_5.json +34 -0
  12. baselines/Llama-2-7b-hf_kurtosis_idx_10.json +34 -0
  13. baselines/Llama-2-7b-hf_kurtosis_idx_5.json +34 -0
  14. baselines/Llama-2-7b-hf_z_idx_10.json +34 -0
  15. baselines/Llama-2-7b-hf_z_idx_5.json +34 -0
  16. baselines_1/Llama-2-7b-hf_bi_idx_10.json +34 -0
  17. baselines_1/Llama-2-7b-hf_bi_idx_5.json +34 -0
  18. baselines_1/Llama-2-7b-hf_zd_idx_10.json +34 -0
  19. baselines_1/Llama-2-7b-hf_zd_idx_5.json +34 -0
  20. eval.sh +59 -0
  21. eval_coherence.sh +29 -0
  22. eval_fg.sh +89 -0
  23. eval_hd.sh +28 -0
  24. eval_layer_llama.sh +39 -0
  25. eval_layer_qwen.sh +39 -0
  26. eval_zd.sh +29 -0
  27. inference.py +19 -0
  28. layerwise-awq.py +322 -0
  29. llm-awq/.gitignore +173 -0
  30. llm-awq/LICENSE +21 -0
  31. llm-awq/README.md +292 -0
  32. llm-awq/awq.egg-info/PKG-INFO +319 -0
  33. llm-awq/awq/__pycache__/entry.cpython-311.pyc +0 -0
  34. llm-awq/awq/entry.py +357 -0
  35. llm-awq/awq/kernels/csrc/attention/README.md +8 -0
  36. llm-awq/awq/kernels/csrc/attention/cuda_bf16_fallbacks.cuh +257 -0
  37. llm-awq/awq/kernels/csrc/attention/cuda_bf16_wrapper.h +23 -0
  38. llm-awq/awq/kernels/csrc/attention/decoder_masked_multihead_attention.cu +154 -0
  39. llm-awq/awq/kernels/csrc/attention/decoder_masked_multihead_attention.h +185 -0
  40. llm-awq/awq/kernels/csrc/attention/decoder_masked_multihead_attention_template.hpp +1608 -0
  41. llm-awq/awq/kernels/csrc/attention/decoder_masked_multihead_attention_utils.h +1795 -0
  42. llm-awq/awq/kernels/csrc/attention/ft_attention.cpp +185 -0
  43. llm-awq/awq/kernels/csrc/attention/ft_attention.h +16 -0
  44. llm-awq/awq/kernels/csrc/attention/setup.py +159 -0
  45. llm-awq/awq/kernels/csrc/layernorm/layernorm.cu +131 -0
  46. llm-awq/awq/kernels/csrc/layernorm/layernorm.h +3 -0
  47. llm-awq/awq/kernels/csrc/layernorm/reduction.cuh +82 -0
  48. llm-awq/awq/kernels/csrc/position_embedding/pos_encoding.h +9 -0
  49. llm-awq/awq/kernels/csrc/position_embedding/pos_encoding_kernels.cu +88 -0
  50. 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
+ ![overview](figures/overview.png)
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
+ ![TinyChat with LLaMA-3-8b on RTX 4090: W4A16 is 2.7x faster than FP16](./tinychat/figures/4090_example_new.gif)
23
+
24
+ * TinyChat with LLaMA-3-8b on Jetson Orin (2.9x faster than FP16):
25
+
26
+ ![TinyChat with LLaMA-3-8b on Jetson Orin: W4A16 is 2.9x faster than FP16](./tinychat/figures/orin_example_new.gif)
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
+ ![TinyChat with NVILA on 4090 single image](./tinychat/figures/4090_nvila_single.gif)
34
+
35
+ * TinyChat with NVILA-8B on RTX 4090 (multi-image inputs):
36
+
37
+ ![TinyChat with NVILA on 4090 multiple images](./tinychat/figures/4090_nvila_multi.gif)
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
+ ![overview](figures/example_vis.jpg)
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
+ ![overview](figures/overview.png)
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
+ ![TinyChat with LLaMA-3-8b on RTX 4090: W4A16 is 2.7x faster than FP16](./tinychat/figures/4090_example_new.gif)
50
+
51
+ * TinyChat with LLaMA-3-8b on Jetson Orin (2.9x faster than FP16):
52
+
53
+ ![TinyChat with LLaMA-3-8b on Jetson Orin: W4A16 is 2.9x faster than FP16](./tinychat/figures/orin_example_new.gif)
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
+ ![TinyChat with NVILA on 4090 single image](./tinychat/figures/4090_nvila_single.gif)
61
+
62
+ * TinyChat with NVILA-8B on RTX 4090 (multi-image inputs):
63
+
64
+ ![TinyChat with NVILA on 4090 multiple images](./tinychat/figures/4090_nvila_multi.gif)
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
+ ![overview](figures/example_vis.jpg)
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*>(&params.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*>(&params.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*>(&params.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*>(&params.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*>(&params.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
+ &params.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*>(&params.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 = &params.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 = &params.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 ? &params.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
+ &params.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 = &params.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 = &params.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*>(&params.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
+ &params.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*>(&params.v[v_offset]);
1522
+ }
1523
+ // Trigger the loads from the V bias buffer.
1524
+ // V_vec v_bias = *reinterpret_cast<const V_vec*>(&params.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
+ &params.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*>(&params.out[bhi * Dh + vi]), out);
1593
+ }
1594
+ #else
1595
+ // TODO: support int8_mode?
1596
+ *reinterpret_cast<V_vec*>(&params.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> &params,
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(&params, 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
+ }