chen459664 commited on
Commit
02bc7b8
·
verified ·
1 Parent(s): bc2e152

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. eval.sh +59 -0
  17. eval_coherence.sh +29 -0
  18. eval_fg.sh +89 -0
  19. eval_hd.sh +28 -0
  20. eval_layer_llama.sh +39 -0
  21. eval_layer_qwen.sh +39 -0
  22. eval_zd.sh +29 -0
  23. inference.py +19 -0
  24. layerwise-awq.py +322 -0
  25. llm-awq/README.md +292 -0
  26. llm-awq/awq/__pycache__/entry.cpython-311.pyc +0 -0
  27. llm-awq/awq/entry.py +357 -0
  28. llm-awq/awq/kernels/csrc/attention/README.md +8 -0
  29. llm-awq/awq/kernels/csrc/attention/cuda_bf16_fallbacks.cuh +257 -0
  30. llm-awq/awq/kernels/csrc/attention/cuda_bf16_wrapper.h +23 -0
  31. llm-awq/awq/kernels/csrc/attention/decoder_masked_multihead_attention.cu +154 -0
  32. llm-awq/awq/kernels/csrc/attention/decoder_masked_multihead_attention_utils.h +1795 -0
  33. llm-awq/awq/kernels/csrc/attention/ft_attention.cpp +185 -0
  34. llm-awq/awq/kernels/csrc/attention/ft_attention.h +16 -0
  35. llm-awq/awq/kernels/csrc/layernorm/layernorm.cu +131 -0
  36. llm-awq/awq/kernels/csrc/position_embedding/pos_encoding.h +9 -0
  37. llm-awq/awq/kernels/csrc/pybind.cpp +38 -0
  38. llm-awq/awq/kernels/csrc/quantization/gemv_cuda.cu +247 -0
  39. llm-awq/awq/kernels/setup.py +51 -0
  40. llm-awq/tinychat/models/falcon.py +304 -0
  41. llm-awq/tinychat/models/internvl3.py +383 -0
  42. llm-awq/tinychat/models/nvila/builder.py +291 -0
  43. llm-awq/tinychat/models/nvila/llava_arch.py +909 -0
  44. llm-awq/tinychat/models/qwen2.py +511 -0
  45. llm-awq/tinychat/models/vila_llama.py +109 -0
  46. llm-awq/tinychat/modules/fused_attn.py +634 -0
  47. llm-awq/tinychat/modules/fused_internencoder.py +237 -0
  48. llm-awq/tinychat/modules/fused_norm.py +46 -0
  49. llm-awq/tinychat/modules/fused_siglipdecoder.py +282 -0
  50. llm-awq/tinychat/modules/fused_vision_attn.py +272 -0
.cache/torch/comm_lib_trace_rank_0 ADDED
Binary file (118 Bytes). View file
 
.cache/torch/comm_lib_trace_rank_1 ADDED
Binary file (118 Bytes). View file
 
.conda/aau_token ADDED
@@ -0,0 +1 @@
 
 
1
+ YN_RyWTyaweE0R_BuNYxb-
.conda/aau_token_host ADDED
@@ -0,0 +1 @@
 
 
1
+ zHxE_XAQ
LSAQ_CoreCode/lsaq_quant.py ADDED
@@ -0,0 +1,170 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import torch
3
+ import torch.nn as nn
4
+ import numpy as np
5
+ from transformers import AutoTokenizer, AutoModelForCausalLM
6
+ import tqdm
7
+ import json
8
+ import math
9
+ import torch.nn.functional as F
10
+
11
+
12
+ from datasets import load_dataset
13
+
14
+ @torch.no_grad()
15
+ def quantize_weight_per_channel_absmax(w, n_bits=8):
16
+ # w: (out_features, in_features)
17
+ scales = w.abs().max(dim=-1, keepdim=True)[0]
18
+ q_max = 2 ** (n_bits - 1) - 1
19
+ scales.clamp_(min=1e-5).div_(q_max)
20
+ w.div_(scales).round_().mul_(scales)
21
+ return w
22
+
23
+
24
+ @torch.no_grad()
25
+ def quantize_weight_per_tensor_absmax(w, n_bits=8):
26
+ # w: (out_features, in_features)
27
+ scales = w.abs().max()
28
+ q_max = 2 ** (n_bits - 1) - 1
29
+ scales.clamp_(min=1e-5).div_(q_max)
30
+ w.div_(scales).round_().mul_(scales)
31
+ return w
32
+
33
+ class W8A16Linear(nn.Module):
34
+ def __init__(
35
+ self,
36
+ # bit_width,
37
+ in_features,
38
+ out_features,
39
+ bias=True,
40
+ quantize_output=False,
41
+ ):
42
+ super().__init__()
43
+ # self.bit_width = bit_width
44
+ self.in_features = in_features
45
+ self.out_features = out_features
46
+
47
+ self.register_buffer(
48
+ "weight",
49
+ torch.randn(
50
+ self.out_features,
51
+ self.in_features,
52
+ dtype=torch.float16,
53
+ requires_grad=False,
54
+ ),
55
+ )
56
+ if bias:
57
+ self.register_buffer(
58
+ "bias",
59
+ torch.zeros(
60
+ (1, self.out_features), dtype=torch.float16, requires_grad=False
61
+ ),
62
+ )
63
+ else:
64
+ self.register_buffer("bias", None)
65
+
66
+ def to(self, *args, **kwargs):
67
+ super(W8A16Linear, self).to(*args, **kwargs)
68
+ self.weight = self.weight.to(*args, **kwargs)
69
+ if self.bias is not None:
70
+ self.bias = self.bias.to(*args, **kwargs)
71
+ return self
72
+
73
+ @torch.no_grad()
74
+ def forward(self, x):
75
+ y = torch.functional.F.linear(x, self.weight, self.bias)
76
+ return y
77
+
78
+ @staticmethod
79
+ def from_float(
80
+ bit, module, weight_quant="per_channel", quantize_output=False
81
+ ):
82
+ assert isinstance(module, torch.nn.Linear)
83
+ new_module = W8A16Linear(
84
+ # bit,
85
+ module.in_features,
86
+ module.out_features,
87
+ module.bias is not None,
88
+ quantize_output=quantize_output,
89
+ )
90
+ if weight_quant == "per_channel":
91
+ new_module.weight = quantize_weight_per_channel_absmax(module.weight, bit)
92
+ elif weight_quant == "per_tensor":
93
+ new_module.weight = quantize_weight_per_tensor_absmax(module.weight, bit)
94
+ else:
95
+ raise ValueError(f"Invalid weight_quant: {weight_quant}")
96
+ new_module.weight_quant_name = weight_quant
97
+ if module.bias is not None:
98
+ new_module.bias = module.bias
99
+ return new_module
100
+
101
+ def __repr__(self):
102
+ return f"W8A16Linear({self.in_features}, {self.out_features}, bias={self.bias is not None}, weight_quant={self.weight_quant_name})"
103
+
104
+ def quantize_llama_like(
105
+ model, mlp_quant, self_attn_quant, low_bit, weight_quant="per_channel", quantize_bmm_input=False
106
+ ):
107
+ from transformers.models.llama.modeling_llama import (
108
+ LlamaAttention,
109
+ LlamaMLP,
110
+ )
111
+
112
+ for name, m in model.model.named_modules():
113
+ if isinstance(m, LlamaMLP):
114
+ if low_bit == 0:
115
+ continue
116
+ else:
117
+ if name in mlp_quant:
118
+ bit = low_bit
119
+ print(f'{name} {bit} bit quant ')
120
+ else:
121
+ if low_bit == 4:
122
+ bit = 8
123
+ print(f'{name} {bit} bit quant ')
124
+ elif low_bit == 8:
125
+ continue
126
+
127
+ m.gate_proj = W8A16Linear.from_float(
128
+ bit, m.gate_proj, weight_quant=weight_quant
129
+ )
130
+ m.up_proj = W8A16Linear.from_float(
131
+ bit, m.up_proj, weight_quant=weight_quant
132
+ )
133
+ m.down_proj = W8A16Linear.from_float(
134
+ bit, m.down_proj, weight_quant=weight_quant
135
+ )
136
+ elif isinstance(m, LlamaAttention):
137
+ if low_bit == 0:
138
+ continue
139
+ else:
140
+ if name in self_attn_quant:
141
+ bit = low_bit
142
+ else:
143
+ if low_bit == 4:
144
+ bit = 8
145
+ elif low_bit == 8:
146
+ continue
147
+
148
+ m.q_proj = W8A16Linear.from_float(
149
+ bit,
150
+ m.q_proj,
151
+ weight_quant=weight_quant,
152
+ quantize_output=quantize_bmm_input,
153
+ )
154
+ m.k_proj = W8A16Linear.from_float(
155
+ bit,
156
+ m.k_proj,
157
+ weight_quant=weight_quant,
158
+ quantize_output=quantize_bmm_input,
159
+ )
160
+ m.v_proj = W8A16Linear.from_float(
161
+ bit,
162
+ m.v_proj,
163
+ weight_quant=weight_quant,
164
+ quantize_output=quantize_bmm_input,
165
+ )
166
+ m.o_proj = W8A16Linear.from_float(
167
+ bit, m.o_proj, weight_quant=weight_quant
168
+ )
169
+
170
+ return model
LSAQ_CoreCode/main.ipynb ADDED
@@ -0,0 +1,321 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "metadata": {},
7
+ "outputs": [],
8
+ "source": [
9
+ "import os\n",
10
+ "import torch\n",
11
+ "import torch.nn as nn\n",
12
+ "import GPUtil\n",
13
+ "from transformers import AutoTokenizer, AutoModelForCausalLM\n",
14
+ "import tqdm\n",
15
+ "from functools import partial"
16
+ ]
17
+ },
18
+ {
19
+ "cell_type": "markdown",
20
+ "metadata": {},
21
+ "source": [
22
+ "## Resource Detection"
23
+ ]
24
+ },
25
+ {
26
+ "cell_type": "code",
27
+ "execution_count": null,
28
+ "metadata": {},
29
+ "outputs": [],
30
+ "source": [
31
+ "gpus = GPUtil.getGPUs()\n",
32
+ "free_memory = []\n",
33
+ "\n",
34
+ "for gpu in gpus:\n",
35
+ " free_memory.append(gpu.memoryFree)\n",
36
+ "\n",
37
+ "memory_sort = sorted(range(len(free_memory)), key=lambda i: free_memory[i])\n",
38
+ "\n",
39
+ "gpu_id = memory_sort[-1]\n",
40
+ "gpu_memory = free_memory[memory_sort[-1]]\n",
41
+ "\n",
42
+ "print(f'gpu_id:{gpu_id}; gpu_memory:{gpu_memory}')\n",
43
+ "\n",
44
+ "os.environ[\"CUDA_DEVICE_ORDER\"] = \"PCI_BUS_ID\"\n",
45
+ "os.environ[\"CUDA_VISIBLE_DEVICES\"] = str(gpu_id)"
46
+ ]
47
+ },
48
+ {
49
+ "cell_type": "markdown",
50
+ "metadata": {},
51
+ "source": [
52
+ "## Model Selection"
53
+ ]
54
+ },
55
+ {
56
+ "cell_type": "code",
57
+ "execution_count": null,
58
+ "metadata": {},
59
+ "outputs": [],
60
+ "source": [
61
+ "model_name = \"/data/LLMs/Llama-2-7b-hf\"\n",
62
+ "\n",
63
+ "tokenizer = AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)\n",
64
+ "model = AutoModelForCausalLM.from_pretrained(model_name, trust_remote_code=True, torch_dtype=torch.float16, device_map=\"auto\")"
65
+ ]
66
+ },
67
+ {
68
+ "cell_type": "markdown",
69
+ "metadata": {},
70
+ "source": [
71
+ "## Layer Importance Detection"
72
+ ]
73
+ },
74
+ {
75
+ "cell_type": "code",
76
+ "execution_count": null,
77
+ "metadata": {},
78
+ "outputs": [],
79
+ "source": [
80
+ "def encode(tok, text, padding=True, truncation=True, max_length=None):\n",
81
+ " # 将文本转换为输入 IDs\n",
82
+ " input_ids = [tok.bos_id] + tok.encode(text)\n",
83
+ "\n",
84
+ " # 生成注意力掩码\n",
85
+ " attention_mask = [1] * len(input_ids)\n",
86
+ "\n",
87
+ " # 如果进行了填充,则调整注意力掩码\n",
88
+ " if padding:\n",
89
+ " padding_length = max_length - len(input_ids)\n",
90
+ " attention_mask = [0] * padding_length + attention_mask\n",
91
+ " input_ids = [tok.eos_id] * padding_length + input_ids\n",
92
+ "\n",
93
+ " encoded_input = {\n",
94
+ " 'input_ids': input_ids,\n",
95
+ " 'attention_mask': attention_mask\n",
96
+ " }\n",
97
+ " return encoded_input\n",
98
+ "\n",
99
+ "def batch_encode_plus(tok, texts, max_length=None, return_tensors=None):\n",
100
+ " encoded_inputs = []\n",
101
+ "\n",
102
+ " # 循环处理每个文本\n",
103
+ " if max_length is None:\n",
104
+ " max_length = -1\n",
105
+ " for text in texts:\n",
106
+ " # if isinstance(text, list):\n",
107
+ " # text = text[0]\n",
108
+ " # print(text)\n",
109
+ " len_ = len([tok.bos_id] + tok.encode(text))\n",
110
+ " if len_ > max_length:\n",
111
+ " max_length = len_\n",
112
+ " for text in texts:\n",
113
+ " # if isinstance(text, list):\n",
114
+ " # text = text[0]\n",
115
+ " encoded_input = encode(tok, text, max_length = max_length)\n",
116
+ " encoded_inputs.append(encoded_input)\n",
117
+ "\n",
118
+ " # 合并结果\n",
119
+ " batch_encoded = {\n",
120
+ " 'input_ids': [encoded_input['input_ids'] for encoded_input in encoded_inputs],\n",
121
+ " 'attention_mask': [encoded_input['attention_mask'] for encoded_input in encoded_inputs]\n",
122
+ " }\n",
123
+ "\n",
124
+ " batch_encoded = {key: torch.tensor(val) for key, val in batch_encoded.items()}\n",
125
+ "\n",
126
+ " return batch_encoded"
127
+ ]
128
+ },
129
+ {
130
+ "cell_type": "code",
131
+ "execution_count": null,
132
+ "metadata": {},
133
+ "outputs": [],
134
+ "source": [
135
+ "tokenizer.bos_token = tokenizer.eos_token\n",
136
+ "tokenizer.bos_id = tokenizer.bos_token_id\n",
137
+ "tokenizer.eos_id = tokenizer.eos_token_id\n",
138
+ "importances = [0 for i in range(len(model.model.layers))] # layer-wise importance scores"
139
+ ]
140
+ },
141
+ {
142
+ "cell_type": "code",
143
+ "execution_count": null,
144
+ "metadata": {},
145
+ "outputs": [],
146
+ "source": [
147
+ "from datasets import load_dataset\n",
148
+ "\n",
149
+ "dataset = load_dataset(\"wikitext\", \"wikitext-2-raw-v1\", split=\"test\")"
150
+ ]
151
+ },
152
+ {
153
+ "cell_type": "code",
154
+ "execution_count": null,
155
+ "metadata": {},
156
+ "outputs": [],
157
+ "source": [
158
+ "MAX_SEQ_LEN = 1024\n",
159
+ "batch_size = 1\n",
160
+ "dataset_size = 200"
161
+ ]
162
+ },
163
+ {
164
+ "cell_type": "code",
165
+ "execution_count": null,
166
+ "metadata": {},
167
+ "outputs": [],
168
+ "source": [
169
+ "def jaccard_set(list1, list2):\n",
170
+ " \"\"\"Define Jaccard Similarity function for two sets\"\"\"\n",
171
+ " intersection = len(list(set(list1).intersection(list2)))\n",
172
+ " union = (len(list1) + len(list2)) - intersection\n",
173
+ " return float(intersection) / union"
174
+ ]
175
+ },
176
+ {
177
+ "cell_type": "code",
178
+ "execution_count": null,
179
+ "metadata": {},
180
+ "outputs": [],
181
+ "source": [
182
+ "import numpy as np\n",
183
+ "\n",
184
+ "k = 20\n",
185
+ "\n",
186
+ "for i in tqdm.tqdm(range(0, dataset_size, batch_size), total = dataset_size / batch_size):\n",
187
+ " \n",
188
+ " prompts = dataset['text'][i:i + batch_size]\n",
189
+ " max_seq_len = MAX_SEQ_LEN\n",
190
+ " stride = 256\n",
191
+ " max_gen_len = 0\n",
192
+ "\n",
193
+ "\n",
194
+ " prompt_tokens = batch_encode_plus(\n",
195
+ " tokenizer,\n",
196
+ " prompts,\n",
197
+ " return_tensors='pt'\n",
198
+ " )\n",
199
+ " input_ids = prompt_tokens['input_ids']\n",
200
+ " attn_mask = prompt_tokens['attention_mask']\n",
201
+ " max_prompt_len = max(len(t) for t in input_ids)\n",
202
+ " all_jac_sim = [0 for i in range(len(model.model.layers))] \n",
203
+ " E = model.get_input_embeddings().weight.detach()\n",
204
+ " \n",
205
+ " # authors use a sliding window of size 1024 with a shift of 256\n",
206
+ " for start in range(0, max_prompt_len, stride):\n",
207
+ " seq_ids = (attn_mask.sum(dim=-1) > start).nonzero().squeeze()\n",
208
+ " seq_ids = seq_ids.unsqueeze(0) if seq_ids.dim() == 0 else seq_ids # ensure 2d\n",
209
+ " inputs = input_ids[seq_ids, start:start+max_seq_len]\n",
210
+ " attn = attn_mask[seq_ids, start:start+max_seq_len]\n",
211
+ "\n",
212
+ " if max_gen_len == 0:\n",
213
+ " outputs = model(\n",
214
+ " input_ids=inputs.to(\"cuda\"),\n",
215
+ " attention_mask=attn.to(\"cuda\"),\n",
216
+ " output_hidden_states=True,\n",
217
+ " )\n",
218
+ " else:\n",
219
+ " outputs = model.generate(\n",
220
+ " input_ids=inputs.to(\"cuda\"),\n",
221
+ " attention_mask=attn.to(\"cuda\"),\n",
222
+ " max_new_tokens=max_gen_len, \n",
223
+ " output_hidden_states=True,\n",
224
+ " return_dict_in_generate=True,\n",
225
+ " )\n",
226
+ "\n",
227
+ " hiddens = outputs.hidden_states\n",
228
+ "\n",
229
+ " for i in range(len(hiddens) - 1):\n",
230
+ " in_hidden = hiddens[i][:,-1,:]\n",
231
+ " out_hidden = hiddens[i+1][:,-1,:]\n",
232
+ "\n",
233
+ " in_projs = in_hidden @ E.T\n",
234
+ " out_projs = out_hidden @ E.T\n",
235
+ "\n",
236
+ " in_projs = in_projs.detach().cpu().numpy()\n",
237
+ " ot_projs = out_projs.detach().cpu().numpy()\n",
238
+ "\n",
239
+ " in_ind = np.argsort(-in_projs)\n",
240
+ " ot_ind = np.argsort(-ot_projs)\n",
241
+ "\n",
242
+ " in_topks = [tokenizer.decode(i) for i in in_ind[0][:k]]\n",
243
+ " ot_topks = [tokenizer.decode(i) for i in ot_ind[0][:k]]\n",
244
+ "\n",
245
+ " all_jac_sim[i] += jaccard_set(in_topks, ot_topks)\n",
246
+ "\n",
247
+ " \n",
248
+ " importances = [x + y for x, y in zip(importances, all_jac_sim)]\n"
249
+ ]
250
+ },
251
+ {
252
+ "cell_type": "code",
253
+ "execution_count": null,
254
+ "metadata": {},
255
+ "outputs": [],
256
+ "source": [
257
+ "import math\n",
258
+ "def normalize(lst, range_min=0, range_max=1):\n",
259
+ " min_val = min(lst)\n",
260
+ " max_val = max(lst)\n",
261
+ " normalized = [(range_max - range_min) * (x - min_val) / (max_val - min_val) + range_min for x in lst]\n",
262
+ " return normalized\n",
263
+ "\n",
264
+ "filtered_values = [0 if math.isinf(value) else value for value in importances] \n",
265
+ "normalized_lst = normalize(filtered_values)\n",
266
+ "\n",
267
+ "sorted_indices = sorted(range(len(normalized_lst)), key=lambda i: normalized_lst[i])\n",
268
+ "reversed_list = list(reversed(sorted_indices))"
269
+ ]
270
+ },
271
+ {
272
+ "cell_type": "markdown",
273
+ "metadata": {},
274
+ "source": [
275
+ "## Quantize"
276
+ ]
277
+ },
278
+ {
279
+ "cell_type": "code",
280
+ "execution_count": null,
281
+ "metadata": {},
282
+ "outputs": [],
283
+ "source": [
284
+ "from lsaq_quant import quantize_llama_like\n",
285
+ "\n",
286
+ "num_of_layer2quant = 8\n",
287
+ "bit = 8\n",
288
+ "\n",
289
+ "layer_to_quant = reversed_list[0:num_of_layer2quant]\n",
290
+ "\n",
291
+ "mlp_quant = [f'layers.{item}.mlp' for item in layer_to_quant]\n",
292
+ "self_attn_quant = [f'layers.{item}.self_attn' for item in layer_to_quant]\n",
293
+ "\n",
294
+ "print(f'quanting ... ')\n",
295
+ "model_lsaq = quantize_llama_like(model, mlp_quant, self_attn_quant, bit)\n",
296
+ "print(f'quanted')"
297
+ ]
298
+ }
299
+ ],
300
+ "metadata": {
301
+ "kernelspec": {
302
+ "display_name": "smoothquant",
303
+ "language": "python",
304
+ "name": "python3"
305
+ },
306
+ "language_info": {
307
+ "codemirror_mode": {
308
+ "name": "ipython",
309
+ "version": 3
310
+ },
311
+ "file_extension": ".py",
312
+ "mimetype": "text/x-python",
313
+ "name": "python",
314
+ "nbconvert_exporter": "python",
315
+ "pygments_lexer": "ipython3",
316
+ "version": "3.8.19"
317
+ }
318
+ },
319
+ "nbformat": 4,
320
+ "nbformat_minor": 2
321
+ }
README.md ADDED
@@ -0,0 +1 @@
 
 
1
+ # quantization
__pycache__/zscore.cpython-310.pyc ADDED
Binary file (1.93 kB). View file
 
__pycache__/zscore.cpython-311.pyc ADDED
Binary file (2.85 kB). View file
 
baselines/Llama-2-7b-hf_alpha_idx_10.json ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ 4,
3
+ 4,
4
+ 4,
5
+ 4,
6
+ 4,
7
+ 4,
8
+ 4,
9
+ 4,
10
+ 4,
11
+ 4,
12
+ 4,
13
+ 4,
14
+ 4,
15
+ 4,
16
+ 4,
17
+ 4,
18
+ 4,
19
+ 4,
20
+ 4,
21
+ 4,
22
+ 2,
23
+ 2,
24
+ 2,
25
+ 2,
26
+ 2,
27
+ 2,
28
+ 4,
29
+ 2,
30
+ 2,
31
+ 2,
32
+ 2,
33
+ 4
34
+ ]
baselines/Llama-2-7b-hf_alpha_idx_5.json ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ 4,
3
+ 4,
4
+ 4,
5
+ 4,
6
+ 4,
7
+ 4,
8
+ 4,
9
+ 4,
10
+ 4,
11
+ 4,
12
+ 4,
13
+ 4,
14
+ 4,
15
+ 4,
16
+ 4,
17
+ 4,
18
+ 4,
19
+ 4,
20
+ 4,
21
+ 4,
22
+ 2,
23
+ 2,
24
+ 2,
25
+ 4,
26
+ 2,
27
+ 4,
28
+ 4,
29
+ 4,
30
+ 4,
31
+ 4,
32
+ 2,
33
+ 4
34
+ ]
baselines/Llama-2-7b-hf_kurtosis_idx_10.json ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ 4,
3
+ 4,
4
+ 4,
5
+ 4,
6
+ 4,
7
+ 4,
8
+ 4,
9
+ 4,
10
+ 4,
11
+ 4,
12
+ 4,
13
+ 4,
14
+ 4,
15
+ 4,
16
+ 2,
17
+ 2,
18
+ 4,
19
+ 2,
20
+ 2,
21
+ 2,
22
+ 4,
23
+ 2,
24
+ 4,
25
+ 2,
26
+ 4,
27
+ 2,
28
+ 4,
29
+ 2,
30
+ 2,
31
+ 4,
32
+ 4,
33
+ 4
34
+ ]
baselines/Llama-2-7b-hf_kurtosis_idx_5.json ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ 4,
3
+ 4,
4
+ 4,
5
+ 4,
6
+ 4,
7
+ 4,
8
+ 4,
9
+ 4,
10
+ 4,
11
+ 4,
12
+ 4,
13
+ 4,
14
+ 4,
15
+ 4,
16
+ 4,
17
+ 4,
18
+ 4,
19
+ 4,
20
+ 2,
21
+ 4,
22
+ 4,
23
+ 4,
24
+ 4,
25
+ 2,
26
+ 4,
27
+ 2,
28
+ 4,
29
+ 2,
30
+ 2,
31
+ 4,
32
+ 4,
33
+ 4
34
+ ]
baselines/Llama-2-7b-hf_z_idx_10.json ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ 4,
3
+ 4,
4
+ 4,
5
+ 2,
6
+ 2,
7
+ 2,
8
+ 4,
9
+ 2,
10
+ 4,
11
+ 2,
12
+ 2,
13
+ 4,
14
+ 2,
15
+ 4,
16
+ 4,
17
+ 4,
18
+ 4,
19
+ 4,
20
+ 4,
21
+ 4,
22
+ 4,
23
+ 2,
24
+ 4,
25
+ 4,
26
+ 4,
27
+ 2,
28
+ 4,
29
+ 2,
30
+ 4,
31
+ 4,
32
+ 4,
33
+ 4
34
+ ]
baselines/Llama-2-7b-hf_z_idx_5.json ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ 4,
3
+ 4,
4
+ 4,
5
+ 4,
6
+ 4,
7
+ 2,
8
+ 4,
9
+ 4,
10
+ 4,
11
+ 4,
12
+ 4,
13
+ 4,
14
+ 2,
15
+ 4,
16
+ 4,
17
+ 4,
18
+ 4,
19
+ 4,
20
+ 4,
21
+ 4,
22
+ 4,
23
+ 2,
24
+ 4,
25
+ 4,
26
+ 4,
27
+ 2,
28
+ 4,
29
+ 2,
30
+ 4,
31
+ 4,
32
+ 4,
33
+ 4
34
+ ]
eval.sh ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export HTTP_PROXY=http://sys-proxy-rd-relay.byted.org:8118
2
+ export http_proxy=http://sys-proxy-rd-relay.byted.org:8118
3
+ export https_proxy=http://sys-proxy-rd-relay.byted.org:8118
4
+ export no_proxy="$no_proxy,.byteintl.net"
5
+ export HF_ENDPOINT=https://hf-mirror.com
6
+
7
+
8
+ cd quantization_metric/
9
+ model_id=/mnt/bn/life-mllm/users/cxr/quantization/models/Qwen/Qwen2.5-14B
10
+ model_name=$(basename "$model_id")
11
+ cuda_id=4
12
+
13
+ model=/mnt/bn/life-mllm/users/cxr/quantization/models/${model_name}-quantization-layer-mlp
14
+ # output_dir=Alpha_values_mlp
15
+ # bit_layers_dir=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/bit_layers
16
+ # result_dir=/mnt/bn/life-mllm/users/cxr/quantization/lm-evaluation-harness/results
17
+
18
+
19
+
20
+ start=$(date +%s.%N)
21
+ # rm -rf $model
22
+
23
+ modes=("mlp")
24
+ for mode in ${modes[@]}; do
25
+ for idx in {32..47}; do
26
+ echo $mode $idx
27
+ cd ../quantization_metric
28
+ python -u main.py --bit_layer_idx $idx --save_dir ${model} --mode $mode --model_id $model_id --cuda_id $cuda_id
29
+ cd ../lm-evaluation-harness
30
+ bash run_scripts/eval_base_qwen2_5_14b.sh ${model} ${mode}_${idx}
31
+ rm -rf ${model}
32
+ end=$(date +%s.%N)
33
+ runtime=$(awk "BEGIN {print $end - $start}")
34
+ echo "Execution time: $runtime seconds"
35
+
36
+ done
37
+ done
38
+
39
+
40
+ model=/mnt/bn/life-mllm/users/cxr/quantization/models/${model_name}-quantization-layer
41
+
42
+ start=$(date +%s.%N)
43
+ # rm -rf $model
44
+
45
+ modes=("self_attn")
46
+ for mode in ${modes[@]}; do
47
+ for idx in {32..47}; do
48
+ echo $mode $idx
49
+ cd ../quantization_metric
50
+ python -u main.py --bit_layer_idx $idx --save_dir ${model} --mode $mode --model_id $model_id --cuda_id $cuda_id
51
+ cd ../lm-evaluation-harness
52
+ bash run_scripts/eval_base_qwen2_5_14b.sh ${model} ${mode}_${idx}
53
+ rm -rf ${model}
54
+ end=$(date +%s.%N)
55
+ runtime=$(awk "BEGIN {print $end - $start}")
56
+ echo "Execution time: $runtime seconds"
57
+
58
+ done
59
+ done
eval_coherence.sh ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export HTTP_PROXY=http://sys-proxy-rd-relay.byted.org:8118
2
+ export http_proxy=http://sys-proxy-rd-relay.byted.org:8118
3
+ export https_proxy=http://sys-proxy-rd-relay.byted.org:8118
4
+ export no_proxy="$no_proxy,.byteintl.net"
5
+ export HF_ENDPOINT=https://hf-mirror.com
6
+
7
+ cd quantization_metric/
8
+ model=../models/patch/Llama-2-7b-hf-quantization
9
+ # output_dir=Alpha_values_mlp
10
+ tasks=piqa,winogrande,arc_easy,arc_challenge,hellaswag,boolq
11
+ # bit_layers_dir=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/bit_layers
12
+ # result_dir=/mnt/bn/life-mllm/users/cxr/quantization/lm-evaluation-harness/results
13
+
14
+
15
+ start=$(date +%s.%N)
16
+ # rm -rf $model
17
+
18
+ file=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/metrics/coherence/coherence_self_attn_Llama-2-7b-hf.json
19
+ echo "$file"
20
+ cd ../quantization_metric
21
+ configure_id=$(basename $file .json)
22
+ python -u main_low.py --bit_layers $file --save_dir ${model} --k 5 --reverse False
23
+ cd ../lm-evaluation-harness
24
+ bash run_scripts/eval.sh ${configure_id} ${model} ${tasks}
25
+ rm -rf ${model}
26
+ end=$(date +%s.%N)
27
+ runtime=$(awk "BEGIN {print $end - $start}")
28
+ echo "Execution time: $runtime seconds"
29
+
eval_fg.sh ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export HTTP_PROXY=http://sys-proxy-rd-relay.byted.org:8118
2
+ export http_proxy=http://sys-proxy-rd-relay.byted.org:8118
3
+ export https_proxy=http://sys-proxy-rd-relay.byted.org:8118
4
+ export no_proxy="$no_proxy,.byteintl.net"
5
+ export HF_ENDPOINT=https://hf-mirror.com
6
+
7
+
8
+ cd quantization_metric/
9
+ model_id=/mnt/bn/life-mllm/users/cxr/quantization/models/Qwen/Qwen2.5-7B
10
+ model_name=$(basename "$model_id")
11
+
12
+ model=/mnt/bn/life-mllm/users/cxr/quantization/models/${model_name}-quantization-fg
13
+ # output_dir=Alpha_values_mlp
14
+ # bit_layers_dir=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/bit_layers
15
+ # result_dir=/mnt/bn/life-mllm/users/cxr/quantization/lm-evaluation-harness/results
16
+
17
+ start=$(date +%s.%N)
18
+ # rm -rf $model
19
+ cd ../quantization_metric
20
+ # fg1
21
+ # self_attn_layer_to_quant="4 1 2 8 23"
22
+ # mlp_layer_to_quant="27 16 19 17 25"
23
+
24
+
25
+ # save_fg=fg2
26
+ # self_attn_layer_to_quant="23 22 25 24 26"
27
+ # mlp_layer_to_quant="27 16 19 17 25"
28
+
29
+
30
+ # save_fg=fg3
31
+ # self_attn_layer_to_quant="23 22 25 24 26"
32
+ # mlp_layer_to_quant="27 16 19"
33
+
34
+
35
+
36
+ # save_fg=fg4
37
+ # self_attn_layer_to_quant="23 22 25 24 26"
38
+ # mlp_layer_to_quant="27"
39
+
40
+
41
+ # save_fg=fg5
42
+ # self_attn_layer_to_quant="27 16 19 17 25"
43
+ # mlp_layer_to_quant="27 16 19 17 25"
44
+
45
+ # save_fg=baseline_BI
46
+ # self_attn_layer_to_quant="16 17 15 14 13"
47
+ # mlp_layer_to_quant="16 17 15 14 13"
48
+
49
+
50
+ save_fg=f6
51
+ self_attn_layer_to_quant="4 1 2 8 23 22 25 5 24 7 26 6 20 12 19 17 21 11 10 9 18"
52
+ mlp_layer_to_quant="27 16 19"
53
+
54
+ python -u main_fg.py --cuda_id 6 --save_dir ${model} --model_id $model_id --self_attn_layer_to_quant "${self_attn_layer_to_quant}" --mlp_layer_to_quant "${mlp_layer_to_quant}"
55
+ cd ../lm-evaluation-harness
56
+ bash run_scripts/eval_base_fg.sh ${model} ${save_fg}
57
+ rm -rf ${model}
58
+ end=$(date +%s.%N)
59
+ runtime=$(awk "BEGIN {print $end - $start}")
60
+ echo "Execution time: $runtime seconds"
61
+
62
+
63
+
64
+ model_id=/mnt/bn/life-mllm/users/cxr/quantization/models/meta-llama/Llama-3.1-8B
65
+ model_name=$(basename "$model_id")
66
+
67
+ model=/mnt/bn/life-mllm/users/cxr/quantization/models/${model_name}-quantization-fg
68
+ # output_dir=Alpha_values_mlp
69
+ # bit_layers_dir=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/bit_layers
70
+ # result_dir=/mnt/bn/life-mllm/users/cxr/quantization/lm-evaluation-harness/results
71
+
72
+ start=$(date +%s.%N)
73
+ # rm -rf $model
74
+ cd ../quantization_metric
75
+ # save_fg=baseline_BI
76
+ # self_attn_layer_to_quant="24 25 23 26 27"
77
+ # mlp_layer_to_quant="24 25 23 26 27"
78
+ save_fg=fg6
79
+ self_attn_layer_to_quant="29 23 24 30 18 28 26 20 16 27 25 17 19 21"
80
+ mlp_layer_to_quant="26 20 22"
81
+
82
+ python -u main_fg.py --cuda_id 6 --save_dir ${model} --model_id $model_id --self_attn_layer_to_quant "${self_attn_layer_to_quant}" --mlp_layer_to_quant "${mlp_layer_to_quant}"
83
+ cd ../lm-evaluation-harness
84
+ bash run_scripts/eval_base_fg.sh ${model} ${save_fg}
85
+ rm -rf ${model}
86
+ end=$(date +%s.%N)
87
+ runtime=$(awk "BEGIN {print $end - $start}")
88
+ echo "Execution time: $runtime seconds"
89
+
eval_hd.sh ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export HTTP_PROXY=http://sys-proxy-rd-relay.byted.org:8118
2
+ export http_proxy=http://sys-proxy-rd-relay.byted.org:8118
3
+ export https_proxy=http://sys-proxy-rd-relay.byted.org:8118
4
+ export no_proxy="$no_proxy,.byteintl.net"
5
+ export HF_ENDPOINT=https://hf-mirror.com
6
+
7
+ cd quantization_metric/
8
+ model=../models/patch/Llama-2-7b-hf-quantization
9
+ # output_dir=Alpha_values_mlp
10
+ tasks=piqa,winogrande,arc_easy,arc_challenge,hellaswag,boolq
11
+ # bit_layers_dir=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/bit_layers
12
+ # result_dir=/mnt/bn/life-mllm/users/cxr/quantization/lm-evaluation-harness/results
13
+
14
+
15
+ start=$(date +%s.%N)
16
+ # rm -rf $model
17
+
18
+ file=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/metrics/head_diversity/head_diversity_self_attn_Llama-2-7b-hf.json
19
+ echo "$file"
20
+ cd ../quantization_metric
21
+ configure_id=$(basename $file .json)
22
+ python -u main_low.py --bit_layers $file --save_dir ${model} --k 5 --reverse False
23
+ cd ../lm-evaluation-harness
24
+ bash run_scripts/eval.sh ${configure_id} ${model} ${tasks}
25
+ rm -rf ${model}
26
+ end=$(date +%s.%N)
27
+ runtime=$(awk "BEGIN {print $end - $start}")
28
+ echo "Execution time: $runtime seconds"
eval_layer_llama.sh ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export HTTP_PROXY=http://sys-proxy-rd-relay.byted.org:8118
2
+ export http_proxy=http://sys-proxy-rd-relay.byted.org:8118
3
+ export https_proxy=http://sys-proxy-rd-relay.byted.org:8118
4
+ export no_proxy="$no_proxy,.byteintl.net"
5
+ export HF_ENDPOINT=https://hf-mirror.com
6
+
7
+
8
+ cd quantization_metric/
9
+ cuda_id=0
10
+ model_id="/mnt/bn/life-mllm/users/cxr/quantization/models/meta-llama/Llama-3.1-8B"
11
+ model_name=$(basename "$model_id")
12
+
13
+ model=/mnt/bn/life-mllm/users/cxr/quantization/models/${model_name}-quantization-layer
14
+ # output_dir=Alpha_values_mlp
15
+ # bit_layers_dir=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/bit_layers
16
+ # result_dir=/mnt/bn/life-mllm/users/cxr/quantization/lm-evaluation-harness/results
17
+
18
+
19
+
20
+ start=$(date +%s.%N)
21
+ # rm -rf $model
22
+
23
+ modes=("self_attn" "mlp")
24
+ for mode in ${modes[@]}; do
25
+ for idx in {-1..31}; do
26
+ echo $mode $idx
27
+ cd ../quantization_metric
28
+ python -u main.py --bit_layer_idx $idx --save_dir ${model} --mode $mode --model_id $model_id --cuda_id $cuda_id
29
+ cd ../lm-evaluation-harness
30
+ bash run_scripts/eval_base_qwen2_5_7b.sh ${model} ${mode}_${idx} $cuda_id
31
+ rm -rf ${model}
32
+ end=$(date +%s.%N)
33
+ runtime=$(awk "BEGIN {print $end - $start}")
34
+ echo "Execution time: $runtime seconds"
35
+
36
+ done
37
+ done
38
+
39
+
eval_layer_qwen.sh ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export HTTP_PROXY=http://sys-proxy-rd-relay.byted.org:8118
2
+ export http_proxy=http://sys-proxy-rd-relay.byted.org:8118
3
+ export https_proxy=http://sys-proxy-rd-relay.byted.org:8118
4
+ export no_proxy="$no_proxy,.byteintl.net"
5
+ export HF_ENDPOINT=https://hf-mirror.com
6
+
7
+
8
+ cd quantization_metric/
9
+ cuda_id=1
10
+ model_id=/mnt/bn/life-mllm/users/cxr/quantization/models/Qwen/Qwen2.5-7B
11
+ model_name=$(basename "$model_id")
12
+
13
+ model=/mnt/bn/life-mllm/users/cxr/quantization/models/${model_name}-quantization-layer
14
+ # output_dir=Alpha_values_mlp
15
+ # bit_layers_dir=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/bit_layers
16
+ # result_dir=/mnt/bn/life-mllm/users/cxr/quantization/lm-evaluation-harness/results
17
+
18
+
19
+
20
+ start=$(date +%s.%N)
21
+ # rm -rf $model
22
+
23
+ modes=("self_attn" "mlp")
24
+ for mode in ${modes[@]}; do
25
+ for idx in {-1..27}; do
26
+ echo $mode $idx
27
+ cd ../quantization_metric
28
+ python -u main.py --bit_layer_idx $idx --save_dir ${model} --mode $mode --model_id $model_id --cuda_id $cuda_id
29
+ cd ../lm-evaluation-harness
30
+ bash run_scripts/eval_base_qwen2_5_7b.sh ${model} ${mode}_${idx} $cuda_id
31
+ rm -rf ${model}
32
+ end=$(date +%s.%N)
33
+ runtime=$(awk "BEGIN {print $end - $start}")
34
+ echo "Execution time: $runtime seconds"
35
+
36
+ done
37
+ done
38
+
39
+
eval_zd.sh ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export HTTP_PROXY=http://sys-proxy-rd-relay.byted.org:8118
2
+ export http_proxy=http://sys-proxy-rd-relay.byted.org:8118
3
+ export https_proxy=http://sys-proxy-rd-relay.byted.org:8118
4
+ export no_proxy="$no_proxy,.byteintl.net"
5
+ export HF_ENDPOINT=https://hf-mirror.com
6
+
7
+ cd quantization_metric/
8
+ model=../models/patch/Llama-2-7b-hf-quantization-zd
9
+ # output_dir=Alpha_values_mlp
10
+ tasks=piqa,winogrande,arc_easy,arc_challenge,hellaswag,boolq
11
+ # bit_layers_dir=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/bit_layers
12
+ # result_dir=/mnt/bn/life-mllm/users/cxr/quantization/lm-evaluation-harness/results
13
+
14
+
15
+ start=$(date +%s.%N)
16
+ # rm -rf $model
17
+
18
+ # file=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/metrics/ZD/ZD_mlp_Llama-2-7b-hf.json
19
+ file=/mnt/bn/life-mllm/users/cxr/quantization/quantization_metric/metrics/ZD/ZD_self_attn_Llama-2-7b-hf.json
20
+ echo "$file"
21
+ cd ../quantization_metric
22
+ configure_id=$(basename $file .json)
23
+ python -u main_low.py --bit_layers $file --save_dir ${model} --k 5
24
+ cd ../lm-evaluation-harness
25
+ bash run_scripts/eval.sh ${configure_id} ${model} ${tasks}
26
+ rm -rf ${model}
27
+ end=$(date +%s.%N)
28
+ runtime=$(awk "BEGIN {print $end - $start}")
29
+ echo "Execution time: $runtime seconds"
inference.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ a= {"results": {
3
+ "arc_easy": {
4
+ "alias": "arc_easy",
5
+ "acc,none": 0.6902356902356902,
6
+ "acc_stderr,none": 0.00948817285190372,
7
+ "acc_norm,none": 0.6422558922558923,
8
+ "acc_norm_stderr,none": 0.00983577275734336
9
+ },
10
+ "arc_easy": {
11
+ "alias": "arc_easy",
12
+ "acc,none": 0.6902356902356902,
13
+ "acc_stderr,none": 0.00948817285190372,
14
+ "acc_norm,none": 0.6422558922558923,
15
+ "acc_norm_stderr,none": 0.00983577275734336
16
+ }
17
+ }
18
+ }
19
+ print(len(a['results']))
layerwise-awq.py ADDED
@@ -0,0 +1,322 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- encoding:utf-8 -*-
2
+ @torch.no_grad()
3
+ def run_awq(
4
+ model,
5
+ enc,
6
+ w_bit,
7
+ q_config,
8
+ n_samples=512,
9
+ seqlen=512,
10
+ auto_scale=True,
11
+ mse_range=True,
12
+ calib_data="pileval", # data for calibration
13
+ skip_first: int = 0, # number of initial layers to keep in full precision
14
+ first_n: int = 0, # number of initial layers to apply first quant
15
+ w_bit_first: int | None = None,
16
+ w_bit_rest: int | None = None,
17
+ # --- mixed-precision strategy --------------------------------------------------
18
+ strategy: str = "layer", # "layer" (default): original solve layer-by-layer; "auto": structured mixed-precision
19
+ m_auto: int | None = None, # number of high-bit layers when strategy == "auto"; defaults to 25% of L
20
+ hi_bit: int = 4,
21
+ lo_bit: int = 2,
22
+ alpha: float = 1 / 3,
23
+ beta: float = 1 / 3,
24
+ gamma: float = 1 / 3,
25
+ k_energy: int = 32,
26
+ metrics_csv: str | None = None, # optional explicit path to metrics CSV (delta_ppl,erank_diff,topk_energy_diff)
27
+ ):
28
+ from ..utils.calib_data import get_calib_dataset
29
+ from ..utils.module import append_str_prefix, get_op_name
30
+
31
+ if "bigcode" in str(model.__class__).lower():
32
+ # otherwise attention_mask will always be on cpu.
33
+ model.transformer.bias = model.transformer.bias.to("cuda")
34
+
35
+ layers = get_blocks(model)
36
+
37
+ samples = get_calib_dataset(
38
+ data=calib_data, tokenizer=enc, n_samples=n_samples, block_size=seqlen
39
+ )
40
+ samples = torch.cat(samples, dim=0)
41
+
42
+ inps = []
43
+ layer_kwargs = {}
44
+
45
+ layers[0] = layers[0].cuda()
46
+ move_embed(model, "cuda")
47
+
48
+ # get input and kwargs to layer 0
49
+ # with_kwargs is only supported in PyTorch 2.0
50
+ # use this Catcher hack for now
51
+ class Catcher(nn.Module):
52
+ def __init__(self, module):
53
+ super().__init__()
54
+ self.module = module
55
+
56
+ def forward(self, inp, **kwargs):
57
+ inps.append(inp)
58
+ layer_kwargs.update(kwargs)
59
+ raise ValueError # early exit to break later inference
60
+
61
+ # patch layer 0 to catch input and kwargs
62
+ layers[0] = Catcher(layers[0])
63
+ try:
64
+ if model.__class__.__name__ == "LlavaLlamaModel":
65
+ model.llm(samples.to(next(model.parameters()).device))
66
+ elif model.__class__.__name__ == "InternVL3":
67
+ model.language_model(samples.to(next(model.parameters()).device))
68
+ else:
69
+ model(samples.to(next(model.parameters()).device))
70
+ except ValueError: # work with early exit
71
+ pass
72
+ del samples
73
+ layers[0] = layers[0].module # restore
74
+ inps = inps[0]
75
+
76
+ layers[0] = layers[0].cpu()
77
+ move_embed(model, "cpu")
78
+
79
+ gc.collect()
80
+ torch.cuda.empty_cache()
81
+
82
+ awq_results = {
83
+ "scale": [],
84
+ "clip": [],
85
+ }
86
+
87
+ # ---------------------------------------------------------------------------
88
+ # Determine per-layer bit-widths according to the requested *strategy*
89
+ # ---------------------------------------------------------------------------
90
+
91
+ if strategy.lower() == "auto":
92
+ # -------------------------------------------------------------------
93
+ # Use qpRANK pre-computed diagnostics to decide per-layer precision.
94
+ # Users may place the JSON files (drop_layer_ppl.json, diff_erank_values.json)
95
+ # under the project root (default path) or supply env QPRANK_METRICS_DIR.
96
+ # -------------------------------------------------------------------
97
+
98
+ import json, os, math, csv
99
+
100
+ def _load_metrics_from_csv(csv_path: str):
101
+ """Return delta_ppl, erank_diff, topk_energy_diff lists from a csv file."""
102
+ delta_ppl, erank, topk = [], [], []
103
+ with open(csv_path, "r", encoding="utf-8") as f:
104
+ reader = csv.DictReader(f)
105
+ for row in reader:
106
+ delta_ppl.append(float(row.get("delta_ppl", 0)))
107
+ erank.append(abs(float(row.get("erank_diff", 0))))
108
+ topk_val = row.get("topk_energy_diff")
109
+ if topk_val is not None and topk_val != "":
110
+ topk.append(float(topk_val))
111
+ # Ensure all same length
112
+ assert len(delta_ppl) == len(erank), "CSV length mismatch"
113
+ if len(topk) != len(delta_ppl):
114
+ topk = [0.0] * len(delta_ppl)
115
+ return delta_ppl, erank, topk
116
+
117
+ delta_ppl: List[float]
118
+ delta_r: List[float]
119
+ delta_e: List[float]
120
+
121
+ # Priority 1: explicit CSV path
122
+ if metrics_csv is not None and os.path.isfile(metrics_csv):
123
+ delta_ppl, delta_r, delta_e = _load_metrics_from_csv(metrics_csv)
124
+ else:
125
+ # Priority 2: auto-detect inside QPRANK directory structure
126
+ base_dir = os.getenv("QPRANK_METRICS_DIR", os.path.expanduser("~/qpRANK/src"))
127
+
128
+ # Derive a crude model identifier from config
129
+ cfg_name = getattr(model, "config", None)
130
+ model_id = (
131
+ getattr(cfg_name, "_name_or_path", "model").replace("/", "_")
132
+ if cfg_name is not None
133
+ else "model"
134
+ )
135
+
136
+ # Traverse to find a metrics_long.csv matching pattern
137
+ candidate_csv = None
138
+ for root, dirs, files in os.walk(base_dir):
139
+ if "metrics_long.csv" in files and model_id in root:
140
+ candidate_csv = os.path.join(root, "metrics_long.csv")
141
+ break
142
+
143
+ if candidate_csv and os.path.isfile(candidate_csv):
144
+ delta_ppl, delta_r, delta_e = _load_metrics_from_csv(candidate_csv)
145
+ else:
146
+ # Fallback to old JSON files (legacy)
147
+ metrics_dir = os.getenv("QPRANK_METRICS_DIR", os.path.expanduser("~/qpRANK"))
148
+ ppl_path = os.path.join(metrics_dir, "drop_layer_ppl.json")
149
+ erank_path = os.path.join(metrics_dir, "diff_erank_values.json")
150
+
151
+ if not (os.path.isfile(ppl_path) and os.path.isfile(erank_path)):
152
+ raise FileNotFoundError(
153
+ "Cannot locate per-layer metric files for auto strategy. Provide metrics_csv path or set QPRANK_METRICS_DIR appropriately."
154
+ )
155
+
156
+ delta_ppl = json.load(open(ppl_path, "r"))["delta_ppl"]
157
+ erank_json = json.load(open(erank_path, "r"))
158
+
159
+ keys = [k for k in ("q", "k", "v") if k in erank_json]
160
+ delta_r = [
161
+ sum(erank_json[k][i] for k in keys) / len(keys)
162
+ for i in range(len(delta_ppl))
163
+ ]
164
+
165
+ delta_e = erank_json.get("topk_energy_diff", [0.0] * len(delta_ppl))
166
+ #! layer 的数量
167
+ L_total = len(delta_ppl)
168
+
169
+ # Normalise
170
+ def _norm(arr):
171
+ m = max(arr) if max(arr) > 0 else 1.0
172
+ return [x / m for x in arr]
173
+
174
+ ppl_hat = _norm(delta_ppl)
175
+ r_hat = _norm(delta_r)
176
+ e_hat = _norm(delta_e)
177
+
178
+ scores = [
179
+ alpha * ppl_hat[i] + beta * r_hat[i] + gamma * e_hat[i]
180
+ for i in range(L_total)
181
+ ]
182
+
183
+ #! 1/4 的 layer
184
+ if m_auto is None:
185
+ m_auto = max(1, L_total // 4)
186
+
187
+ idx_sorted = sorted(range(L_total), key=lambda i: scores[i], reverse=True)
188
+ #! 前 1/4 的 layer 用 high bit, 其他的用 low bit
189
+ hi_set = set(idx_sorted[:m_auto])
190
+
191
+ #! 每个 layer 的 bit 数量的分配
192
+ #! 我们也是在这边修改成得到我们的 layer 分配就好了
193
+ bits_per_layer = [hi_bit if i in hi_set else lo_bit for i in range(L_total)]
194
+
195
+ # ---- verbose print & log ----
196
+ try:
197
+ import logging
198
+ _logger = logging.getLogger(__name__)
199
+ except ImportError:
200
+ _logger = None
201
+
202
+ print("[AUTO] Per-layer bit-width allocation (index:bit):")
203
+ mapping_str = ", ".join(f"{idx}:{bits_per_layer[idx]}b" for idx in range(L_total))
204
+ print(mapping_str)
205
+
206
+ if _logger is not None:
207
+ _logger.info("AUTO bit-width allocation: " + mapping_str)
208
+
209
+ print(f"[AUTO] Layers @ {hi_bit}-bit: {sorted(list(hi_set))}")
210
+ print(f"[AUTO] Layers @ {lo_bit}-bit: {sorted([i for i in range(L_total) if i not in hi_set])}")
211
+
212
+ if _logger is not None:
213
+ _logger.info(f"Layers_{hi_bit}bit: {sorted(list(hi_set))}")
214
+ _logger.info(f"Layers_{lo_bit}bit: {[i for i in range(L_total) if i not in hi_set]}")
215
+
216
+ else:
217
+ # Fallback to original scheme (uniform or head/tail mixed precision).
218
+ bits_per_layer = None # will be decided on the fly as before
219
+
220
+ # solve layer by layer
221
+ for i in tqdm.tqdm(range(len(layers)), desc="Running AWQ..."):
222
+ # print(f"Layer {i} of {len(layers)-1}")
223
+ layer = layers[i]
224
+
225
+ # Flag: whether to apply quantization to this layer
226
+ #! 他们也指定了超参数从第几层开始量化
227
+ quantize_this = i >= skip_first
228
+
229
+ # Determine bit-width for this layer
230
+ if strategy.lower() == "auto" and bits_per_layer is not None:
231
+ current_w_bit = bits_per_layer[i]
232
+ if i == 0:
233
+ # show a brief summary once for user awareness
234
+ print(
235
+ f"[AUTO] Using structured mixed-precision: {sum(b == hi_bit for b in bits_per_layer)} layers @ {hi_bit}-bit, {sum(b == lo_bit for b in bits_per_layer)} layers @ {lo_bit}-bit."
236
+ )
237
+ else:
238
+ # original rule-based selection
239
+ if i < first_n:
240
+ current_w_bit = w_bit_first if w_bit_first is not None else w_bit
241
+ print(
242
+ f"Layer {i} is quantizing with {current_w_bit} bits. (when this sentence isnt printed, it is quantizing with {w_bit_rest} bits)"
243
+ )
244
+ else:
245
+ current_w_bit = w_bit_rest if w_bit_rest is not None else w_bit
246
+
247
+
248
+ #! 从这边往后就和原来的代码一样
249
+ layer = layer.cuda()
250
+ named_linears = get_named_linears(layer)
251
+
252
+ # firstly, get input features of all linear layers
253
+ def cache_input_hook(m, x, y, name, feat_dict):
254
+ x = x[0]
255
+ x = x.detach().cpu()
256
+ feat_dict[name].append(x)
257
+
258
+ input_feat = defaultdict(list)
259
+ handles = []
260
+ for name in named_linears:
261
+ handles.append(
262
+ named_linears[name].register_forward_hook(
263
+ functools.partial(cache_input_hook, name=name, feat_dict=input_feat)
264
+ )
265
+ )
266
+ inps = inps.to(next(layer.parameters()).device) # in case multi-gpu
267
+ # get output as next layer's input
268
+ inps = layer(inps, **layer_kwargs)[0]
269
+ for h in handles:
270
+ h.remove()
271
+ # now solve for scaling and clipping
272
+ input_feat = {k: torch.cat(v, dim=0) for k, v in input_feat.items()}
273
+
274
+ # Clear GPU memory
275
+ torch.cuda.empty_cache()
276
+
277
+ if (
278
+ auto_scale
279
+ ): # if it applies, we should also modify the input_feat with scales
280
+ scales_list = auto_scale_block(
281
+ layer,
282
+ layer_kwargs,
283
+ w_bit=current_w_bit, #! 改成 current_w_bit 就可以
284
+ q_config=q_config,
285
+ input_feat=input_feat,
286
+ )
287
+ # apply_scale(layer, scales_list, input_feat_dict=input_feat)
288
+ apply_scale(layers[i], scales_list, input_feat_dict=input_feat)
289
+ # append prefix to make names global
290
+ awq_results["scale"] += append_str_prefix(
291
+ scales_list, get_op_name(model, layer) + "."
292
+ )
293
+
294
+ # Clear GPU memory
295
+ torch.cuda.empty_cache()
296
+ # for line in torch.cuda.memory_summary().splitlines():
297
+ # if "Allocated" in line:
298
+ # print(line)
299
+
300
+ if mse_range:
301
+ clip_list = auto_clip_block(
302
+ layer,
303
+ w_bit=current_w_bit, #! 改成 current_w_bit 就可以
304
+ q_config=q_config,
305
+ input_feat=input_feat,
306
+ )
307
+ apply_clip(layer, clip_list)
308
+ # append prefix to make names global
309
+ awq_results["clip"] += append_str_prefix(
310
+ clip_list, get_op_name(model, layer) + "."
311
+ )
312
+
313
+ layer = layer.cpu()
314
+ # Haotian: check activation replacement
315
+ del input_feat
316
+ gc.collect()
317
+ torch.cuda.empty_cache()
318
+ # for line in torch.cuda.memory_summary().splitlines():
319
+ # if "Allocated" in line:
320
+ # print(line)
321
+
322
+ return awq_results
llm-awq/README.md ADDED
@@ -0,0 +1,292 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration
2
+ [[Paper](https://arxiv.org/abs/2306.00978)][[Website](https://hanlab.mit.edu/projects/awq)]
3
+
4
+ **Efficient and accurate** low-bit weight quantization (INT3/4) for LLMs, supporting **instruction-tuned** models and **multi-modal** LMs.
5
+
6
+ ![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/__pycache__/entry.cpython-311.pyc ADDED
Binary file (18.3 kB). View file
 
llm-awq/awq/entry.py ADDED
@@ -0,0 +1,357 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from lm_eval import evaluator, tasks
2
+ from transformers import AutoModelForCausalLM, AutoTokenizer, AutoConfig
3
+ import torch
4
+ import argparse
5
+ import os
6
+ import json
7
+ from accelerate import (
8
+ init_empty_weights,
9
+ infer_auto_device_map,
10
+ dispatch_model,
11
+ load_checkpoint_in_model,
12
+ )
13
+ from accelerate.utils.modeling import get_balanced_memory
14
+ from awq.utils.parallel import auto_parallel
15
+ from awq.quantize.pre_quant import run_awq, apply_awq
16
+ from awq.quantize.quantizer import (
17
+ pseudo_quantize_model_weight,
18
+ real_quantize_model_weight,
19
+ )
20
+ from awq.utils.lm_eval_adaptor import LMEvalAdaptor
21
+ from awq.utils.utils import simple_dispatch_model
22
+ from datasets import load_dataset
23
+ from torch import nn
24
+ import tqdm
25
+
26
+ parser = argparse.ArgumentParser()
27
+ parser.add_argument("--model_path", type=str, help="path of the hf model")
28
+ parser.add_argument("--dtype", type=str, default="float16", choices=["float16", "bfloat16"])
29
+ parser.add_argument("--batch_size", type=int, default=1, help="batch size")
30
+ parser.add_argument("--tasks", default=None, type=str)
31
+ parser.add_argument("--output_path", default=None, type=str)
32
+ parser.add_argument("--num_fewshot", type=int, default=0)
33
+ # model config
34
+ parser.add_argument("--parallel", action="store_true", help="enable model parallelism")
35
+ # max memory to offload larger models to CPU
36
+ parser.add_argument(
37
+ "--max_memory",
38
+ type=str,
39
+ nargs="*",
40
+ help="List of device_id:max_memory pairs to be parsed into a dictionary; "
41
+ + "Example: 0:10GiB 1:10GiB cpu:30GiB; "
42
+ + "mode details here: "
43
+ + "https://huggingface.co/docs/accelerate/usage_guides/big_modeling",
44
+ )
45
+ parser.add_argument(
46
+ "--auto_parallel",
47
+ action="store_true",
48
+ help="automatically set parallel and batch_size",
49
+ )
50
+ # quantization config
51
+ parser.add_argument("--w_bit", type=int, default=None)
52
+ parser.add_argument("--q_group_size", type=int, default=-1)
53
+ parser.add_argument("--no_zero_point", action="store_true", help="disable zero_point")
54
+ parser.add_argument("--q_backend", type=str, default="fake", choices=["fake", "real"])
55
+ # save/load real quantized weights
56
+ parser.add_argument("--dump_quant", type=str, default=None, help="save quantized model")
57
+ parser.add_argument(
58
+ "--dump_fake", type=str, default=None, help="save fake-quantized model"
59
+ )
60
+ parser.add_argument("--load_quant", type=str, default=None, help="load quantized model")
61
+ # apply/save/load awq
62
+ parser.add_argument("--run_awq", action="store_true", help="perform awq search process")
63
+ parser.add_argument(
64
+ "--dump_awq", type=str, default=None, help="save the awq search results"
65
+ )
66
+ parser.add_argument(
67
+ "--load_awq", type=str, default=None, help="load the awq search results"
68
+ )
69
+ parser.add_argument(
70
+ "--vila-15",
71
+ action="store_true",
72
+ help="quantizing vila 1.5",
73
+ )
74
+ parser.add_argument(
75
+ "--vila-20",
76
+ action="store_true",
77
+ help="quantizing or smoothing vila 2.0 (NVILA)",
78
+ )
79
+ parser.add_argument(
80
+ "--smooth_scale",
81
+ action="store_true",
82
+ help="generate the act scale of visiontower",
83
+ )
84
+ parser.add_argument(
85
+ "--media_path",
86
+ type=str,
87
+ nargs="+",
88
+ help="The input video to get act scale for visiontower",
89
+ )
90
+ parser.add_argument(
91
+ "--act_scale_path",
92
+ type=str,
93
+ default=None,
94
+ help="Path to save act scale",
95
+ )
96
+ args = parser.parse_args()
97
+ assert (
98
+ args.act_scale_path is not None and len(args.media_path) > 0
99
+ ) or not args.smooth_scale
100
+ vila_10_quant_mode = (
101
+ ("llava" in args.model_path.lower() or "vila" in args.model_path.lower())
102
+ and not args.vila_15
103
+ and not args.vila_20
104
+ )
105
+
106
+ max_memory = [v.split(":") for v in (args.max_memory or [])]
107
+ max_memory = {(int(k) if k.isdigit() else k): v for k, v in max_memory}
108
+
109
+ if args.auto_parallel:
110
+ gpu_list = auto_parallel(args)
111
+
112
+ # get quantization config (apart from w_bit)
113
+ q_config = {
114
+ "zero_point": not args.no_zero_point, # by default True
115
+ "q_group_size": args.q_group_size, # whether to use group quantization
116
+ }
117
+ print("Quantization config:", q_config)
118
+
119
+ # build model and tokenizer
120
+
121
+
122
+ def build_model_and_enc(model_path, dtype):
123
+ torch_dtype = torch.float16 if dtype == "float16" else torch.bfloat16
124
+ if not os.path.exists(model_path): # look into ssd
125
+ raise FileNotFoundError(f"{model_path} not found!")
126
+ print(f"* Building model {model_path}")
127
+
128
+ # all hf model
129
+ if vila_10_quant_mode:
130
+ from llava.model.builder import load_pretrained_model
131
+ from llava.mm_utils import get_model_name_from_path
132
+
133
+ enc, model, image_processor, context_len = load_pretrained_model(
134
+ model_path=model_path,
135
+ model_base=None,
136
+ model_name=get_model_name_from_path(model_path),
137
+ device="cpu",
138
+ **{"use_cache": False},
139
+ )
140
+ else:
141
+ config = AutoConfig.from_pretrained(model_path, trust_remote_code=True)
142
+ # Note (Haotian): To avoid OOM after huggingface transformers 4.36.2
143
+ config.use_cache = False
144
+ if "mpt" in config.__class__.__name__.lower():
145
+ enc = AutoTokenizer.from_pretrained(
146
+ config.tokenizer_name, trust_remote_code=True
147
+ )
148
+ else:
149
+ enc = AutoTokenizer.from_pretrained(
150
+ model_path, use_fast=False, trust_remote_code=True
151
+ )
152
+
153
+ if args.load_quant: # directly load quantized weights
154
+ print("Loading pre-computed quantized weights...")
155
+ with init_empty_weights():
156
+ model = AutoModelForCausalLM.from_config(
157
+ config=config, torch_dtype=torch_dtype, trust_remote_code=True
158
+ )
159
+ real_quantize_model_weight(
160
+ model, w_bit=args.w_bit, q_config=q_config, init_only=True
161
+ )
162
+
163
+ model.tie_weights()
164
+
165
+ # Infer device map
166
+ kwargs = {"max_memory": max_memory} if len(max_memory) else {}
167
+ device_map = infer_auto_device_map(
168
+ model,
169
+ no_split_module_classes=[
170
+ "OPTDecoderLayer",
171
+ "LlamaDecoderLayer",
172
+ "BloomBlock",
173
+ "MPTBlock",
174
+ "DecoderLayer",
175
+ ],
176
+ **kwargs,
177
+ )
178
+ # Load checkpoint in the model
179
+ load_checkpoint_in_model(
180
+ model,
181
+ checkpoint=args.load_quant,
182
+ device_map=device_map,
183
+ offload_state_dict=True,
184
+ )
185
+ # Dispatch model
186
+ model = simple_dispatch_model(model, device_map=device_map)
187
+
188
+ model.eval()
189
+ else: # fp16 to quantized
190
+ args.run_awq &= not args.load_awq # if load_awq, no need to run awq
191
+ # Init model on CPU:
192
+ kwargs = {"torch_dtype": torch_dtype, "low_cpu_mem_usage": True}
193
+ if not vila_10_quant_mode:
194
+ model = AutoModelForCausalLM.from_pretrained(
195
+ model_path, config=config, trust_remote_code=True, **kwargs
196
+ )
197
+
198
+ model.eval()
199
+
200
+ if args.run_awq:
201
+ assert args.dump_awq, "Please save the awq results with --dump_awq"
202
+
203
+ awq_results = run_awq(
204
+ model,
205
+ enc,
206
+ w_bit=args.w_bit,
207
+ q_config=q_config,
208
+ n_samples=128,
209
+ seqlen=512,
210
+ )
211
+ if args.dump_awq:
212
+ dirpath = os.path.dirname(args.dump_awq)
213
+ os.makedirs(dirpath, exist_ok=True)
214
+
215
+ torch.save(awq_results, args.dump_awq)
216
+ print("AWQ results saved at", args.dump_awq)
217
+
218
+ exit(0)
219
+
220
+ if args.load_awq:
221
+ print("Loading pre-computed AWQ results from", args.load_awq)
222
+ awq_results = torch.load(args.load_awq, map_location="cpu")
223
+ apply_awq(model, awq_results)
224
+
225
+ # weight quantization
226
+ if args.w_bit is not None:
227
+ if args.q_backend == "fake":
228
+ assert (
229
+ args.dump_quant is None
230
+ ), "Need to use real quantization to dump quantized weights"
231
+ pseudo_quantize_model_weight(model, w_bit=args.w_bit, q_config=q_config)
232
+ if args.dump_fake:
233
+ model.save_pretrained(args.dump_fake)
234
+ print("Pseudo-quantized models saved at", args.dump_fake)
235
+ elif args.q_backend == "real": # real quantization
236
+ real_quantize_model_weight(model, w_bit=args.w_bit, q_config=q_config)
237
+ if args.dump_quant:
238
+ if not args.dump_quant.endswith("v2.pt"):
239
+ print("[Info] Auto-change the dump_quant file name to *v2.pt")
240
+ args.dump_quant = args.dump_quant.replace(".pt", "-v2.pt")
241
+ dirpath = os.path.dirname(args.dump_quant)
242
+ os.makedirs(dirpath, exist_ok=True)
243
+
244
+ print(f"Saving the quantized model at {args.dump_quant}...")
245
+ torch.save(model.cpu().state_dict(), args.dump_quant)
246
+ exit(0)
247
+ else:
248
+ raise NotImplementedError
249
+
250
+ # Move the model to GPU (as much as possible) for LM evaluation
251
+ kwargs = {
252
+ "max_memory": get_balanced_memory(
253
+ model, max_memory if len(max_memory) > 0 else None
254
+ )
255
+ }
256
+ device_map = infer_auto_device_map(
257
+ model,
258
+ # TODO: can we remove this?
259
+ no_split_module_classes=[
260
+ "OPTDecoderLayer",
261
+ "LlamaDecoderLayer",
262
+ "BloomBlock",
263
+ "MPTBlock",
264
+ "DecoderLayer",
265
+ ],
266
+ **kwargs,
267
+ )
268
+ model = dispatch_model(model, device_map=device_map)
269
+
270
+ return model, enc
271
+
272
+
273
+ def main():
274
+ if args.output_path is not None and os.path.exists(args.output_path):
275
+ # print(f"Results {args.output_path} already generated. Exit.")
276
+ print(f"Results {args.output_path} already generated. Overwrite.")
277
+ # exit()
278
+
279
+ # a hack here to auto set model group
280
+ if args.smooth_scale and args.vila_20:
281
+ if os.path.exists(args.act_scale_path):
282
+ print(f"Found existing Smooth Scales {args.act_scale_path}, skip.")
283
+ else:
284
+ from awq.quantize import get_smooth_scale
285
+
286
+ act_scale = get_smooth_scale(args.model_path, args.media_path)
287
+ os.makedirs(os.path.dirname(args.act_scale_path), exist_ok=True)
288
+ torch.save(act_scale, args.act_scale_path)
289
+ print("Save act scales at " + str(args.act_scale_path))
290
+ args.model_path = args.model_path + "/llm"
291
+ if args.dump_awq is None and args.dump_quant is None:
292
+ exit()
293
+
294
+ if args.dump_awq and os.path.exists(args.dump_awq):
295
+ print(f"Found existing AWQ results {args.dump_awq}, exit.")
296
+ exit()
297
+ model, enc = build_model_and_enc(args.model_path, args.dtype)
298
+
299
+ if args.tasks is not None:
300
+ # https://github.com/IST-DASLab/gptq/blob/2d65066eeb06a5c9ff5184d8cebdf33662c67faf/llama.py#L206
301
+ if args.tasks == "wikitext":
302
+ testenc = load_dataset("wikitext", "wikitext-2-raw-v1", split="test")
303
+ testenc = enc("\n\n".join(testenc["text"]), return_tensors="pt")
304
+ model.seqlen = 2048
305
+ testenc = testenc.input_ids.to(model.device)
306
+ nsamples = testenc.numel() // model.seqlen
307
+ model = model.eval()
308
+ nlls = []
309
+ for i in tqdm.tqdm(range(nsamples), desc="evaluating..."):
310
+ batch = testenc[:, (i * model.seqlen) : ((i + 1) * model.seqlen)].to(
311
+ model.device
312
+ )
313
+ with torch.no_grad():
314
+ lm_logits = model(batch).logits
315
+ shift_logits = lm_logits[:, :-1, :].contiguous().float()
316
+ shift_labels = testenc[
317
+ :, (i * model.seqlen) : ((i + 1) * model.seqlen)
318
+ ][:, 1:]
319
+ loss_fct = nn.CrossEntropyLoss()
320
+ loss = loss_fct(
321
+ shift_logits.view(-1, shift_logits.size(-1)), shift_labels.view(-1)
322
+ )
323
+ neg_log_likelihood = loss.float() * model.seqlen
324
+ nlls.append(neg_log_likelihood)
325
+
326
+ ppl = torch.exp(torch.stack(nlls).sum() / (nsamples * model.seqlen))
327
+ print(ppl.item())
328
+
329
+ results = {"ppl": ppl.item()}
330
+ if args.output_path is not None:
331
+ os.makedirs(os.path.dirname(args.output_path), exist_ok=True)
332
+ with open(args.output_path, "w") as f:
333
+ json.dump(results, f, indent=2)
334
+ else:
335
+ task_names = args.tasks.split(",")
336
+
337
+ lm_eval_model = LMEvalAdaptor(args.model_path, model, enc, args.batch_size)
338
+ results = evaluator.simple_evaluate(
339
+ model=lm_eval_model,
340
+ tasks=task_names,
341
+ batch_size=args.batch_size,
342
+ no_cache=True,
343
+ num_fewshot=args.num_fewshot,
344
+ )
345
+
346
+ print(evaluator.make_table(results))
347
+
348
+ if args.output_path is not None:
349
+ os.makedirs(os.path.dirname(args.output_path), exist_ok=True)
350
+ # otherwise cannot save
351
+ results["config"]["model"] = args.model_path
352
+ with open(args.output_path, "w") as f:
353
+ json.dump(results, f, indent=2)
354
+
355
+
356
+ if __name__ == "__main__":
357
+ main()
llm-awq/awq/kernels/csrc/attention/README.md ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ # Attention kernel from FasterTransformer
2
+
3
+ This CUDA extension wraps the single-query attention [kernel](https://github.com/NVIDIA/FasterTransformer/blob/release/v5.2.1_tag/src/fastertransformer/kernels/decoder_masked_multihead_attention/decoder_masked_multihead_attention_template.hpp) from
4
+ FasterTransformer v5.2.1 for benchmarking purpose.
5
+
6
+ ```sh
7
+ cd csrc/ft_attention && pip install .
8
+ ```
llm-awq/awq/kernels/csrc/attention/cuda_bf16_fallbacks.cuh ADDED
@@ -0,0 +1,257 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Downloaded from from FasterTransformer v5.2.1
2
+ // https://github.com/NVIDIA/FasterTransformer/blob/release/v5.2.1_tag/src/fastertransformer/utils/cuda_bf16_fallbacks.cuh
3
+ /*
4
+ * Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ #pragma once
20
+
21
+ #include "cuda_bf16_wrapper.h"
22
+ #include <cuda_fp16.h>
23
+
24
+ namespace fastertransformer {
25
+
26
+ #ifdef ENABLE_BF16
27
+ inline __device__ float2 bf1622float2(const __nv_bfloat162 val) {
28
+ #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
29
+ float2 f_val;
30
+ f_val.x = __low2float(val);
31
+ f_val.y = __high2float(val);
32
+ return f_val;
33
+ #else
34
+ return __bfloat1622float2(val);
35
+ #endif
36
+ }
37
+
38
+ inline __device__ int16_t bf1622int16(__nv_bfloat162 val) {
39
+ #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
40
+ float2 f_val;
41
+ f_val.x = max(min(__low2float(val), 127.f), -128.f);
42
+ f_val.y = max(min(__high2float(val), 127.f), -128.f);
43
+ union { int8_t int8[2]; int16_t int16; };
44
+ int8[0] = static_cast<int8_t>(static_cast<short>(f_val.x));
45
+ int8[1] = static_cast<int8_t>(static_cast<short>(f_val.y));
46
+ return int16;
47
+ #else
48
+ val = __hmin2(val, make_bfloat162(127., 127.));
49
+ val = __hmax2(val, make_bfloat162(-128., -128.));
50
+ union { int8_t int8[2]; int16_t int16; };
51
+ int8[0] = static_cast<int8_t>(static_cast<short>(val.x));
52
+ int8[1] = static_cast<int8_t>(static_cast<short>(val.y));
53
+ return int16;
54
+ #endif
55
+ }
56
+
57
+ inline __device__ __nv_bfloat162 float22bf162(const float2 val) {
58
+ #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
59
+ return __floats2bfloat162_rn(val.x, val.y);
60
+ #else
61
+ return __float22bfloat162_rn(val);
62
+ #endif
63
+ }
64
+
65
+ inline __device__ __nv_bfloat162 bf162bf162(const __nv_bfloat16 val) {
66
+ #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
67
+ __nv_bfloat162 val2;
68
+ val2.x = val;
69
+ val2.y = val;
70
+ return val2;
71
+ #else
72
+ return __bfloat162bfloat162(val);
73
+ #endif
74
+ }
75
+
76
+ inline __device__ __nv_bfloat162 bf16hadd2(const __nv_bfloat162 x, const __nv_bfloat162 y) {
77
+ #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
78
+ float fxl, fxh, fyl, fyh;
79
+ fxl = __low2float(x);
80
+ fxh = __high2float(x);
81
+ fyl = __low2float(y);
82
+ fyh = __high2float(y);
83
+ return __floats2bfloat162_rn(fxl + fyl, fxh + fyh);
84
+ #else
85
+ return __hadd2(x, y);
86
+ #endif
87
+ }
88
+
89
+ inline __device__ __nv_bfloat16 bf16hadd(const __nv_bfloat16 x, const __nv_bfloat16 y) {
90
+ #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
91
+ return __float2bfloat16( __bfloat162float(x) + __bfloat162float(y) );
92
+ #else
93
+ return __hadd(x, y);
94
+ #endif
95
+ }
96
+
97
+ inline __device__ __nv_bfloat162 bf16hsub2(const __nv_bfloat162 x, const __nv_bfloat162 y) {
98
+ #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
99
+ float fxl, fxh, fyl, fyh;
100
+ fxl = __low2float(x);
101
+ fxh = __high2float(x);
102
+ fyl = __low2float(y);
103
+ fyh = __high2float(y);
104
+ return __floats2bfloat162_rn(fxl - fyl, fxh - fyh);
105
+ #else
106
+ return __hsub2(x, y);
107
+ #endif
108
+ }
109
+
110
+ inline __device__ __nv_bfloat16 bf16hsub(const __nv_bfloat16 x, const __nv_bfloat16 y) {
111
+ #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
112
+ return __float2bfloat16( __bfloat162float(x) - __bfloat162float(y) );
113
+ #else
114
+ return __hsub(x, y);
115
+ #endif
116
+ }
117
+
118
+ inline __device__ __nv_bfloat162 bf16hmul2(const __nv_bfloat162 x, const __nv_bfloat162 y) {
119
+ #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
120
+ float fxl, fxh, fyl, fyh;
121
+ fxl = __low2float(x);
122
+ fxh = __high2float(x);
123
+ fyl = __low2float(y);
124
+ fyh = __high2float(y);
125
+ return __floats2bfloat162_rn(fxl * fyl, fxh * fyh);
126
+ #else
127
+ return __hmul2(x, y);
128
+ #endif
129
+ }
130
+
131
+ inline __device__ __nv_bfloat16 bf16hmul(const __nv_bfloat16 x, const __nv_bfloat16 y) {
132
+ #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
133
+ return __float2bfloat16( __bfloat162float(x) * __bfloat162float(y) );
134
+ #else
135
+ return __hmul(x, y);
136
+ #endif
137
+ }
138
+
139
+ inline __device__ __nv_bfloat162 bf16hfma2(const __nv_bfloat162 x, const __nv_bfloat162 y, const __nv_bfloat162 z) {
140
+ #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
141
+ float fxl, fxh, fyl, fyh, fzl, fzh;
142
+ fxl = __low2float(x);
143
+ fxh = __high2float(x);
144
+ fyl = __low2float(y);
145
+ fyh = __high2float(y);
146
+ fzl = __low2float(z);
147
+ fzh = __high2float(z);
148
+ return __floats2bfloat162_rn(fxl * fyl + fzl, fxh * fyh + fzh);
149
+ #else
150
+ return __hfma2(x, y, z);
151
+ #endif
152
+ }
153
+
154
+ inline __device__ __nv_bfloat16 bf16hfma(const __nv_bfloat16 x, const __nv_bfloat16 y, const __nv_bfloat16 z) {
155
+ #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
156
+ return __float2bfloat16( __bfloat162float(x) * __bfloat162float(y) + __bfloat162float(z));
157
+ #else
158
+ return __hfma(x, y, z);
159
+ #endif
160
+ }
161
+
162
+ inline __device__ __nv_bfloat162 bf16exp2(const __nv_bfloat162 x) {
163
+ #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
164
+ float fxl, fxh;
165
+ fxl = __low2float(x);
166
+ fxh = __high2float(x);;
167
+ return __floats2bfloat162_rn(expf(fxl), expf(fxh));
168
+ #else
169
+ return h2exp(x);
170
+ #endif
171
+ }
172
+
173
+ #if defined(__CUDA_ARCH__) && (__CUDA_ARCH__ < 800)
174
+ inline __device__ __nv_bfloat162 operator*(const __nv_bfloat162 x, const __nv_bfloat162 y) { return bf16hmul2(x, y); };
175
+ inline __device__ __nv_bfloat162 operator+(const __nv_bfloat162 x, const __nv_bfloat162 y) { return bf16hadd2(x, y); };
176
+
177
+ inline __device__ __nv_bfloat162 make_bfloat162(const __nv_bfloat16 x, const __nv_bfloat16 y)
178
+ {
179
+ __nv_bfloat162 t; t.x = x; t.y = y; return t;
180
+ }
181
+
182
+ #endif
183
+
184
+ inline __device__ __nv_bfloat16 bf16hadd(__nv_bfloat16 a, __nv_bfloat16 b, __nv_bfloat16 c) {
185
+ #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
186
+ return __float2bfloat16(__bfloat162float(a) + __bfloat162float(b) + __bfloat162float(c));
187
+ #else
188
+ return a + b + c;
189
+ #endif
190
+ }
191
+
192
+ inline __device__ __nv_bfloat16 bf16hadd(__nv_bfloat16 a, __nv_bfloat16 b, __nv_bfloat16 c, __nv_bfloat16 d) {
193
+ #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
194
+ return __float2bfloat16(__bfloat162float(a) + __bfloat162float(b) + __bfloat162float(c) + __bfloat162float(d));
195
+ #else
196
+ return (__nv_bfloat16)((float)a + (float)b + (float)c + (float)d);
197
+ #endif
198
+ }
199
+
200
+ inline __device__ __nv_bfloat162 bf16hadd2(__nv_bfloat162 a, __nv_bfloat162 b, __nv_bfloat162 c) {
201
+ #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
202
+ float fal, fah, fbl, fbh, fcl, fch;
203
+ fal = __low2float(a);
204
+ fah = __high2float(a);
205
+ fbl = __low2float(b);
206
+ fbh = __high2float(b);
207
+ fcl = __low2float(c);
208
+ fch = __high2float(c);
209
+ return __floats2bfloat162_rn(fal + fbl + fcl, fah + fbh + fch);
210
+ #else
211
+ return a + b + c;
212
+ #endif
213
+ }
214
+
215
+ inline __device__ __nv_bfloat16 bf16hmul(__nv_bfloat16 a, __nv_bfloat16 b, __nv_bfloat16 c) {
216
+ #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
217
+ return __float2bfloat16(__bfloat162float(a) * __bfloat162float(b) * __bfloat162float(c));
218
+ #else
219
+ return a * b * c;
220
+ #endif
221
+ }
222
+
223
+ inline __device__ __nv_bfloat162 bf16hmul2(__nv_bfloat162 a, __nv_bfloat162 b, __nv_bfloat162 c) {
224
+ #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
225
+ float fal, fah, fbl, fbh, fcl, fch;
226
+ fal = __low2float(a);
227
+ fah = __high2float(a);
228
+ fbl = __low2float(b);
229
+ fbh = __high2float(b);
230
+ fcl = __low2float(c);
231
+ fch = __high2float(c);
232
+ return __floats2bfloat162_rn(fal * fbl * fcl, fah * fbh * fch);
233
+ #else
234
+ return a * b * c;
235
+ #endif
236
+ }
237
+
238
+ inline __device__ __nv_bfloat162 bf16hfma2(__nv_bfloat162 a, __nv_bfloat162 b, __nv_bfloat162 c, __nv_bfloat162 d) {
239
+ #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 800
240
+ float fal, fah, fbl, fbh, fcl, fch, fdl, fdh;
241
+ fal = __low2float(a);
242
+ fah = __high2float(a);
243
+ fbl = __low2float(b);
244
+ fbh = __high2float(b);
245
+ fcl = __low2float(c);
246
+ fch = __high2float(c);
247
+ fdl = __low2float(d);
248
+ fdh = __high2float(d);
249
+ return __floats2bfloat162_rn(fal * fbl * fcl + fdl, fah * fbh * fch + fdh);
250
+ #else
251
+ return a * b * c + d;
252
+ #endif
253
+ }
254
+
255
+ #endif // ENABLE_BF16
256
+
257
+ } // namespace fastertransformer
llm-awq/awq/kernels/csrc/attention/cuda_bf16_wrapper.h ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Downloaded from from FasterTransformer v5.2.1
2
+ // https://github.com/NVIDIA/FasterTransformer/blob/release/v5.2.1_tag/src/fastertransformer/utils/cuda_bf16_wrapper.h
3
+ /*
4
+ * Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ #pragma once
20
+
21
+ #ifdef ENABLE_BF16
22
+ #include <cuda_bf16.h>
23
+ #endif
llm-awq/awq/kernels/csrc/attention/decoder_masked_multihead_attention.cu ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Adapted from from FasterTransformer v5.2.1
2
+ // https://github.com/NVIDIA/FasterTransformer/blob/release/v5.2.1_tag/src/fastertransformer/kernels/decoder_masked_multihead_attention/decoder_masked_multihead_attention_128.cu
3
+ /*
4
+ * Copyright (c) 2020-2022, NVIDIA CORPORATION. All rights reserved.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ #include "decoder_masked_multihead_attention.h"
20
+ #include "decoder_masked_multihead_attention_utils.h"
21
+ #include "cuda_bf16_wrapper.h"
22
+ #include <assert.h>
23
+ #include <float.h>
24
+ #include <type_traits>
25
+
26
+ #include "decoder_masked_multihead_attention_template.hpp"
27
+
28
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
29
+
30
+ #define MMHA_LAUNCH_KERNEL(T, Dh, Dh_MAX, THDS_PER_KEY, THDS_PER_VALUE, THDS_PER_BLOCK, DO_CROSS_ATTENTION, stream) \
31
+ size_t smem_sz = mmha::smem_size_in_bytes<T, DO_CROSS_ATTENTION>(params, THDS_PER_VALUE, THDS_PER_BLOCK); \
32
+ auto kernel = mmha::masked_multihead_attention_kernel<T, Dh, Dh_MAX, THDS_PER_KEY, THDS_PER_VALUE, \
33
+ THDS_PER_BLOCK, DO_CROSS_ATTENTION>; \
34
+ if (smem_sz >= 48 * 1024) { \
35
+ cudaFuncSetAttribute(kernel, cudaFuncAttributeMaxDynamicSharedMemorySize, smem_sz); \
36
+ } \
37
+ dim3 grid(params.num_heads, params.batch_size); \
38
+ kernel<<<grid, THDS_PER_BLOCK, smem_sz, stream>>>(params)
39
+
40
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
41
+
42
+ // !!! Specialize the launcher for Cross attention
43
+ template<typename T, int Dh, int Dh_MAX, typename KERNEL_PARAMS_TYPE>
44
+ void mmha_launch_kernel(const KERNEL_PARAMS_TYPE& params, const cudaStream_t& stream)
45
+ {
46
+ constexpr int THREADS_PER_VALUE = Dh_MAX * sizeof(T) / 16;
47
+ constexpr bool DO_CROSS_ATTENTION = std::is_same<KERNEL_PARAMS_TYPE, Cross_multihead_attention_params<T>>::value;
48
+ int tlength = (DO_CROSS_ATTENTION) ? params.memory_max_len : params.timestep;
49
+ // printf("tlength, CROSS_ATTENTION = %d, %d\n", tlength, DO_CROSS_ATTENTION);
50
+ if (tlength < 32) {
51
+ MMHA_LAUNCH_KERNEL(T, Dh, Dh_MAX, 4, THREADS_PER_VALUE, 64, DO_CROSS_ATTENTION, stream);
52
+ }
53
+ else if (tlength < 2048) {
54
+ MMHA_LAUNCH_KERNEL(T, Dh, Dh_MAX, 2, THREADS_PER_VALUE, 128, DO_CROSS_ATTENTION, stream);
55
+ }
56
+ else {
57
+ MMHA_LAUNCH_KERNEL(T, Dh, Dh_MAX, 1, THREADS_PER_VALUE, 256, DO_CROSS_ATTENTION, stream);
58
+ }
59
+ }
60
+
61
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
62
+
63
+ #undef MMHA_LAUNCH_KERNEL
64
+
65
+ template<typename T, typename KERNEL_PARAMS_TYPE>
66
+ void multihead_attention_(const KERNEL_PARAMS_TYPE& params, const cudaStream_t& stream)
67
+ {
68
+ switch (params.hidden_size_per_head) {
69
+ case 32:
70
+ mmha_launch_kernel<T, 32, 32, KERNEL_PARAMS_TYPE>(params, stream);
71
+ break;
72
+ case 48:
73
+ mmha_launch_kernel<T, 48, 64, KERNEL_PARAMS_TYPE>(params, stream);
74
+ break;
75
+ case 64:
76
+ mmha_launch_kernel<T, 64, 64, KERNEL_PARAMS_TYPE>(params, stream);
77
+ break;
78
+ case 80:
79
+ mmha_launch_kernel<T, 80, 128, KERNEL_PARAMS_TYPE>(params, stream);
80
+ break;
81
+ case 96:
82
+ mmha_launch_kernel<T, 96, 128, KERNEL_PARAMS_TYPE>(params, stream);
83
+ break;
84
+ case 112:
85
+ mmha_launch_kernel<T, 112, 128, KERNEL_PARAMS_TYPE>(params, stream);
86
+ break;
87
+ case 128:
88
+ mmha_launch_kernel<T, 128, 128, KERNEL_PARAMS_TYPE>(params, stream);
89
+ break;
90
+ case 160:
91
+ mmha_launch_kernel<T, 160, 256, KERNEL_PARAMS_TYPE>(params, stream);
92
+ break;
93
+ case 192:
94
+ mmha_launch_kernel<T, 192, 256, KERNEL_PARAMS_TYPE>(params, stream);
95
+ break;
96
+ case 224:
97
+ mmha_launch_kernel<T, 224, 256, KERNEL_PARAMS_TYPE>(params, stream);
98
+ break;
99
+ case 256:
100
+ mmha_launch_kernel<T, 256, 256, KERNEL_PARAMS_TYPE>(params, stream);
101
+ break;
102
+ default:
103
+ assert(false);
104
+ }
105
+ }
106
+
107
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
108
+
109
+ void masked_multihead_attention(const Masked_multihead_attention_params<float>& params, const cudaStream_t& stream)
110
+ {
111
+ multihead_attention_<float, Masked_multihead_attention_params<float>>(params, stream);
112
+ }
113
+
114
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
115
+
116
+ void masked_multihead_attention(const Masked_multihead_attention_params<uint16_t>& params, const cudaStream_t& stream)
117
+ {
118
+ multihead_attention_<uint16_t, Masked_multihead_attention_params<uint16_t>>(params, stream);
119
+ }
120
+
121
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
122
+
123
+ #ifdef ENABLE_BF16
124
+ void masked_multihead_attention(const Masked_multihead_attention_params<__nv_bfloat16>& params,
125
+ const cudaStream_t& stream)
126
+ {
127
+ multihead_attention_<__nv_bfloat16, Masked_multihead_attention_params<__nv_bfloat16>>(params, stream);
128
+ }
129
+ #endif
130
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
131
+
132
+ void cross_multihead_attention(const Cross_multihead_attention_params<float>& params, const cudaStream_t& stream)
133
+ {
134
+ multihead_attention_<float, Cross_multihead_attention_params<float>>(params, stream);
135
+ }
136
+
137
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
138
+
139
+ void cross_multihead_attention(const Cross_multihead_attention_params<uint16_t>& params, const cudaStream_t& stream)
140
+ {
141
+ multihead_attention_<uint16_t, Cross_multihead_attention_params<uint16_t>>(params, stream);
142
+ }
143
+
144
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
145
+
146
+ #ifdef ENABLE_BF16
147
+ void cross_multihead_attention(const Cross_multihead_attention_params<__nv_bfloat16>& params,
148
+ const cudaStream_t& stream)
149
+ {
150
+ multihead_attention_<__nv_bfloat16, Cross_multihead_attention_params<__nv_bfloat16>>(params, stream);
151
+ }
152
+ #endif
153
+
154
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
llm-awq/awq/kernels/csrc/attention/decoder_masked_multihead_attention_utils.h ADDED
@@ -0,0 +1,1795 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Downloaded from from FasterTransformer v5.2.1
2
+ // https://github.com/NVIDIA/FasterTransformer/blob/release/v5.2.1_tag/src/fastertransformer/kernels/decoder_masked_multihead_attention_utils.h
3
+ /*
4
+ * Copyright (c) 2020-2022, NVIDIA CORPORATION. All rights reserved.
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * you may not use this file except in compliance with the License.
8
+ * You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing, software
13
+ * distributed under the License is distributed on an "AS IS" BASIS,
14
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ * See the License for the specific language governing permissions and
16
+ * limitations under the License.
17
+ */
18
+
19
+ #pragma once
20
+
21
+ #include "cuda_bf16_wrapper.h"
22
+ #include "cuda_bf16_fallbacks.cuh"
23
+ #include <stdint.h>
24
+
25
+ using namespace fastertransformer;
26
+
27
+ namespace mmha {
28
+
29
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
30
+
31
+ struct Float8_ {
32
+ float2 x;
33
+ float2 y;
34
+ float2 z;
35
+ float2 w;
36
+ };
37
+
38
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
39
+
40
+ struct Float4_ {
41
+ float2 x;
42
+ float2 y;
43
+ };
44
+
45
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
46
+
47
+ #ifdef ENABLE_BF16
48
+ struct bf16_4_t {
49
+ __nv_bfloat162 x;
50
+ __nv_bfloat162 y;
51
+ };
52
+
53
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
54
+
55
+ struct bf16_8_t {
56
+ __nv_bfloat162 x;
57
+ __nv_bfloat162 y;
58
+ __nv_bfloat162 z;
59
+ __nv_bfloat162 w;
60
+ };
61
+ #endif
62
+
63
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
64
+
65
+ template<typename T>
66
+ struct num_elems;
67
+ template<>
68
+ struct num_elems<float> {
69
+ static constexpr int value = 1;
70
+ };
71
+ template<>
72
+ struct num_elems<float2> {
73
+ static constexpr int value = 2;
74
+ };
75
+ template<>
76
+ struct num_elems<float4> {
77
+ static constexpr int value = 4;
78
+ };
79
+ template<>
80
+ struct num_elems<Float4_> {
81
+ static constexpr int value = 4;
82
+ };
83
+ template<>
84
+ struct num_elems<Float8_> {
85
+ static constexpr int value = 8;
86
+ };
87
+
88
+ template<>
89
+ struct num_elems<uint32_t> {
90
+ static constexpr int value = 2;
91
+ };
92
+ template<>
93
+ struct num_elems<uint2> {
94
+ static constexpr int value = 4;
95
+ };
96
+ template<>
97
+ struct num_elems<uint4> {
98
+ static constexpr int value = 8;
99
+ };
100
+
101
+ #ifdef ENABLE_BF16
102
+ template<>
103
+ struct num_elems<__nv_bfloat162> {
104
+ static constexpr int value = 2;
105
+ };
106
+ template<>
107
+ struct num_elems<bf16_4_t> {
108
+ static constexpr int value = 4;
109
+ };
110
+ template<>
111
+ struct num_elems<bf16_8_t> {
112
+ static constexpr int value = 8;
113
+ };
114
+ #endif
115
+
116
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
117
+
118
+ template<typename T, int N>
119
+ struct packed_type;
120
+ template<typename T>
121
+ struct packed_type<T, 1> {
122
+ using type = T;
123
+ };
124
+ template<>
125
+ struct packed_type<int8_t, 2> {
126
+ using type = int16_t;
127
+ };
128
+ template<>
129
+ struct packed_type<int8_t, 4> {
130
+ using type = int32_t;
131
+ };
132
+ template<>
133
+ struct packed_type<int8_t, 8> {
134
+ using type = int64_t;
135
+ };
136
+
137
+ template<>
138
+ struct packed_type<float, 2> {
139
+ using type = float2;
140
+ };
141
+ template<>
142
+ struct packed_type<float, 4> {
143
+ using type = float4;
144
+ };
145
+ template<>
146
+ struct packed_type<float, 8> {
147
+ using type = Float8_;
148
+ };
149
+
150
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
151
+
152
+ inline __device__ float add(float a, float b)
153
+ {
154
+ return a + b;
155
+ }
156
+
157
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
158
+
159
+ inline __device__ float2 add(float2 a, float2 b)
160
+ {
161
+ float2 c;
162
+ c.x = add(a.x, b.x);
163
+ c.y = add(a.y, b.y);
164
+ return c;
165
+ }
166
+
167
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
168
+
169
+ inline __device__ float4 add(float4 a, float4 b)
170
+ {
171
+ float4 c;
172
+ c.x = add(a.x, b.x);
173
+ c.y = add(a.y, b.y);
174
+ c.z = add(a.z, b.z);
175
+ c.w = add(a.w, b.w);
176
+ return c;
177
+ }
178
+
179
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
180
+
181
+ #ifdef ENABLE_BF16
182
+ inline __device__ __nv_bfloat16 add(__nv_bfloat16 a, __nv_bfloat16 b)
183
+ {
184
+ return a + b;
185
+ }
186
+
187
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
188
+
189
+ inline __device__ __nv_bfloat162 add(__nv_bfloat162 a, __nv_bfloat162 b)
190
+ {
191
+ return bf16hadd2(a, b);
192
+ }
193
+
194
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
195
+
196
+ inline __device__ bf16_4_t add(bf16_4_t a, bf16_4_t b)
197
+ {
198
+ bf16_4_t c;
199
+ c.x = add(a.x, b.x);
200
+ c.y = add(a.y, b.y);
201
+ return c;
202
+ }
203
+
204
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
205
+
206
+ inline __device__ bf16_8_t add(bf16_8_t a, bf16_8_t b)
207
+ {
208
+ bf16_8_t c;
209
+ c.x = add(a.x, b.x);
210
+ c.y = add(a.y, b.y);
211
+ c.z = add(a.z, b.z);
212
+ c.w = add(a.w, b.w);
213
+ return c;
214
+ }
215
+ #endif // ENABLE_BF16
216
+
217
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
218
+
219
+ inline __device__ uint16_t add(uint16_t a, uint16_t b)
220
+ {
221
+ uint16_t c;
222
+ asm volatile("add.f16 %0, %1, %2;\n" : "=h"(c) : "h"(a), "h"(b));
223
+ return c;
224
+ }
225
+
226
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
227
+
228
+ inline __device__ uint32_t add(uint32_t a, uint32_t b)
229
+ {
230
+ uint32_t c;
231
+ asm volatile("add.f16x2 %0, %1, %2;\n" : "=r"(c) : "r"(a), "r"(b));
232
+ return c;
233
+ }
234
+
235
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
236
+
237
+ inline __device__ uint2 add(uint2 a, uint2 b)
238
+ {
239
+ uint2 c;
240
+ c.x = add(a.x, b.x);
241
+ c.y = add(a.y, b.y);
242
+ return c;
243
+ }
244
+
245
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
246
+
247
+ inline __device__ uint4 add(uint4 a, uint4 b)
248
+ {
249
+ uint4 c;
250
+ c.x = add(a.x, b.x);
251
+ c.y = add(a.y, b.y);
252
+ c.z = add(a.z, b.z);
253
+ c.w = add(a.w, b.w);
254
+ return c;
255
+ }
256
+
257
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
258
+
259
+ inline __device__ uint16_t float_to_half(float f)
260
+ {
261
+ union {
262
+ uint32_t u32;
263
+ uint16_t u16[2];
264
+ } tmp;
265
+ #if 0 && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 800 // Is it better?
266
+ float zero = 0.f;
267
+ asm volatile("cvt.rn.f16x2.f32 %0, %1, %2;\n" : "=r"(tmp.u32) : "f"(zero), "f"(f));
268
+ #else
269
+ asm volatile("cvt.rn.f16.f32 %0, %1;\n" : "=h"(tmp.u16[0]) : "f"(f));
270
+ #endif
271
+ return tmp.u16[0];
272
+ }
273
+
274
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
275
+
276
+ inline __device__ uint32_t float2_to_half2(float2 f)
277
+ {
278
+ union {
279
+ uint32_t u32;
280
+ uint16_t u16[2];
281
+ } tmp;
282
+ #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 800
283
+ asm volatile("cvt.rn.f16x2.f32 %0, %1, %2;\n" : "=r"(tmp.u32) : "f"(f.y), "f"(f.x));
284
+ #else
285
+ asm volatile("cvt.rn.f16.f32 %0, %1;\n" : "=h"(tmp.u16[0]) : "f"(f.x));
286
+ asm volatile("cvt.rn.f16.f32 %0, %1;\n" : "=h"(tmp.u16[1]) : "f"(f.y));
287
+ #endif
288
+ return tmp.u32;
289
+ }
290
+
291
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
292
+
293
+ inline __device__ float half_to_float(uint16_t h)
294
+ {
295
+ float f;
296
+ asm volatile("cvt.f32.f16 %0, %1;\n" : "=f"(f) : "h"(h));
297
+ return f;
298
+ }
299
+
300
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
301
+
302
+ inline __device__ float2 half2_to_float2(uint32_t v)
303
+ {
304
+ uint16_t lo, hi;
305
+ asm volatile("mov.b32 {%0, %1}, %2;\n" : "=h"(lo), "=h"(hi) : "r"(v));
306
+ return make_float2(half_to_float(lo), half_to_float(hi));
307
+ }
308
+
309
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
310
+
311
+ inline __device__ float add(float a, uint16_t b)
312
+ {
313
+ return a + half_to_float(b);
314
+ }
315
+
316
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
317
+
318
+ #ifdef ENABLE_BF16
319
+ inline __device__ float add(float a, __nv_bfloat16 b)
320
+ {
321
+ return a + __bfloat162float(b);
322
+ }
323
+ #endif
324
+
325
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
326
+
327
+ inline __device__ float2 add(uint32_t a, float2 fb)
328
+ {
329
+ float2 fa = half2_to_float2(a);
330
+ return add(fa, fb);
331
+ }
332
+
333
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
334
+
335
+ inline __device__ Float4_ add(uint2 a, Float4_ fb)
336
+ {
337
+ Float4_ fc;
338
+ fc.x = add(a.x, fb.x);
339
+ fc.y = add(a.y, fb.y);
340
+ return fc;
341
+ }
342
+
343
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
344
+
345
+ inline __device__ Float8_ add(uint4 a, Float8_ fb)
346
+ {
347
+ Float8_ fc;
348
+ fc.x = add(a.x, fb.x);
349
+ fc.y = add(a.y, fb.y);
350
+ fc.z = add(a.z, fb.z);
351
+ fc.w = add(a.w, fb.w);
352
+ return fc;
353
+ }
354
+
355
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
356
+
357
+ inline __device__ uint32_t h0_h0(uint16_t a)
358
+ {
359
+ uint32_t b;
360
+ asm volatile("mov.b32 %0, {%1, %1};" : "=r"(b) : "h"(a));
361
+ return b;
362
+ }
363
+
364
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
365
+
366
+ inline __device__ float fma(float a, float b, float c)
367
+ {
368
+ return a * b + c;
369
+ }
370
+
371
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
372
+
373
+ inline __device__ float2 fma(float2 a, float2 b, float2 c)
374
+ {
375
+ float2 d;
376
+ d.x = fma(a.x, b.x, c.x);
377
+ d.y = fma(a.y, b.y, c.y);
378
+ return d;
379
+ }
380
+
381
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
382
+
383
+ inline __device__ float2 fma(float a, float2 b, float2 c)
384
+ {
385
+ float2 d;
386
+ d.x = fma(a, b.x, c.x);
387
+ d.y = fma(a, b.y, c.y);
388
+ return d;
389
+ }
390
+
391
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
392
+
393
+ inline __device__ float4 fma(float4 a, float4 b, float4 c)
394
+ {
395
+ float4 d;
396
+ d.x = fma(a.x, b.x, c.x);
397
+ d.y = fma(a.y, b.y, c.y);
398
+ d.z = fma(a.z, b.z, c.z);
399
+ d.w = fma(a.w, b.w, c.w);
400
+ return d;
401
+ }
402
+
403
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
404
+
405
+ inline __device__ float4 fma(float a, float4 b, float4 c)
406
+ {
407
+ float4 d;
408
+ d.x = fma(a, b.x, c.x);
409
+ d.y = fma(a, b.y, c.y);
410
+ d.z = fma(a, b.z, c.z);
411
+ d.w = fma(a, b.w, c.w);
412
+ return d;
413
+ }
414
+
415
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
416
+
417
+ inline __device__ Float4_ fma(float a, Float4_ b, Float4_ c)
418
+ {
419
+ Float4_ d;
420
+ d.x = fma(a, b.x, c.x);
421
+ d.y = fma(a, b.y, c.y);
422
+ return d;
423
+ }
424
+
425
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
426
+
427
+ inline __device__ Float8_ fma(float a, Float8_ b, Float8_ c)
428
+ {
429
+ Float8_ d;
430
+ d.x = fma(a, b.x, c.x);
431
+ d.y = fma(a, b.y, c.y);
432
+ d.z = fma(a, b.z, c.z);
433
+ d.w = fma(a, b.w, c.w);
434
+ return d;
435
+ }
436
+
437
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
438
+
439
+ #ifdef ENABLE_BF16
440
+ inline __device__ float2 add(__nv_bfloat162 a, float2 fb)
441
+ {
442
+ float2 fa = bf1622float2(a);
443
+ return add(fa, fb);
444
+ }
445
+
446
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
447
+
448
+ inline __device__ Float4_ add(bf16_4_t a, Float4_ fb)
449
+ {
450
+ Float4_ fc;
451
+ fc.x = add(a.x, fb.x);
452
+ fc.y = add(a.y, fb.y);
453
+ return fc;
454
+ }
455
+
456
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
457
+
458
+ inline __device__ Float8_ add(bf16_8_t a, Float8_ fb)
459
+ {
460
+ Float8_ fc;
461
+ fc.x = add(a.x, fb.x);
462
+ fc.y = add(a.y, fb.y);
463
+ fc.z = add(a.z, fb.z);
464
+ fc.w = add(a.w, fb.w);
465
+ return fc;
466
+ }
467
+ #endif // ENABLE_BF16
468
+
469
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
470
+
471
+ inline __device__ uint32_t fma(uint32_t a, uint32_t b, uint32_t c)
472
+ {
473
+ uint32_t d;
474
+ asm volatile("fma.rn.f16x2 %0, %1, %2, %3;\n" : "=r"(d) : "r"(a), "r"(b), "r"(c));
475
+ return d;
476
+ }
477
+
478
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
479
+
480
+ inline __device__ uint32_t fma(uint16_t a, uint32_t b, uint32_t c)
481
+ {
482
+ return fma(h0_h0(a), b, c);
483
+ }
484
+
485
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
486
+
487
+ inline __device__ uint2 fma(uint2 a, uint2 b, uint2 c)
488
+ {
489
+ uint2 d;
490
+ d.x = fma(a.x, b.x, c.x);
491
+ d.y = fma(a.y, b.y, c.y);
492
+ return d;
493
+ }
494
+
495
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
496
+
497
+ inline __device__ uint2 fma(uint16_t a, uint2 b, uint2 c)
498
+ {
499
+ uint32_t s = h0_h0(a);
500
+ uint2 d;
501
+ d.x = fma(s, b.x, c.x);
502
+ d.y = fma(s, b.y, c.y);
503
+ return d;
504
+ }
505
+
506
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
507
+
508
+ inline __device__ uint4 fma(uint4 a, uint4 b, uint4 c)
509
+ {
510
+ uint4 d;
511
+ d.x = fma(a.x, b.x, c.x);
512
+ d.y = fma(a.y, b.y, c.y);
513
+ d.z = fma(a.z, b.z, c.z);
514
+ d.w = fma(a.w, b.w, c.w);
515
+ return d;
516
+ }
517
+
518
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
519
+
520
+ inline __device__ uint4 fma(uint16_t a, uint4 b, uint4 c)
521
+ {
522
+ uint32_t s = h0_h0(a);
523
+ uint4 d;
524
+ d.x = fma(s, b.x, c.x);
525
+ d.y = fma(s, b.y, c.y);
526
+ d.z = fma(s, b.z, c.z);
527
+ d.w = fma(s, b.w, c.w);
528
+ return d;
529
+ }
530
+
531
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
532
+
533
+ inline __device__ float fma(uint16_t a, uint16_t b, float fc)
534
+ {
535
+ float fa = half_to_float(a);
536
+ float fb = half_to_float(b);
537
+ return fa * fb + fc;
538
+ }
539
+
540
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
541
+
542
+ inline __device__ float2 fma(uint32_t a, uint32_t b, float2 fc)
543
+ {
544
+ float2 fa = half2_to_float2(a);
545
+ float2 fb = half2_to_float2(b);
546
+ return fma(fa, fb, fc);
547
+ }
548
+
549
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
550
+
551
+ inline __device__ float2 fma(uint16_t a, uint32_t b, float2 fc)
552
+ {
553
+ return fma(h0_h0(a), b, fc);
554
+ }
555
+
556
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
557
+
558
+ inline __device__ Float4_ fma(uint2 a, uint2 b, Float4_ fc)
559
+ {
560
+ Float4_ fd;
561
+ fd.x = fma(a.x, b.x, fc.x);
562
+ fd.y = fma(a.y, b.y, fc.y);
563
+ return fd;
564
+ }
565
+
566
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
567
+
568
+ inline __device__ Float4_ fma(uint16_t a, uint2 b, Float4_ fc)
569
+ {
570
+ uint32_t s = h0_h0(a);
571
+ Float4_ fd;
572
+ fd.x = fma(s, b.x, fc.x);
573
+ fd.y = fma(s, b.y, fc.y);
574
+ return fd;
575
+ }
576
+
577
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
578
+
579
+ inline __device__ Float8_ fma(uint4 a, uint4 b, Float8_ fc)
580
+ {
581
+ Float8_ fd;
582
+ fd.x = fma(a.x, b.x, fc.x);
583
+ fd.y = fma(a.y, b.y, fc.y);
584
+ fd.z = fma(a.z, b.z, fc.z);
585
+ fd.w = fma(a.w, b.w, fc.w);
586
+ return fd;
587
+ }
588
+
589
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
590
+
591
+ inline __device__ Float8_ fma(uint16_t a, uint4 b, Float8_ fc)
592
+ {
593
+ uint32_t s = h0_h0(a);
594
+ Float8_ fd;
595
+ fd.x = fma(s, b.x, fc.x);
596
+ fd.y = fma(s, b.y, fc.y);
597
+ fd.z = fma(s, b.z, fc.z);
598
+ fd.w = fma(s, b.w, fc.w);
599
+ return fd;
600
+ }
601
+
602
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
603
+ #ifdef ENABLE_BF16
604
+ inline __device__ __nv_bfloat162 fma(__nv_bfloat162 a, __nv_bfloat162 b, __nv_bfloat162 c)
605
+ {
606
+ return bf16hfma2(a, b, c);
607
+ }
608
+
609
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
610
+
611
+ inline __device__ __nv_bfloat162 fma(__nv_bfloat16 a, __nv_bfloat162 b, __nv_bfloat162 c)
612
+ {
613
+ return bf16hfma2(bf162bf162(a), b, c);
614
+ }
615
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
616
+
617
+ inline __device__ bf16_4_t fma(bf16_4_t a, bf16_4_t b, bf16_4_t c)
618
+ {
619
+ bf16_4_t d;
620
+ d.x = fma(a.x, b.x, c.x);
621
+ d.y = fma(a.y, b.y, c.y);
622
+ return d;
623
+ }
624
+
625
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
626
+
627
+ inline __device__ bf16_4_t fma(__nv_bfloat16 a, bf16_4_t b, bf16_4_t c)
628
+ {
629
+ __nv_bfloat162 s = bf162bf162(a);
630
+ bf16_4_t d;
631
+ d.x = fma(s, b.x, c.x);
632
+ d.y = fma(s, b.y, c.y);
633
+ return d;
634
+ }
635
+
636
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
637
+
638
+ inline __device__ bf16_8_t fma(bf16_8_t a, bf16_8_t b, bf16_8_t c)
639
+ {
640
+ bf16_8_t d;
641
+ d.x = fma(a.x, b.x, c.x);
642
+ d.y = fma(a.y, b.y, c.y);
643
+ d.z = fma(a.z, b.z, c.z);
644
+ d.w = fma(a.w, b.w, c.w);
645
+ return d;
646
+ }
647
+
648
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
649
+
650
+ inline __device__ bf16_8_t fma(__nv_bfloat16 a, bf16_8_t b, bf16_8_t c)
651
+ {
652
+ __nv_bfloat162 s = bf162bf162(a);
653
+ bf16_8_t d;
654
+ d.x = fma(s, b.x, c.x);
655
+ d.y = fma(s, b.y, c.y);
656
+ d.z = fma(s, b.z, c.z);
657
+ d.w = fma(s, b.w, c.w);
658
+ return d;
659
+ }
660
+
661
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
662
+
663
+ inline __device__ float fma(__nv_bfloat16 a, __nv_bfloat16 b, float fc)
664
+ {
665
+ return __bfloat162float(a) * __bfloat162float(b) + fc;
666
+ }
667
+
668
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
669
+
670
+ inline __device__ float2 fma(__nv_bfloat162 a, __nv_bfloat162 b, float2 fc)
671
+ {
672
+ float2 fa = bf1622float2(a);
673
+ float2 fb = bf1622float2(b);
674
+ return fma(fa, fb, fc);
675
+ }
676
+
677
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
678
+
679
+ inline __device__ float2 fma(__nv_bfloat16 a, __nv_bfloat162 b, float2 fc)
680
+ {
681
+ return fma(bf162bf162(a), b, fc);
682
+ }
683
+
684
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
685
+
686
+ inline __device__ Float4_ fma(bf16_4_t a, bf16_4_t b, Float4_ fc)
687
+ {
688
+ Float4_ fd;
689
+ fd.x = fma(a.x, b.x, fc.x);
690
+ fd.y = fma(a.y, b.y, fc.y);
691
+ return fd;
692
+ }
693
+
694
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
695
+
696
+ inline __device__ Float4_ fma(__nv_bfloat16 a, bf16_4_t b, Float4_ fc)
697
+ {
698
+ __nv_bfloat162 s = bf162bf162(a);
699
+ Float4_ fd;
700
+ fd.x = fma(s, b.x, fc.x);
701
+ fd.y = fma(s, b.y, fc.y);
702
+ return fd;
703
+ }
704
+
705
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
706
+
707
+ inline __device__ Float8_ fma(bf16_8_t a, bf16_8_t b, Float8_ fc)
708
+ {
709
+ Float8_ fd;
710
+ fd.x = fma(a.x, b.x, fc.x);
711
+ fd.y = fma(a.y, b.y, fc.y);
712
+ fd.z = fma(a.z, b.z, fc.z);
713
+ fd.w = fma(a.w, b.w, fc.w);
714
+ return fd;
715
+ }
716
+
717
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
718
+
719
+ inline __device__ Float8_ fma(__nv_bfloat16 a, bf16_8_t b, Float8_ fc)
720
+ {
721
+ __nv_bfloat162 s = bf162bf162(a);
722
+ Float8_ fd;
723
+ fd.x = fma(s, b.x, fc.x);
724
+ fd.y = fma(s, b.y, fc.y);
725
+ fd.z = fma(s, b.z, fc.z);
726
+ fd.w = fma(s, b.w, fc.w);
727
+ return fd;
728
+ }
729
+ #endif // ENABLE_BF16
730
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
731
+
732
+ template<typename Acc, typename A, typename B>
733
+ inline __device__ Acc mul(A a, B b)
734
+ {
735
+ return a * b;
736
+ }
737
+
738
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
739
+
740
+ template<>
741
+ inline __device__ float mul<float, float>(float a, float b)
742
+ {
743
+ return a * b;
744
+ }
745
+
746
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
747
+
748
+ template<>
749
+ inline __device__ float2 mul(float2 a, float2 b)
750
+ {
751
+ float2 c;
752
+ c.x = a.x * b.x;
753
+ c.y = a.y * b.y;
754
+ return c;
755
+ }
756
+
757
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
758
+
759
+ template<>
760
+ inline __device__ float2 mul(float a, float2 b)
761
+ {
762
+ float2 c;
763
+ c.x = a * b.x;
764
+ c.y = a * b.y;
765
+ return c;
766
+ }
767
+
768
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
769
+
770
+ template<>
771
+ inline __device__ float4 mul(float4 a, float4 b)
772
+ {
773
+ float4 c;
774
+ c.x = a.x * b.x;
775
+ c.y = a.y * b.y;
776
+ c.z = a.z * b.z;
777
+ c.w = a.w * b.w;
778
+ return c;
779
+ }
780
+
781
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
782
+
783
+ template<>
784
+ inline __device__ float4 mul(float a, float4 b)
785
+ {
786
+ float4 c;
787
+ c.x = a * b.x;
788
+ c.y = a * b.y;
789
+ c.z = a * b.z;
790
+ c.w = a * b.w;
791
+ return c;
792
+ }
793
+
794
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
795
+
796
+ template<>
797
+ inline __device__ Float8_ mul(float a, Float8_ b)
798
+ {
799
+ Float8_ c;
800
+ c.x = make_float2(a * b.x.x, a * b.x.y);
801
+ c.y = make_float2(a * b.y.x, a * b.y.y);
802
+ c.z = make_float2(a * b.z.x, a * b.z.y);
803
+ c.w = make_float2(a * b.w.x, a * b.w.y);
804
+ return c;
805
+ }
806
+
807
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
808
+
809
+ template<>
810
+ inline __device__ uint16_t mul(uint16_t a, uint16_t b)
811
+ {
812
+ uint16_t c;
813
+ asm volatile("mul.f16 %0, %1, %2;\n" : "=h"(c) : "h"(a), "h"(b));
814
+ return c;
815
+ }
816
+
817
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
818
+
819
+ template<>
820
+ inline __device__ uint32_t mul(uint32_t a, uint32_t b)
821
+ {
822
+ uint32_t c;
823
+ asm volatile("mul.f16x2 %0, %1, %2;\n" : "=r"(c) : "r"(a), "r"(b));
824
+ return c;
825
+ }
826
+
827
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
828
+
829
+ template<>
830
+ inline __device__ uint32_t mul(uint16_t a, uint32_t b)
831
+ {
832
+ return mul<uint32_t, uint32_t, uint32_t>(h0_h0(a), b);
833
+ }
834
+
835
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
836
+
837
+ template<>
838
+ inline __device__ uint2 mul(uint2 a, uint2 b)
839
+ {
840
+ uint2 c;
841
+ c.x = mul<uint32_t, uint32_t, uint32_t>(a.x, b.x);
842
+ c.y = mul<uint32_t, uint32_t, uint32_t>(a.y, b.y);
843
+ return c;
844
+ }
845
+
846
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
847
+
848
+ template<>
849
+ inline __device__ uint2 mul(uint16_t a, uint2 b)
850
+ {
851
+ uint32_t s = h0_h0(a);
852
+ uint2 c;
853
+ c.x = mul<uint32_t, uint32_t, uint32_t>(s, b.x);
854
+ c.y = mul<uint32_t, uint32_t, uint32_t>(s, b.y);
855
+ return c;
856
+ }
857
+
858
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
859
+
860
+ template<>
861
+ inline __device__ uint4 mul(uint4 a, uint4 b)
862
+ {
863
+ uint4 c;
864
+ c.x = mul<uint32_t, uint32_t, uint32_t>(a.x, b.x);
865
+ c.y = mul<uint32_t, uint32_t, uint32_t>(a.y, b.y);
866
+ c.z = mul<uint32_t, uint32_t, uint32_t>(a.z, b.z);
867
+ c.w = mul<uint32_t, uint32_t, uint32_t>(a.w, b.w);
868
+ return c;
869
+ }
870
+
871
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
872
+
873
+ template<>
874
+ inline __device__ uint4 mul(uint16_t a, uint4 b)
875
+ {
876
+ uint32_t s = h0_h0(a);
877
+ uint4 c;
878
+ c.x = mul<uint32_t, uint32_t, uint32_t>(s, b.x);
879
+ c.y = mul<uint32_t, uint32_t, uint32_t>(s, b.y);
880
+ c.z = mul<uint32_t, uint32_t, uint32_t>(s, b.z);
881
+ c.w = mul<uint32_t, uint32_t, uint32_t>(s, b.w);
882
+ return c;
883
+ }
884
+
885
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
886
+
887
+ template<>
888
+ inline __device__ float mul(uint16_t a, uint16_t b)
889
+ {
890
+ float fa = half_to_float(a);
891
+ float fb = half_to_float(b);
892
+ return fa * fb;
893
+ }
894
+
895
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
896
+
897
+ template<>
898
+ inline __device__ float mul(uint16_t a, float b)
899
+ {
900
+ return half_to_float(a) * b;
901
+ }
902
+
903
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
904
+
905
+ template<>
906
+ inline __device__ float2 mul(uint32_t a, uint32_t b)
907
+ {
908
+ float2 fa = half2_to_float2(a);
909
+ float2 fb = half2_to_float2(b);
910
+ return mul<float2, float2, float2>(fa, fb);
911
+ }
912
+
913
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
914
+
915
+ template<>
916
+ inline __device__ float2 mul(uint16_t a, uint32_t b)
917
+ {
918
+ return mul<float2, uint32_t, uint32_t>(h0_h0(a), b);
919
+ }
920
+
921
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
922
+
923
+ template<>
924
+ inline __device__ Float4_ mul(uint2 a, uint2 b)
925
+ {
926
+ Float4_ fc;
927
+ fc.x = mul<float2, uint32_t, uint32_t>(a.x, b.x);
928
+ fc.y = mul<float2, uint32_t, uint32_t>(a.y, b.y);
929
+ return fc;
930
+ }
931
+
932
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
933
+
934
+ template<>
935
+ inline __device__ Float4_ mul(uint16_t a, uint2 b)
936
+ {
937
+ uint32_t s = h0_h0(a);
938
+ Float4_ fc;
939
+ fc.x = mul<float2, uint32_t, uint32_t>(s, b.x);
940
+ fc.y = mul<float2, uint32_t, uint32_t>(s, b.y);
941
+ return fc;
942
+ }
943
+
944
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
945
+
946
+ template<>
947
+ inline __device__ Float8_ mul(uint4 a, uint4 b)
948
+ {
949
+ Float8_ fc;
950
+ fc.x = mul<float2, uint32_t, uint32_t>(a.x, b.x);
951
+ fc.y = mul<float2, uint32_t, uint32_t>(a.y, b.y);
952
+ fc.z = mul<float2, uint32_t, uint32_t>(a.z, b.z);
953
+ fc.w = mul<float2, uint32_t, uint32_t>(a.w, b.w);
954
+ return fc;
955
+ }
956
+
957
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
958
+
959
+ template<>
960
+ inline __device__ Float8_ mul(uint16_t a, uint4 b)
961
+ {
962
+ uint32_t s = h0_h0(a);
963
+ Float8_ fc;
964
+ fc.x = mul<float2, uint32_t, uint32_t>(s, b.x);
965
+ fc.y = mul<float2, uint32_t, uint32_t>(s, b.y);
966
+ fc.z = mul<float2, uint32_t, uint32_t>(s, b.z);
967
+ fc.w = mul<float2, uint32_t, uint32_t>(s, b.w);
968
+ return fc;
969
+ }
970
+
971
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
972
+
973
+ #ifdef ENABLE_BF16
974
+ template<>
975
+ inline __device__ __nv_bfloat16 mul(__nv_bfloat16 a, __nv_bfloat16 b)
976
+ {
977
+ #if defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= 800
978
+ return __hmul(a, b);
979
+ #else
980
+ return bf16hmul(a, b);
981
+ #endif
982
+ }
983
+
984
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
985
+
986
+ template<>
987
+ inline __device__ __nv_bfloat162 mul(__nv_bfloat162 a, __nv_bfloat162 b)
988
+ {
989
+ return bf16hmul2(a, b);
990
+ }
991
+
992
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
993
+
994
+ template<>
995
+ inline __device__ __nv_bfloat162 mul(__nv_bfloat16 a, __nv_bfloat162 b)
996
+ {
997
+ return mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(bf162bf162(a), b);
998
+ }
999
+
1000
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1001
+
1002
+ template<>
1003
+ inline __device__ bf16_4_t mul(bf16_4_t a, bf16_4_t b)
1004
+ {
1005
+ bf16_4_t c;
1006
+ c.x = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(a.x, b.x);
1007
+ c.y = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(a.y, b.y);
1008
+ return c;
1009
+ }
1010
+
1011
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1012
+
1013
+ template<>
1014
+ inline __device__ bf16_4_t mul(__nv_bfloat16 a, bf16_4_t b)
1015
+ {
1016
+ __nv_bfloat162 s = bf162bf162(a);
1017
+ bf16_4_t c;
1018
+ c.x = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(s, b.x);
1019
+ c.y = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(s, b.y);
1020
+ return c;
1021
+ }
1022
+
1023
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1024
+
1025
+ template<>
1026
+ inline __device__ bf16_8_t mul(bf16_8_t a, bf16_8_t b)
1027
+ {
1028
+ bf16_8_t c;
1029
+ c.x = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(a.x, b.x);
1030
+ c.y = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(a.y, b.y);
1031
+ c.z = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(a.z, b.z);
1032
+ c.w = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(a.w, b.w);
1033
+ return c;
1034
+ }
1035
+
1036
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1037
+
1038
+ template<>
1039
+ inline __device__ bf16_8_t mul(__nv_bfloat16 a, bf16_8_t b)
1040
+ {
1041
+ __nv_bfloat162 s = bf162bf162(a);
1042
+ bf16_8_t c;
1043
+ c.x = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(s, b.x);
1044
+ c.y = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(s, b.y);
1045
+ c.z = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(s, b.z);
1046
+ c.w = mul<__nv_bfloat162, __nv_bfloat162, __nv_bfloat162>(s, b.w);
1047
+ return c;
1048
+ }
1049
+
1050
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1051
+
1052
+ template<>
1053
+ inline __device__ float mul(__nv_bfloat16 a, __nv_bfloat16 b)
1054
+ {
1055
+ float fa = (float)a;
1056
+ float fb = (float)b;
1057
+ return fa * fb;
1058
+ }
1059
+
1060
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1061
+
1062
+ template<>
1063
+ inline __device__ float mul(__nv_bfloat16 a, float b)
1064
+ {
1065
+ return __bfloat162float(a) * b;
1066
+ }
1067
+
1068
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1069
+
1070
+ template<>
1071
+ inline __device__ float2 mul(__nv_bfloat162 a, __nv_bfloat162 b)
1072
+ {
1073
+ float2 fa = bf1622float2(a);
1074
+ float2 fb = bf1622float2(b);
1075
+ return mul<float2, float2, float2>(fa, fb);
1076
+ }
1077
+
1078
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1079
+
1080
+ template<>
1081
+ inline __device__ float2 mul(__nv_bfloat16 a, __nv_bfloat162 b)
1082
+ {
1083
+ return mul<float2, __nv_bfloat162, __nv_bfloat162>(bf162bf162(a), b);
1084
+ }
1085
+
1086
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1087
+
1088
+ template<>
1089
+ inline __device__ Float4_ mul(bf16_4_t a, bf16_4_t b)
1090
+ {
1091
+ Float4_ fc;
1092
+ fc.x = mul<float2, __nv_bfloat162, __nv_bfloat162>(a.x, b.x);
1093
+ fc.y = mul<float2, __nv_bfloat162, __nv_bfloat162>(a.y, b.y);
1094
+ return fc;
1095
+ }
1096
+
1097
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1098
+
1099
+ template<>
1100
+ inline __device__ Float4_ mul(__nv_bfloat16 a, bf16_4_t b)
1101
+ {
1102
+ __nv_bfloat162 s = bf162bf162(a);
1103
+ Float4_ fc;
1104
+ fc.x = mul<float2, __nv_bfloat162, __nv_bfloat162>(s, b.x);
1105
+ fc.y = mul<float2, __nv_bfloat162, __nv_bfloat162>(s, b.y);
1106
+ return fc;
1107
+ }
1108
+
1109
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1110
+
1111
+ template<>
1112
+ inline __device__ Float8_ mul(bf16_8_t a, bf16_8_t b)
1113
+ {
1114
+ Float8_ fc;
1115
+ fc.x = mul<float2, __nv_bfloat162, __nv_bfloat162>(a.x, b.x);
1116
+ fc.y = mul<float2, __nv_bfloat162, __nv_bfloat162>(a.y, b.y);
1117
+ fc.z = mul<float2, __nv_bfloat162, __nv_bfloat162>(a.z, b.z);
1118
+ fc.w = mul<float2, __nv_bfloat162, __nv_bfloat162>(a.w, b.w);
1119
+ return fc;
1120
+ }
1121
+
1122
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1123
+
1124
+ template<>
1125
+ inline __device__ Float8_ mul(__nv_bfloat16 a, bf16_8_t b)
1126
+ {
1127
+ __nv_bfloat162 s = bf162bf162(a);
1128
+ Float8_ fc;
1129
+ fc.x = mul<float2, __nv_bfloat162, __nv_bfloat162>(s, b.x);
1130
+ fc.y = mul<float2, __nv_bfloat162, __nv_bfloat162>(s, b.y);
1131
+ fc.z = mul<float2, __nv_bfloat162, __nv_bfloat162>(s, b.z);
1132
+ fc.w = mul<float2, __nv_bfloat162, __nv_bfloat162>(s, b.w);
1133
+ return fc;
1134
+ }
1135
+ #endif // ENABLE_BF16
1136
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1137
+
1138
+ inline __device__ float sum(float v)
1139
+ {
1140
+ return v;
1141
+ }
1142
+
1143
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1144
+
1145
+ inline __device__ float sum(float2 v)
1146
+ {
1147
+ return v.x + v.y;
1148
+ }
1149
+
1150
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1151
+
1152
+ inline __device__ float sum(float4 v)
1153
+ {
1154
+ return v.x + v.y + v.z + v.w;
1155
+ }
1156
+
1157
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1158
+
1159
+ #ifdef ENABLE_BF16
1160
+ inline __device__ float sum(__nv_bfloat162 v)
1161
+ {
1162
+ float2 vf = bf1622float2(v);
1163
+ return vf.x + vf.y;
1164
+ }
1165
+
1166
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1167
+
1168
+ inline __device__ float sum(bf16_4_t v)
1169
+ {
1170
+ return sum(v.x) + sum(v.y);
1171
+ }
1172
+
1173
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1174
+
1175
+ inline __device__ float sum(bf16_8_t v)
1176
+ {
1177
+ return sum(v.x) + sum(v.y) + sum(v.z) + sum(v.w);
1178
+ }
1179
+ #endif // ENABLE_BF16
1180
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1181
+
1182
+ inline __device__ float sum(uint16_t v)
1183
+ {
1184
+ return half_to_float(v);
1185
+ }
1186
+
1187
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1188
+
1189
+ inline __device__ float sum(uint32_t v)
1190
+ {
1191
+ float2 tmp = half2_to_float2(v);
1192
+ return tmp.x + tmp.y;
1193
+ }
1194
+
1195
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1196
+
1197
+ inline __device__ float sum(uint2 v)
1198
+ {
1199
+ uint32_t c = add(v.x, v.y);
1200
+ return sum(c);
1201
+ }
1202
+
1203
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1204
+
1205
+ inline __device__ float sum(uint4 v)
1206
+ {
1207
+ #if 1
1208
+ uint32_t c = add(v.x, v.y);
1209
+ c = add(c, v.z);
1210
+ c = add(c, v.w);
1211
+ #else
1212
+ uint32_t c = add(v.x, v.y);
1213
+ uint32_t d = add(v.z, v.w);
1214
+ c = add(c, d);
1215
+ #endif
1216
+ return sum(c);
1217
+ }
1218
+
1219
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1220
+
1221
+ inline __device__ float sum(Float4_ v)
1222
+ {
1223
+ return v.x.x + v.x.y + v.y.x + v.y.y;
1224
+ }
1225
+
1226
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1227
+
1228
+ inline __device__ float sum(Float8_ v)
1229
+ {
1230
+ return v.x.x + v.x.y + v.y.x + v.y.y + v.z.x + v.z.y + v.w.x + v.w.y;
1231
+ }
1232
+
1233
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1234
+
1235
+ template<typename T>
1236
+ inline __device__ float dot(T a, T b)
1237
+ {
1238
+ return sum(mul<T, T, T>(a, b));
1239
+ }
1240
+
1241
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1242
+
1243
+ template<typename A, typename T>
1244
+ inline __device__ float dot(T a, T b)
1245
+ {
1246
+ return sum(mul<A, T, T>(a, b));
1247
+ }
1248
+
1249
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1250
+
1251
+ inline __device__ void zero(uint16_t& dst)
1252
+ {
1253
+ dst = uint16_t(0);
1254
+ }
1255
+
1256
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1257
+
1258
+ template<typename T>
1259
+ inline __device__ void zero(T& dst)
1260
+ {
1261
+ constexpr int WORDS = sizeof(T) / 4;
1262
+ union {
1263
+ T raw;
1264
+ uint32_t words[WORDS];
1265
+ } tmp;
1266
+ #pragma unroll
1267
+ for (int ii = 0; ii < WORDS; ++ii) {
1268
+ tmp.words[ii] = 0u;
1269
+ }
1270
+ dst = tmp.raw;
1271
+ }
1272
+
1273
+ ////////////////////////////////////////////////////////////////////////////////////////////////////
1274
+
1275
+ // inline __device__ float2 rotary_embedding_coefficient(const int zid, const int rot_embed_dim, const float t_step, const float base)
1276
+ // {
1277
+ // const float inv_freq = t_step / pow(base, zid / (float)rot_embed_dim);
1278
+ // return {cos(inv_freq), sin(inv_freq)};
1279
+ // }
1280
+
1281
+ // with scale
1282
+ inline __device__ float2 rotary_embedding_coefficient(
1283
+ const int zid, const int rot_embed_dim, const float t_step, const float base, const float scale)
1284
+ {
1285
+ const float inv_freq = (t_step * scale) / pow(base, zid / (float)rot_embed_dim);
1286
+ return {cos(inv_freq), sin(inv_freq)};
1287
+ }
1288
+
1289
+
1290
+ inline __device__ float2 rotary_embedding_transform(const float2 v, const float2 coef)
1291
+ {
1292
+ float2 rot_v;
1293
+ rot_v.x = coef.x * v.x - coef.y * v.y;
1294
+ rot_v.y = coef.x * v.y + coef.y * v.x;
1295
+ return rot_v;
1296
+ }
1297
+
1298
+ inline __device__ uint32_t rotary_embedding_transform(const uint32_t v, const float2 coef)
1299
+ {
1300
+ float2 fv = half2_to_float2(v);
1301
+ float2 rot_fv = rotary_embedding_transform(fv, coef);
1302
+ return float2_to_half2(rot_fv);
1303
+ }
1304
+
1305
+ #ifdef ENABLE_BF16
1306
+ inline __device__ __nv_bfloat162 rotary_embedding_transform(const __nv_bfloat162 v, const float2 coef)
1307
+ {
1308
+ float2 fv = bf1622float2(v);
1309
+ float2 rot_fv = rotary_embedding_transform(fv, coef);
1310
+ return __floats2bfloat162_rn(rot_fv.x, rot_fv.y);
1311
+ }
1312
+ #endif
1313
+
1314
+ inline __device__ void apply_rotary_embedding(float& q, int zid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
1315
+ {
1316
+ return;
1317
+ }
1318
+
1319
+ inline __device__ void apply_rotary_embedding(float& q, float& k, int zid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
1320
+ {
1321
+ return;
1322
+ }
1323
+
1324
+ inline __device__ void apply_rotary_embedding(float2& q, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
1325
+ {
1326
+ if (2 * tid >= rot_embed_dim) {
1327
+ return;
1328
+ }
1329
+ const auto coef = rotary_embedding_coefficient(2 * tid, rot_embed_dim, t_step, base, scale);
1330
+ q = rotary_embedding_transform(q, coef);
1331
+ }
1332
+
1333
+ inline __device__ void apply_rotary_embedding(float2& q, float2& k, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
1334
+ {
1335
+ if (2 * tid >= rot_embed_dim) {
1336
+ return;
1337
+ }
1338
+ const auto coef = rotary_embedding_coefficient(2 * tid, rot_embed_dim, t_step, base, scale);
1339
+ q = rotary_embedding_transform(q, coef);
1340
+ k = rotary_embedding_transform(k, coef);
1341
+ }
1342
+
1343
+ inline __device__ void apply_rotary_embedding(float4& q, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
1344
+ {
1345
+ if (4 * tid >= rot_embed_dim) {
1346
+ return;
1347
+ }
1348
+
1349
+ Float4_& q_ = *reinterpret_cast<Float4_*>(&q);
1350
+ const auto coef0 = rotary_embedding_coefficient(4 * tid, rot_embed_dim, t_step, base, scale);
1351
+ q_.x = rotary_embedding_transform(q_.x, coef0);
1352
+ const auto coef1 = rotary_embedding_coefficient(4 * tid + 2, rot_embed_dim, t_step, base, scale);
1353
+ q_.y = rotary_embedding_transform(q_.y, coef1);
1354
+ }
1355
+
1356
+ inline __device__ void apply_rotary_embedding(float4& q, float4& k, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
1357
+ {
1358
+ if (4 * tid >= rot_embed_dim) {
1359
+ return;
1360
+ }
1361
+
1362
+ Float4_& q_ = *reinterpret_cast<Float4_*>(&q);
1363
+ Float4_& k_ = *reinterpret_cast<Float4_*>(&k);
1364
+ const auto coef0 = rotary_embedding_coefficient(4 * tid, rot_embed_dim, t_step, base, scale);
1365
+ q_.x = rotary_embedding_transform(q_.x, coef0);
1366
+ k_.x = rotary_embedding_transform(k_.x, coef0);
1367
+ const auto coef1 = rotary_embedding_coefficient(4 * tid + 2, rot_embed_dim, t_step, base, scale);
1368
+ q_.y = rotary_embedding_transform(q_.y, coef1);
1369
+ k_.y = rotary_embedding_transform(k_.y, coef1);
1370
+ }
1371
+
1372
+ inline __device__ void apply_rotary_embedding(uint32_t& q, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
1373
+ {
1374
+ if (2 * tid >= rot_embed_dim) {
1375
+ return;
1376
+ }
1377
+ const auto coef = rotary_embedding_coefficient(2 * tid, rot_embed_dim, t_step, base, scale);
1378
+ q = rotary_embedding_transform(q, coef);
1379
+ }
1380
+
1381
+ inline __device__ void apply_rotary_embedding(uint32_t& q, uint32_t& k, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
1382
+ {
1383
+ if (2 * tid >= rot_embed_dim) {
1384
+ return;
1385
+ }
1386
+ const auto coef = rotary_embedding_coefficient(2 * tid, rot_embed_dim, t_step, base, scale);
1387
+ q = rotary_embedding_transform(q, coef);
1388
+ k = rotary_embedding_transform(k, coef);
1389
+ }
1390
+
1391
+ inline __device__ void apply_rotary_embedding(uint2& q, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
1392
+ {
1393
+ if (4 * tid >= rot_embed_dim) {
1394
+ return;
1395
+ }
1396
+ const auto coef0 = rotary_embedding_coefficient(4 * tid, rot_embed_dim, t_step, base, scale);
1397
+ q.x = rotary_embedding_transform(q.x, coef0);
1398
+ const auto coef1 = rotary_embedding_coefficient(4 * tid + 2, rot_embed_dim, t_step, base, scale);
1399
+ q.y = rotary_embedding_transform(q.y, coef1);
1400
+ }
1401
+
1402
+ inline __device__ void apply_rotary_embedding(uint2& q, uint2& k, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
1403
+ {
1404
+ if (4 * tid >= rot_embed_dim) {
1405
+ return;
1406
+ }
1407
+ const auto coef0 = rotary_embedding_coefficient(4 * tid, rot_embed_dim, t_step, base, scale);
1408
+ q.x = rotary_embedding_transform(q.x, coef0);
1409
+ k.x = rotary_embedding_transform(k.x, coef0);
1410
+ const auto coef1 = rotary_embedding_coefficient(4 * tid + 2, rot_embed_dim, t_step, base, scale);
1411
+ q.y = rotary_embedding_transform(q.y, coef1);
1412
+ k.y = rotary_embedding_transform(k.y, coef1);
1413
+ }
1414
+
1415
+ inline __device__ void apply_rotary_embedding(uint4& q, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
1416
+ {
1417
+ if (8 * tid >= rot_embed_dim) {
1418
+ return;
1419
+ }
1420
+ const auto coef0 = rotary_embedding_coefficient(8 * tid, rot_embed_dim, t_step, base, scale);
1421
+ q.x = rotary_embedding_transform(q.x, coef0);
1422
+ const auto coef1 = rotary_embedding_coefficient(8 * tid + 2, rot_embed_dim, t_step, base, scale);
1423
+ q.y = rotary_embedding_transform(q.y, coef1);
1424
+ const auto coef2 = rotary_embedding_coefficient(8 * tid + 4, rot_embed_dim, t_step, base, scale);
1425
+ q.z = rotary_embedding_transform(q.z, coef2);
1426
+ const auto coef3 = rotary_embedding_coefficient(8 * tid + 6, rot_embed_dim, t_step, base, scale);
1427
+ q.w = rotary_embedding_transform(q.w, coef3);
1428
+ }
1429
+
1430
+ inline __device__ void apply_rotary_embedding(uint4& q, uint4& k, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
1431
+ {
1432
+ if (8 * tid >= rot_embed_dim) {
1433
+ return;
1434
+ }
1435
+ const auto coef0 = rotary_embedding_coefficient(8 * tid, rot_embed_dim, t_step, base, scale);
1436
+ q.x = rotary_embedding_transform(q.x, coef0);
1437
+ k.x = rotary_embedding_transform(k.x, coef0);
1438
+ const auto coef1 = rotary_embedding_coefficient(8 * tid + 2, rot_embed_dim, t_step, base, scale);
1439
+ q.y = rotary_embedding_transform(q.y, coef1);
1440
+ k.y = rotary_embedding_transform(k.y, coef1);
1441
+ const auto coef2 = rotary_embedding_coefficient(8 * tid + 4, rot_embed_dim, t_step, base, scale);
1442
+ q.z = rotary_embedding_transform(q.z, coef2);
1443
+ k.z = rotary_embedding_transform(k.z, coef2);
1444
+ const auto coef3 = rotary_embedding_coefficient(8 * tid + 6, rot_embed_dim, t_step, base, scale);
1445
+ q.w = rotary_embedding_transform(q.w, coef3);
1446
+ k.w = rotary_embedding_transform(k.w, coef3);
1447
+ }
1448
+
1449
+ #ifdef ENABLE_BF16
1450
+ inline __device__ void apply_rotary_embedding(__nv_bfloat162& q, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
1451
+ {
1452
+ if (2 * tid >= rot_embed_dim) {
1453
+ return;
1454
+ }
1455
+ const auto coef = rotary_embedding_coefficient(2 * tid, rot_embed_dim, t_step, base, scale);
1456
+ q = rotary_embedding_transform(q, coef);
1457
+ }
1458
+
1459
+ inline __device__ void
1460
+ apply_rotary_embedding(__nv_bfloat162& q, __nv_bfloat162& k, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
1461
+ {
1462
+ if (2 * tid >= rot_embed_dim) {
1463
+ return;
1464
+ }
1465
+ const auto coef = rotary_embedding_coefficient(2 * tid, rot_embed_dim, t_step, base, scale);
1466
+ q = rotary_embedding_transform(q, coef);
1467
+ k = rotary_embedding_transform(k, coef);
1468
+ }
1469
+
1470
+ inline __device__ void apply_rotary_embedding(bf16_4_t& q, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
1471
+ {
1472
+ if (4 * tid >= rot_embed_dim) {
1473
+ return;
1474
+ }
1475
+ const auto coef0 = rotary_embedding_coefficient(4 * tid, rot_embed_dim, t_step, base, scale);
1476
+ q.x = rotary_embedding_transform(q.x, coef0);
1477
+ const auto coef1 = rotary_embedding_coefficient(4 * tid + 2, rot_embed_dim, t_step, base, scale);
1478
+ q.y = rotary_embedding_transform(q.y, coef1);
1479
+ }
1480
+
1481
+ inline __device__ void apply_rotary_embedding(bf16_4_t& q, bf16_4_t& k, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
1482
+ {
1483
+ if (4 * tid >= rot_embed_dim) {
1484
+ return;
1485
+ }
1486
+ const auto coef0 = rotary_embedding_coefficient(4 * tid, rot_embed_dim, t_step, base, scale);
1487
+ q.x = rotary_embedding_transform(q.x, coef0);
1488
+ k.x = rotary_embedding_transform(k.x, coef0);
1489
+ const auto coef1 = rotary_embedding_coefficient(4 * tid + 2, rot_embed_dim, t_step, base, scale);
1490
+ q.y = rotary_embedding_transform(q.y, coef1);
1491
+ k.y = rotary_embedding_transform(k.y, coef1);
1492
+ }
1493
+
1494
+ inline __device__ void apply_rotary_embedding(bf16_8_t& q, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
1495
+ {
1496
+ if (8 * tid >= rot_embed_dim) {
1497
+ return;
1498
+ }
1499
+ const auto coef0 = rotary_embedding_coefficient(8 * tid, rot_embed_dim, t_step, base, scale);
1500
+ q.x = rotary_embedding_transform(q.x, coef0);
1501
+ const auto coef1 = rotary_embedding_coefficient(8 * tid + 2, rot_embed_dim, t_step, base, scale);
1502
+ q.y = rotary_embedding_transform(q.y, coef1);
1503
+ const auto coef2 = rotary_embedding_coefficient(8 * tid + 4, rot_embed_dim, t_step, base, scale);
1504
+ q.z = rotary_embedding_transform(q.z, coef2);
1505
+ const auto coef3 = rotary_embedding_coefficient(8 * tid + 6, rot_embed_dim, t_step, base, scale);
1506
+ q.w = rotary_embedding_transform(q.w, coef3);
1507
+ }
1508
+
1509
+ inline __device__ void apply_rotary_embedding(bf16_8_t& q, bf16_8_t& k, int tid, int rot_embed_dim, int t_step, const float base=10000.0f, const float scale=1.0f)
1510
+ {
1511
+ if (8 * tid >= rot_embed_dim) {
1512
+ return;
1513
+ }
1514
+ const auto coef0 = rotary_embedding_coefficient(8 * tid, rot_embed_dim, t_step, base, scale);
1515
+ q.x = rotary_embedding_transform(q.x, coef0);
1516
+ k.x = rotary_embedding_transform(k.x, coef0);
1517
+ const auto coef1 = rotary_embedding_coefficient(8 * tid + 2, rot_embed_dim, t_step, base, scale);
1518
+ q.y = rotary_embedding_transform(q.y, coef1);
1519
+ k.y = rotary_embedding_transform(k.y, coef1);
1520
+ const auto coef2 = rotary_embedding_coefficient(8 * tid + 4, rot_embed_dim, t_step, base, scale);
1521
+ q.z = rotary_embedding_transform(q.z, coef2);
1522
+ k.z = rotary_embedding_transform(k.z, coef2);
1523
+ const auto coef3 = rotary_embedding_coefficient(8 * tid + 6, rot_embed_dim, t_step, base, scale);
1524
+ q.w = rotary_embedding_transform(q.w, coef3);
1525
+ k.w = rotary_embedding_transform(k.w, coef3);
1526
+ }
1527
+ #endif // ENABLE_BF16
1528
+
1529
+ template<typename Vec_T, typename T>
1530
+ __device__ __inline__ void vec_from_smem_transpose(Vec_T& vec, T* smem, int transpose_idx, int smem_pitch);
1531
+
1532
+ template<>
1533
+ __device__ __inline__ void vec_from_smem_transpose(float& vec, float* smem, int transpose_idx, int smem_pitch)
1534
+ {
1535
+ return;
1536
+ }
1537
+
1538
+ template<>
1539
+ __device__ __inline__ void vec_from_smem_transpose(uint32_t& vec, uint16_t* smem, int transpose_idx, int smem_pitch)
1540
+ {
1541
+ union {
1542
+ uint32_t u32;
1543
+ uint16_t u16[2];
1544
+ } tmp;
1545
+ tmp.u16[0] = smem[transpose_idx];
1546
+ tmp.u16[1] = smem[smem_pitch + transpose_idx];
1547
+
1548
+ vec = tmp.u32;
1549
+ }
1550
+
1551
+ template<>
1552
+ __device__ __inline__ void vec_from_smem_transpose(uint2& vec, uint16_t* smem, int transpose_idx, int smem_pitch)
1553
+ {
1554
+ union {
1555
+ uint32_t u32;
1556
+ uint16_t u16[2];
1557
+ } tmp_1, tmp_2;
1558
+ tmp_1.u32 = *reinterpret_cast<uint32_t*>(&smem[transpose_idx]);
1559
+ tmp_2.u32 = *reinterpret_cast<uint32_t*>(&smem[smem_pitch + transpose_idx]);
1560
+
1561
+ union {
1562
+ uint2 u32x2;
1563
+ uint16_t u16[4];
1564
+ } tmp_3;
1565
+ tmp_3.u16[0] = tmp_1.u16[0];
1566
+ tmp_3.u16[1] = tmp_2.u16[0];
1567
+ tmp_3.u16[2] = tmp_1.u16[1];
1568
+ tmp_3.u16[3] = tmp_2.u16[1];
1569
+
1570
+ vec = tmp_3.u32x2;
1571
+ }
1572
+
1573
+ template<>
1574
+ __device__ __inline__ void vec_from_smem_transpose(uint4& vec, uint16_t* smem, int transpose_idx, int smem_pitch)
1575
+ {
1576
+ union {
1577
+ uint64_t u64;
1578
+ uint16_t u16[4];
1579
+ } tmp_1, tmp_2;
1580
+ tmp_1.u64 = *reinterpret_cast<uint64_t*>(&smem[transpose_idx]);
1581
+ tmp_2.u64 = *reinterpret_cast<uint64_t*>(&smem[smem_pitch + transpose_idx]);
1582
+
1583
+ union {
1584
+ uint4 u32x4;
1585
+ uint16_t u16[8];
1586
+ } tmp_3;
1587
+ tmp_3.u16[0] = tmp_1.u16[0];
1588
+ tmp_3.u16[1] = tmp_2.u16[0];
1589
+ tmp_3.u16[2] = tmp_1.u16[1];
1590
+ tmp_3.u16[3] = tmp_2.u16[1];
1591
+ tmp_3.u16[4] = tmp_1.u16[2];
1592
+ tmp_3.u16[5] = tmp_2.u16[2];
1593
+ tmp_3.u16[6] = tmp_1.u16[3];
1594
+ tmp_3.u16[7] = tmp_2.u16[3];
1595
+
1596
+ vec = tmp_3.u32x4;
1597
+ }
1598
+
1599
+ #ifdef ENABLE_BF16
1600
+ template<>
1601
+ __device__ __inline__ void
1602
+ vec_from_smem_transpose(bf16_4_t& vec, __nv_bfloat16* smem, int transpose_idx, int smem_pitch)
1603
+ {
1604
+ union {
1605
+ uint32_t u32;
1606
+ __nv_bfloat16 bf16[2];
1607
+ } tmp_1, tmp_2;
1608
+ tmp_1.u32 = *reinterpret_cast<uint32_t*>(&smem[transpose_idx]);
1609
+ tmp_2.u32 = *reinterpret_cast<uint32_t*>(&smem[smem_pitch + transpose_idx]);
1610
+
1611
+ vec.x = __nv_bfloat162{tmp_1.bf16[0], tmp_2.bf16[0]};
1612
+ vec.y = __nv_bfloat162{tmp_1.bf16[1], tmp_2.bf16[1]};
1613
+ }
1614
+
1615
+ template<>
1616
+ __device__ __inline__ void
1617
+ vec_from_smem_transpose(bf16_8_t& vec, __nv_bfloat16* smem, int transpose_idx, int smem_pitch)
1618
+ {
1619
+ union {
1620
+ uint64_t u64;
1621
+ __nv_bfloat16 bf16[4];
1622
+ } tmp_1, tmp_2;
1623
+ tmp_1.u64 = *reinterpret_cast<uint64_t*>(&smem[transpose_idx]);
1624
+ tmp_2.u64 = *reinterpret_cast<uint64_t*>(&smem[smem_pitch + transpose_idx]);
1625
+
1626
+ vec.x = __nv_bfloat162{tmp_1.bf16[0], tmp_2.bf16[0]};
1627
+ vec.y = __nv_bfloat162{tmp_1.bf16[1], tmp_2.bf16[1]};
1628
+ vec.z = __nv_bfloat162{tmp_1.bf16[2], tmp_2.bf16[2]};
1629
+ vec.w = __nv_bfloat162{tmp_1.bf16[3], tmp_2.bf16[3]};
1630
+ }
1631
+ #endif // ENABLE_BF16
1632
+
1633
+ template<>
1634
+ __device__ __inline__ void vec_from_smem_transpose(float4& vec, float* smem, int transpose_idx, int smem_pitch)
1635
+ {
1636
+ vec.x = smem[transpose_idx];
1637
+ vec.z = smem[transpose_idx + 1];
1638
+ vec.y = smem[smem_pitch + transpose_idx];
1639
+ vec.w = smem[smem_pitch + transpose_idx + 1];
1640
+ }
1641
+
1642
+ template<>
1643
+ __device__ __inline__ void vec_from_smem_transpose(uint32_t& vec, half* smem, int transpose_idx, int smem_pitch)
1644
+ {
1645
+ union {
1646
+ uint32_t u32;
1647
+ half u16[2];
1648
+ } tmp;
1649
+ tmp.u16[0] = smem[transpose_idx];
1650
+ tmp.u16[1] = smem[smem_pitch + transpose_idx];
1651
+
1652
+ vec = tmp.u32;
1653
+ }
1654
+
1655
+ #ifdef ENABLE_BF16
1656
+ template<>
1657
+ __device__ __inline__ void
1658
+ vec_from_smem_transpose(__nv_bfloat162& vec, __nv_bfloat16* smem, int transpose_idx, int smem_pitch)
1659
+ {
1660
+ vec.x = smem[transpose_idx];
1661
+ vec.y = smem[smem_pitch + transpose_idx];
1662
+ }
1663
+ #endif
1664
+
1665
+ template<>
1666
+ __device__ __inline__ void vec_from_smem_transpose(float2& vec, float* smem, int transpose_idx, int smem_pitch)
1667
+ {
1668
+ vec.x = smem[transpose_idx];
1669
+ vec.y = smem[smem_pitch + transpose_idx];
1670
+ }
1671
+
1672
+ template<typename Vec_T, typename T>
1673
+ __device__ __inline__ void write_smem_transpose(const Vec_T& vec, T* smem, int transpose_idx, int smem_pitch);
1674
+
1675
+ template<>
1676
+ __device__ __inline__ void write_smem_transpose(const float& vec, float* smem, int transpose_idx, int smem_pitch)
1677
+ {
1678
+ return;
1679
+ }
1680
+
1681
+ template<>
1682
+ __device__ __inline__ void write_smem_transpose(const uint4& vec, uint16_t* smem, int transpose_idx, int smem_pitch)
1683
+ {
1684
+ union {
1685
+ uint64_t u64;
1686
+ uint16_t u16[4];
1687
+ } tmp_1, tmp_2;
1688
+
1689
+ union {
1690
+ uint4 u32x4;
1691
+ uint16_t u16[8];
1692
+ } tmp_3;
1693
+ tmp_3.u32x4 = vec;
1694
+ tmp_1.u16[0] = tmp_3.u16[0];
1695
+ tmp_2.u16[0] = tmp_3.u16[1];
1696
+ tmp_1.u16[1] = tmp_3.u16[2];
1697
+ tmp_2.u16[1] = tmp_3.u16[3];
1698
+ tmp_1.u16[2] = tmp_3.u16[4];
1699
+ tmp_2.u16[2] = tmp_3.u16[5];
1700
+ tmp_1.u16[3] = tmp_3.u16[6];
1701
+ tmp_2.u16[3] = tmp_3.u16[7];
1702
+
1703
+ *reinterpret_cast<uint64_t*>(&smem[transpose_idx]) = tmp_1.u64;
1704
+ *reinterpret_cast<uint64_t*>(&smem[smem_pitch + transpose_idx]) = tmp_2.u64;
1705
+ }
1706
+
1707
+ template<>
1708
+ __device__ __inline__ void write_smem_transpose(const uint2& vec, uint16_t* smem, int transpose_idx, int smem_pitch)
1709
+ {
1710
+ union {
1711
+ uint32_t u32;
1712
+ uint16_t u16[2];
1713
+ } tmp_1, tmp_2;
1714
+
1715
+ union {
1716
+ uint2 u32x2;
1717
+ uint16_t u16[4];
1718
+ } tmp_3;
1719
+ tmp_3.u32x2 = vec;
1720
+ tmp_1.u16[0] = tmp_3.u16[0];
1721
+ tmp_2.u16[0] = tmp_3.u16[1];
1722
+ tmp_1.u16[1] = tmp_3.u16[2];
1723
+ tmp_2.u16[1] = tmp_3.u16[3];
1724
+
1725
+ *reinterpret_cast<uint32_t*>(&smem[transpose_idx]) = tmp_1.u32;
1726
+ *reinterpret_cast<uint32_t*>(&smem[smem_pitch + transpose_idx]) = tmp_2.u32;
1727
+ }
1728
+
1729
+ template<>
1730
+ __device__ __inline__ void write_smem_transpose(const uint32_t& vec, uint16_t* smem, int transpose_idx, int smem_pitch)
1731
+ {
1732
+ union {
1733
+ uint32_t u32;
1734
+ uint16_t u16[2];
1735
+ } tmp;
1736
+ tmp.u32 = vec;
1737
+
1738
+ smem[transpose_idx] = tmp.u16[0];
1739
+ smem[smem_pitch + transpose_idx] = tmp.u16[1];
1740
+ }
1741
+
1742
+ template<>
1743
+ __device__ __inline__ void write_smem_transpose(const float4& vec, float* smem, int transpose_idx, int smem_pitch)
1744
+ {
1745
+ smem[transpose_idx] = vec.x;
1746
+ smem[transpose_idx + 1] = vec.z;
1747
+ smem[smem_pitch + transpose_idx] = vec.y;
1748
+ smem[smem_pitch + transpose_idx + 1] = vec.w;
1749
+ }
1750
+
1751
+ template<>
1752
+ __device__ __inline__ void write_smem_transpose(const uint32_t& vec, half* smem, int transpose_idx, int smem_pitch)
1753
+ {
1754
+ union {
1755
+ uint32_t u32;
1756
+ half u16[2];
1757
+ } tmp;
1758
+
1759
+ tmp.u32 = vec;
1760
+ smem[transpose_idx] = tmp.u16[0];
1761
+ smem[smem_pitch + transpose_idx] = tmp.u16[1];
1762
+ }
1763
+
1764
+ #ifdef ENABLE_BF16
1765
+ template<>
1766
+ __device__ __inline__ void
1767
+ write_smem_transpose(const __nv_bfloat162& vec, __nv_bfloat16* smem, int transpose_idx, int smem_pitch)
1768
+ {
1769
+ smem[transpose_idx] = vec.x;
1770
+ smem[smem_pitch + transpose_idx] = vec.y;
1771
+ }
1772
+
1773
+ template<>
1774
+ __device__ __inline__ void
1775
+ write_smem_transpose(const bf16_4_t& vec, __nv_bfloat16* smem, int transpose_idx, int smem_pitch)
1776
+ {
1777
+ write_smem_transpose(reinterpret_cast<const uint2&>(vec), reinterpret_cast<uint16_t*>(smem), transpose_idx, smem_pitch);
1778
+ }
1779
+
1780
+ template<>
1781
+ __device__ __inline__ void
1782
+ write_smem_transpose(const bf16_8_t& vec, __nv_bfloat16* smem, int transpose_idx, int smem_pitch)
1783
+ {
1784
+ write_smem_transpose(reinterpret_cast<const uint4&>(vec), reinterpret_cast<uint16_t*>(smem), transpose_idx, smem_pitch);
1785
+ }
1786
+ #endif
1787
+
1788
+ template<>
1789
+ __device__ __inline__ void write_smem_transpose(const float2& vec, float* smem, int transpose_idx, int smem_pitch)
1790
+ {
1791
+ smem[transpose_idx] = vec.x;
1792
+ smem[smem_pitch + transpose_idx] = vec.y;
1793
+ }
1794
+
1795
+ } // namespace mmha
llm-awq/awq/kernels/csrc/attention/ft_attention.cpp ADDED
@@ -0,0 +1,185 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Adapted from NVIDIA/FasterTransformer and FlashAttention
2
+
3
+ #include <torch/extension.h>
4
+ #include "ATen/cuda/CUDAContext.h"
5
+ #include <c10/cuda/CUDAGuard.h>
6
+
7
+ #include "ft_attention.h"
8
+ #include "decoder_masked_multihead_attention.h"
9
+
10
+ #define CHECK_DEVICE(x) TORCH_CHECK(x.device().type() == torch::kCUDA, #x " must be on CUDA")
11
+ #define CHECK_SHAPE(x, ...) TORCH_CHECK(x.sizes() == torch::IntArrayRef({__VA_ARGS__}), #x " must have shape (" #__VA_ARGS__ ")")
12
+ #define CHECK_CONTIGUOUS(x) TORCH_CHECK(x.is_contiguous(), #x " must be contiguous")
13
+
14
+ #define DISPATCH_FLOAT_AND_HALF_AND_BF16(TYPE, NAME, ...) \
15
+ if (TYPE == at::ScalarType::Half) { \
16
+ using scalar_t = at::Half; \
17
+ __VA_ARGS__(); \
18
+ } else if (TYPE == at::ScalarType::BFloat16) { \
19
+ using scalar_t = at::BFloat16; \
20
+ __VA_ARGS__(); \
21
+ } else if (TYPE == at::ScalarType::Float) { \
22
+ using scalar_t = float; \
23
+ __VA_ARGS__(); \
24
+ } else { \
25
+ AT_ERROR(#NAME, " not implemented for type '", toString(TYPE), "'"); \
26
+ }
27
+
28
+ template<typename T>
29
+ void masked_multihead_attention(const Masked_multihead_attention_params<T>& params,
30
+ const cudaStream_t& stream);
31
+
32
+ template<typename T>
33
+ void cross_multihead_attention(const Masked_multihead_attention_params<T>& params,
34
+ const cudaStream_t& stream);
35
+
36
+ template<typename T>
37
+ struct SATypeConverter {
38
+ using Type = T;
39
+ };
40
+
41
+ template<>
42
+ struct SATypeConverter<at::Half> {
43
+ using Type = uint16_t;
44
+ };
45
+
46
+ template<>
47
+ struct SATypeConverter<at::BFloat16> {
48
+ using Type = __nv_bfloat16;
49
+ };
50
+
51
+ template <typename T>
52
+ void set_params(Masked_multihead_attention_params<T> &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/layernorm/layernorm.cu ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+
3
+ Adapted from NVIDIA FasterTransformer:
4
+ https://github.com/NVIDIA/FasterTransformer/blob/main/src/fastertransformer/kernels/layernorm_kernels.cu
5
+
6
+ */
7
+
8
+ #include <torch/extension.h>
9
+ #include <cuda_fp16.h>
10
+ #include "reduction.cuh"
11
+ #include "layernorm.h"
12
+ #include <cuda_runtime.h>
13
+ #include <c10/cuda/CUDAGuard.h>
14
+
15
+ #define DISPATCH_PYTORCH_DTYPE_TO_CTYPE_FP16(pytorch_dtype, c_type, ...) \
16
+ if (pytorch_dtype == at::ScalarType::Half) { \
17
+ using c_type = half; \
18
+ __VA_ARGS__ \
19
+ } else if (pytorch_dtype == at::ScalarType::BFloat16) { \
20
+ using c_type = nv_bfloat16; \
21
+ __VA_ARGS__ \
22
+ } else { \
23
+ std::ostringstream oss; \
24
+ oss << __PRETTY_FUNCTION__ << " failed to dispatch data type " << pytorch_dtype; \
25
+ TORCH_CHECK(false, oss.str()); \
26
+ }
27
+
28
+ static inline __device__ float to_float(half src)
29
+ {
30
+ return __half2float(src);
31
+ }
32
+
33
+ static inline __device__ float to_float(float src)
34
+ {
35
+ return src;
36
+ }
37
+
38
+ template<typename T>
39
+ __global__ void generalT5LayerNorm(
40
+ const T* __restrict input, const T* __restrict gamma, T* output, const float layernorm_eps, int m, int n)
41
+ {
42
+ // layernorm module in the T5 style No bias and no subtraction of mean.
43
+ const int tid = threadIdx.x;
44
+
45
+ __shared__ float s_variance;
46
+ float variance = 0.0f;
47
+
48
+ float local_var_sum = 0.0f;
49
+ for (int i = tid; i < n; i += blockDim.x) {
50
+ float diff = to_float(__ldg(&input[blockIdx.x * n + i]));
51
+ local_var_sum += diff * diff;
52
+ }
53
+ variance = blockReduceSum(local_var_sum);
54
+
55
+ if (threadIdx.x == 0) {
56
+ s_variance = rsqrtf(variance / (float)n + layernorm_eps);
57
+ }
58
+ __syncthreads();
59
+
60
+ for (int i = tid; i < n; i += blockDim.x) {
61
+ output[blockIdx.x * n + i] =
62
+ clamp_inf_for_half<T>((to_float(input[blockIdx.x * n + i]) * s_variance) * to_float(__ldg(&gamma[i])));
63
+ }
64
+ }
65
+
66
+
67
+ template<typename T>
68
+ void invokeGeneralT5LayerNorm(T* out,
69
+ const T* input,
70
+ const T* gamma,
71
+ // const T* beta,
72
+ const float layernorm_eps,
73
+ const int m,
74
+ const int n)
75
+ {
76
+ dim3 grid(m);
77
+ dim3 block(min(n, 1024));
78
+
79
+ /* For general cases, n is equal to hidden_units, e.g., 512/1024.
80
+ Since we have warp shuffle inside the code, block.x % 32 should be 0.
81
+ */
82
+ if (n % 32 != 0) {
83
+ block.x = 1024;
84
+ }
85
+
86
+ block.x = block.x / (4 / sizeof(T)); // if using half, only need half of block.x
87
+
88
+ /* should pay attention to the rsqrt precision*/
89
+ generalT5LayerNorm<T><<<grid, block>>>(input, gamma, out, layernorm_eps, m, n); // For gpt-3
90
+ }
91
+
92
+ template void invokeGeneralT5LayerNorm(half* out,
93
+ const half* input,
94
+ const half* gamma,
95
+ // const half* beta,
96
+ const float layernorm_eps,
97
+ const int m,
98
+ const int n);
99
+
100
+ template void invokeGeneralT5LayerNorm(float* out,
101
+ const float* input,
102
+ const float* gamma,
103
+ // const half* beta,
104
+ const float layernorm_eps,
105
+ const int m,
106
+ const int n);
107
+
108
+
109
+
110
+ // input b, n, c
111
+ void layernorm_forward_cuda(
112
+ torch::Tensor _input,
113
+ torch::Tensor _gamma,
114
+ torch::Tensor _out,
115
+ float eps)
116
+ {
117
+ int m = _input.size(0) * _input.size(1);
118
+ int n = _input.size(2);
119
+ const at::cuda::OptionalCUDAGuard device_guard(device_of(_input));
120
+
121
+ auto data_type = _input.scalar_type();
122
+ TORCH_CHECK(_gamma.scalar_type() == data_type);
123
+ TORCH_CHECK(_out.scalar_type() == data_type);
124
+
125
+ DISPATCH_PYTORCH_DTYPE_TO_CTYPE_FP16(data_type, ctype, {
126
+ auto input = reinterpret_cast<ctype*>(_input.data_ptr());
127
+ auto gamma = reinterpret_cast<ctype*>(_gamma.data_ptr());
128
+ auto out = reinterpret_cast<ctype*>(_out.data_ptr());
129
+ invokeGeneralT5LayerNorm(out, input, gamma, eps, m, n);
130
+ });
131
+ }
llm-awq/awq/kernels/csrc/position_embedding/pos_encoding.h ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+ #include <torch/extension.h>
3
+
4
+ void rotary_embedding_neox(
5
+ torch::Tensor& positions,
6
+ torch::Tensor& query,
7
+ torch::Tensor& key,
8
+ int head_size,
9
+ torch::Tensor& cos_sin_cache);
llm-awq/awq/kernels/csrc/pybind.cpp ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <pybind11/pybind11.h>
2
+ #include <torch/extension.h>
3
+ #include "attention/ft_attention.h"
4
+ #include "layernorm/layernorm.h"
5
+ #include "quantization/gemm_cuda.h"
6
+ #include "quantization/gemv_cuda.h"
7
+ #include "quantization_new/gemm/gemm_cuda.h"
8
+ #include "quantization_new/gemv/gemv_cuda.h"
9
+ #include "position_embedding/pos_encoding.h"
10
+ #include "rope_new/fused_rope_with_pos.h"
11
+ #include "w8a8/w8a8_gemm_cuda.h"
12
+ #include "w8a8/quantization.h"
13
+ #include "w8a8/layernorm.h"
14
+ #include "w8a8/act.h"
15
+
16
+
17
+ PYBIND11_MODULE(TORCH_EXTENSION_NAME, m)
18
+ {
19
+ m.def("layernorm_forward_cuda", &layernorm_forward_cuda, "FasterTransformer layernorm kernel");
20
+ m.def("gemm_forward_cuda", &gemm_forward_cuda, "Quantized GEMM kernel.");
21
+ m.def("gemv_forward_cuda", &gemv_forward_cuda, "Quantized GEMV kernel.");
22
+ m.def("gemm_forward_cuda_new", &gemm_forward_cuda_new, "New quantized GEMM kernel.");
23
+ m.def("gemv_forward_cuda_new", &gemv_forward_cuda_new, "New quantized GEMV kernel.");
24
+ m.def("rotary_embedding_neox", &rotary_embedding_neox, "Apply GPT-NeoX style rotary embedding to query and key");
25
+ m.def("single_query_attention", &single_query_attention, "Attention with a single query",
26
+ py::arg("q"), py::arg("k"), py::arg("v"), py::arg("k_cache"), py::arg("v_cache"),
27
+ py::arg("length_per_sample_"), py::arg("alibi_slopes_"), py::arg("timestep"), py::arg("rotary_embedding_dim")=0,
28
+ py::arg("rotary_base")=10000.0f, py::arg("rotary_scale")=1.0f, py::arg("neox_rotary_style")=true);
29
+ m.def("fused_rope_with_pos_forward_func", &fused_rope_with_pos_forward_func,"Fused rope forward function with B,S,D embedding");
30
+ m.def("w8a8_gemm_forward_cuda", &w8a8_gemm_forward_cuda, "our w8a8 gemm kernel");
31
+ m.def("w8a8_gemm_fuse_bias_forward_cuda", &w8a8_gemm_fuse_bias_forward_cuda, "our w8a8 gemm fused bias kernel");
32
+ m.def("invoke_quant", &invoke_quant, "fp16->int8 quantization");
33
+ m.def("rms_norm_general", &rms_norm_general, py::arg("out"), py::arg("input"),
34
+ py::arg("weight"), py::arg("bias"),py::arg("scaling"), py::arg("epsilon"), py::arg("use_per_token_quant") = true,
35
+ "Apply Root Mean Square (RMS) Normalization to the input tensor (TRTLLM kernel).");
36
+ m.def("silu_and_mul", &silu_and_mul, "Activation function.");
37
+ m.def("gelu_and_quant",&gelu_and_quant, "Apply gelu act and quant output");
38
+ }
llm-awq/awq/kernels/csrc/quantization/gemv_cuda.cu ADDED
@@ -0,0 +1,247 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Inspired by https://github.com/ankan-ban/llama_cu_awq
2
+ /*
3
+
4
+ @article{lin2023awq,
5
+ title={AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration},
6
+ author={Lin, Ji and Tang, Jiaming and Tang, Haotian and Yang, Shang and Dang, Xingyu and Han, Song},
7
+ journal={arXiv},
8
+ year={2023}
9
+ }
10
+
11
+ */
12
+
13
+ #include <cuda_fp16.h>
14
+ #include <stdio.h>
15
+ #include <torch/extension.h>
16
+ #include "gemv_cuda.h"
17
+ #define VECTORIZE_FACTOR 8
18
+ #define Q_VECTORIZE_FACTOR 8
19
+ #define PACK_FACTOR 8
20
+ #define WARP_SIZE 32
21
+
22
+
23
+ // Reduce sum within the warp using the tree reduction algorithm.
24
+ __device__ __forceinline__ float warp_reduce_sum(float sum) {
25
+ #pragma unroll
26
+ for(int i = 4; i >= 0; i--){
27
+ sum += __shfl_down_sync(0xffffffff, sum, 1<<i);
28
+ }
29
+ /*
30
+ // Equivalent to the following tree reduction implementation:
31
+ sum += __shfl_down_sync(0xffffffff, sum, 16);
32
+ sum += __shfl_down_sync(0xffffffff, sum, 8);
33
+ sum += __shfl_down_sync(0xffffffff, sum, 4);
34
+ sum += __shfl_down_sync(0xffffffff, sum, 2);
35
+ sum += __shfl_down_sync(0xffffffff, sum, 1);
36
+ */
37
+ return sum;
38
+ }
39
+
40
+ __device__ __forceinline__ int make_divisible(int c, int divisor){
41
+ return (c + divisor - 1) / divisor;
42
+ }
43
+
44
+
45
+ /*
46
+ Computes GEMV (group_size = 64).
47
+
48
+ Args:
49
+ inputs: vector of shape [batch_size, IC];
50
+ weight: matrix of shape [OC, IC / 8];
51
+ output: vector of shape [OC];
52
+ zeros: matrix of shape [OC, IC / group_size / 8];
53
+ scaling_factors: matrix of shape [OC, IC / group_size];
54
+
55
+ Notes:
56
+ One cannot infer group_size from the shape of scaling factors.
57
+ the second dimension is rounded up to a multiple of PACK_FACTOR.
58
+ */
59
+ __global__ void gemv_kernel_g64(
60
+ const float4* _inputs, const uint32_t* weight, const uint32_t* zeros, const half* scaling_factors, half* _outputs,
61
+ const int IC, const int OC){
62
+ const int group_size = 64;
63
+ float psum = 0;
64
+ const int batch_idx = blockIdx.z;
65
+ const int oc_idx = blockIdx.y * blockDim.y + threadIdx.y;
66
+ const float4* inputs = _inputs + batch_idx * IC / PACK_FACTOR;
67
+ half* outputs = _outputs + batch_idx * OC;
68
+ // This is essentially zeros_w.
69
+ const int num_groups_packed = make_divisible(make_divisible(IC / group_size, PACK_FACTOR), 2) * 2;
70
+ const int weight_w = IC / PACK_FACTOR;
71
+ // TODO (Haotian): zeros_w is incorrect, after fixing we got misaligned address
72
+ const int zeros_w = make_divisible(make_divisible(IC / group_size, PACK_FACTOR), 2) * 2;
73
+ // consistent with input shape
74
+ const int sf_w = make_divisible(make_divisible(IC / group_size, PACK_FACTOR), 2) * 2 * PACK_FACTOR;
75
+ // if(blockIdx.x == 0 && blockIdx.y == 0 && threadIdx.x == 0 && threadIdx.y == 0) printf("%d %d %d %d %d\n", IC, group_size, PACK_FACTOR, zeros_w, sf_w);
76
+ // tile size: 4 OC x 1024 IC per iter
77
+ for(int packed_group_idx = 0; packed_group_idx < num_groups_packed / 2; packed_group_idx++){
78
+ // 1024 numbers in one iteration across warp. Need 1024 / group_size zeros.
79
+ uint64_t packed_zeros = *reinterpret_cast<const uint64_t*>(zeros + oc_idx * zeros_w + packed_group_idx * 2);
80
+ uint32_t packed_weights[4];
81
+ // use float4 to load weights, each thread load 32 int4 numbers (1 x float4)
82
+ *((float4*)(packed_weights)) = *((float4*)(weight + oc_idx * weight_w + packed_group_idx * (WARP_SIZE * 4) + threadIdx.x * 4));
83
+ // load scaling factors
84
+ // g64: two threads -> 64 numbers -> 1 group; 1 warp = 16 groups.
85
+ float scaling_factor = __half2float(scaling_factors[oc_idx * sf_w + packed_group_idx * 16 + (threadIdx.x / 2)]);
86
+ float current_zeros = (float)((packed_zeros >> (threadIdx.x / 2 * 4)) & 0xF);
87
+ int inputs_ptr_delta = packed_group_idx * WARP_SIZE * 4 + threadIdx.x * 4;
88
+ const float4* inputs_ptr = inputs + inputs_ptr_delta;
89
+ // multiply 32 weights with 32 inputs
90
+ #pragma unroll
91
+ for (int ic_0 = 0; ic_0 < 4; ic_0++){
92
+ // iterate over different uint32_t packed_weights in this loop
93
+ uint32_t current_packed_weight = packed_weights[ic_0];
94
+ half packed_inputs[PACK_FACTOR];
95
+ // each thread load 8 inputs, starting index is packed_group_idx * 128 * 8 (because each iter loads 128*8)
96
+ if (inputs_ptr_delta + ic_0 < IC / PACK_FACTOR) {
97
+ *((float4*)packed_inputs) = *(inputs_ptr + ic_0);
98
+ #pragma unroll
99
+ for (int ic_1 = 0; ic_1 < PACK_FACTOR; ic_1++){
100
+ // iterate over 8 numbers packed within each uint32_t number
101
+ float current_single_weight_fp = (float)(current_packed_weight & 0xF);
102
+ float dequantized_weight = scaling_factor * (current_single_weight_fp - current_zeros);
103
+ //if(blockIdx.x == 0 && blockIdx.y == 0 && threadIdx.x == 0 && threadIdx.y == 0 && ic_0 == 0 && ic_1 == 0 && packed_group_idx == 0) printf("%f %f %f %f %X %X\n", dequantized_weight, current_single_weight_fp, scaling_factor, current_zeros, current_packed_weight, packed_zeros);
104
+ psum += dequantized_weight * __half2float(packed_inputs[ic_1]);
105
+ current_packed_weight = current_packed_weight >> 4;
106
+ }
107
+ }
108
+ }
109
+ }
110
+ psum = warp_reduce_sum(psum);
111
+ if (threadIdx.x == 0) {
112
+ outputs[oc_idx] = __float2half(psum);
113
+ }
114
+ }
115
+
116
+
117
+ /*
118
+ Computes GEMV (group_size = 128).
119
+
120
+ Args:
121
+ inputs: vector of shape [batch_size, IC];
122
+ weight: matrix of shape [OC, IC / 8];
123
+ output: vector of shape [OC];
124
+ zeros: matrix of shape [OC, IC / group_size / 8];
125
+ scaling_factors: matrix of shape [OC, IC / group_size];
126
+
127
+ Notes:
128
+ One cannot infer group_size from the shape of scaling factors.
129
+ the second dimension is rounded up to a multiple of PACK_FACTOR.
130
+ */
131
+ __global__ void gemv_kernel_g128(
132
+ const float4* _inputs, const uint32_t* weight, const uint32_t* zeros, const half* scaling_factors, half* _outputs,
133
+ const int IC, const int OC){
134
+ const int group_size = 128;
135
+ float psum = 0;
136
+ const int batch_idx = blockIdx.z;
137
+ const int oc_idx = blockIdx.y * blockDim.y + threadIdx.y;
138
+ const float4* inputs = _inputs + batch_idx * IC / PACK_FACTOR;
139
+ half* outputs = _outputs + batch_idx * OC;
140
+ const int num_groups_packed = make_divisible(IC / group_size, PACK_FACTOR);
141
+ const int weight_w = IC / PACK_FACTOR;
142
+ // TODO (Haotian): zeros_w is incorrect, after fixing we got misaligned address
143
+ const int zeros_w = make_divisible(IC / group_size, PACK_FACTOR);
144
+ // consistent with input shape
145
+ const int sf_w = make_divisible(IC / group_size, PACK_FACTOR) * PACK_FACTOR;
146
+ //if(blockIdx.x == 0 && blockIdx.y == 0 && threadIdx.x == 0 && threadIdx.y == 0) printf("%d %d %d %d\n", IC, group_size, PACK_FACTOR, zeros_w);
147
+ // tile size: 4 OC x 1024 IC per iter
148
+ for(int packed_group_idx = 0; packed_group_idx < num_groups_packed; packed_group_idx++){
149
+ // 1024 numbers in one iteration across warp. Need 1024 / group_size zeros.
150
+ uint32_t packed_zeros = *(zeros + oc_idx * zeros_w + packed_group_idx);
151
+ uint32_t packed_weights[4];
152
+ // use float4 to load weights, each thread load 32 int4 numbers (1 x float4)
153
+ *((float4*)(packed_weights)) = *((float4*)(weight + oc_idx * weight_w + packed_group_idx * (WARP_SIZE * 4) + threadIdx.x * 4));
154
+ // load scaling factors
155
+ // g128: four threads -> 128 numbers -> 1 group; 1 warp = 8 groups.
156
+ float scaling_factor = __half2float(scaling_factors[oc_idx * sf_w + packed_group_idx * 8 + (threadIdx.x / 4)]);
157
+ float current_zeros = (float)((packed_zeros >> (threadIdx.x / 4 * 4)) & 0xF);
158
+ int inputs_ptr_delta = packed_group_idx * WARP_SIZE * 4 + threadIdx.x * 4;
159
+ const float4* inputs_ptr = inputs + inputs_ptr_delta;
160
+ // multiply 32 weights with 32 inputs
161
+ #pragma unroll
162
+ for (int ic_0 = 0; ic_0 < 4; ic_0++){
163
+ // iterate over different uint32_t packed_weights in this loop
164
+ uint32_t current_packed_weight = packed_weights[ic_0];
165
+ half packed_inputs[PACK_FACTOR];
166
+ // each thread load 8 inputs, starting index is packed_group_idx * 128 * 8 (because each iter loads 128*8)
167
+ if (inputs_ptr_delta + ic_0 < IC / PACK_FACTOR) {
168
+ *((float4*)packed_inputs) = *(inputs_ptr + ic_0);
169
+ #pragma unroll
170
+ for (int ic_1 = 0; ic_1 < PACK_FACTOR; ic_1++){
171
+ // iterate over 8 numbers packed within each uint32_t number
172
+ float current_single_weight_fp = (float)(current_packed_weight & 0xF);
173
+ float dequantized_weight = scaling_factor * (current_single_weight_fp - current_zeros);
174
+ //if(blockIdx.x == 0 && blockIdx.y == 0 && threadIdx.x == 0 && threadIdx.y == 0 && ic_0 == 0 && ic_1 == 0 && packed_group_idx == 0) printf("%f %f %f %f %X %X\n", dequantized_weight, current_single_weight_fp, scaling_factor, current_zeros, current_packed_weight, packed_zeros);
175
+ psum += dequantized_weight * __half2float(packed_inputs[ic_1]);
176
+ current_packed_weight = current_packed_weight >> 4;
177
+ }
178
+ }
179
+ }
180
+ }
181
+ psum = warp_reduce_sum(psum);
182
+ if (threadIdx.x == 0) {
183
+ outputs[oc_idx] = __float2half(psum);
184
+ }
185
+ }
186
+
187
+
188
+ /*
189
+ Computes GEMV (PyTorch interface).
190
+
191
+ Args:
192
+ _in_feats: tensor of shape [B, IC];
193
+ _kernel: int tensor of shape [OC, IC // 8];
194
+ _zeros: int tensor of shape [OC, IC // G // 8];
195
+ _scaling_factors: tensor of shape [OC, IC // G];
196
+ blockDim_x: size of thread block, dimension x, where blockDim_x * workload_per_thread = IC;
197
+ blockDim_y: size of thread block, dimension y, where blockDim_y * gridDim_y = OC;
198
+
199
+ Returns:
200
+ out_feats: tensor of shape [B, OC];
201
+ */
202
+ torch::Tensor gemv_forward_cuda(
203
+ torch::Tensor _in_feats,
204
+ torch::Tensor _kernel,
205
+ torch::Tensor _scaling_factors,
206
+ torch::Tensor _zeros,
207
+ int group_size)
208
+ {
209
+ int num_in_feats = _in_feats.size(0);
210
+ int num_in_channels = _in_feats.size(1);
211
+ // int kernel_volume = _out_in_map.size(1);
212
+ auto in_feats = reinterpret_cast<float4*>(_in_feats.data_ptr<at::Half>());
213
+ auto kernel = reinterpret_cast<uint32_t*>(_kernel.data_ptr<int>());
214
+ auto zeros = reinterpret_cast<uint32_t*>(_zeros.data_ptr<int>());
215
+ auto scaling_factors = reinterpret_cast<half*>(_scaling_factors.data_ptr<at::Half>());
216
+ // auto out_in_map = _out_in_map.data_ptr<int>();
217
+ auto options =
218
+ torch::TensorOptions().dtype(_in_feats.dtype()).device(_in_feats.device());
219
+ // kernel is [OC, IC]
220
+ at::Tensor _out_feats = torch::empty({num_in_feats, _kernel.size(0)}, options);
221
+ int num_out_feats = _out_feats.size(-2);
222
+ int num_out_channels = _out_feats.size(-1);
223
+ auto out_feats = reinterpret_cast<half*>(_out_feats.data_ptr<at::Half>());
224
+ int blockDim_z = num_out_feats;
225
+ dim3 num_blocks(1, num_out_channels / 4, num_out_feats);
226
+ dim3 num_threads(32, 4);
227
+ if (group_size == 64)
228
+ {
229
+ gemv_kernel_g64<<<num_blocks, num_threads>>>(
230
+ // pointers
231
+ in_feats, kernel, zeros, scaling_factors, out_feats,
232
+ // constants
233
+ num_in_channels, num_out_channels
234
+ );
235
+ }
236
+ else if (group_size == 128)
237
+ {
238
+ gemv_kernel_g128<<<num_blocks, num_threads>>>(
239
+ // pointers
240
+ in_feats, kernel, zeros, scaling_factors, out_feats,
241
+ // constants
242
+ num_in_channels, num_out_channels
243
+ );
244
+ }
245
+ return _out_feats;
246
+ ;}
247
+
llm-awq/awq/kernels/setup.py ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from setuptools import find_packages, setup
2
+ from torch.utils.cpp_extension import BuildExtension, CUDAExtension, CppExtension
3
+
4
+
5
+ extra_compile_args = {
6
+ "cxx": ["-g", "-O3", "-fopenmp", "-lgomp", "-std=c++17", "-DENABLE_BF16"],
7
+ "nvcc": [
8
+ "-O3",
9
+ "-std=c++17",
10
+ "-DENABLE_BF16", # TODO
11
+ "-U__CUDA_NO_HALF_OPERATORS__",
12
+ "-U__CUDA_NO_HALF_CONVERSIONS__",
13
+ "-U__CUDA_NO_BFLOAT16_OPERATORS__",
14
+ "-U__CUDA_NO_BFLOAT16_CONVERSIONS__",
15
+ "-U__CUDA_NO_BFLOAT162_OPERATORS__",
16
+ "-U__CUDA_NO_BFLOAT162_CONVERSIONS__",
17
+ "--expt-relaxed-constexpr",
18
+ "--expt-extended-lambda",
19
+ "--use_fast_math",
20
+ "--threads=8",
21
+ ],
22
+ }
23
+
24
+ setup(
25
+ name="awq_inference_engine",
26
+ packages=find_packages(),
27
+ ext_modules=[
28
+ CUDAExtension(
29
+ name="awq_inference_engine",
30
+ sources=[
31
+ "csrc/pybind.cpp",
32
+ "csrc/quantization/gemm_cuda_gen.cu",
33
+ "csrc/quantization/gemv_cuda.cu",
34
+ "csrc/quantization_new/gemv/gemv_cuda.cu",
35
+ "csrc/quantization_new/gemm/gemm_cuda.cu",
36
+ "csrc/layernorm/layernorm.cu",
37
+ "csrc/position_embedding/pos_encoding_kernels.cu",
38
+ "csrc/attention/ft_attention.cpp",
39
+ "csrc/attention/decoder_masked_multihead_attention.cu",
40
+ "csrc/rope_new/fused_rope_with_pos.cu",
41
+ "csrc/w8a8/w8a8_gemm_cuda.cu",
42
+ "csrc/w8a8/quantization.cu",
43
+ "csrc/w8a8/act.cu",
44
+ "csrc/w8a8/layernorm.cu"
45
+ ],
46
+ extra_compile_args=extra_compile_args,
47
+ ),
48
+ ],
49
+ cmdclass={"build_ext": BuildExtension},
50
+ install_requires=["torch"],
51
+ )
llm-awq/tinychat/models/falcon.py ADDED
@@ -0,0 +1,304 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright (c) Meta Platforms, Inc. and affiliates.
2
+ # This software may be used and distributed according to the terms of the GNU General Public License version 3.
3
+
4
+ from typing import Optional, Tuple
5
+ from dataclasses import dataclass
6
+ import math
7
+
8
+ import torch
9
+ from torch import nn
10
+ import torch.nn.functional as F
11
+ import awq_inference_engine
12
+
13
+ import tinychat.utils.constants
14
+
15
+ max_batch_size = tinychat.utils.constants.max_batch_size
16
+ max_seq_len = tinychat.utils.constants.max_seq_len
17
+
18
+
19
+ # rotary pos emb helpers (torch.jit.script does not seem to support staticmethod...)
20
+ def rotate_half(x):
21
+ x1, x2 = x[..., : x.shape[-1] // 2], x[..., x.shape[-1] // 2 :]
22
+ return torch.cat(
23
+ (-x2, x1), dim=x1.ndim - 1
24
+ ) # dim=-1 triggers a bug in torch < 1.8.0
25
+
26
+
27
+ class RotaryEmbedding(nn.Module):
28
+ """Implementation of RotaryEmbedding from GPT-NeoX.
29
+ This implementation is design to operate on queries and keys that are compatible with
30
+ [batch_size, n_heads_per_partition, seq_len, head_dim] (e.g. MinGPTAttention format).
31
+ """
32
+
33
+ def __init__(
34
+ self,
35
+ head_dim: int,
36
+ base=10000,
37
+ ):
38
+ super().__init__()
39
+ inv_freq = 1.0 / (base ** (torch.arange(0, head_dim, 2).float() / head_dim))
40
+ self.register_buffer("inv_freq", inv_freq, persistent=False)
41
+ self.head_dim = head_dim
42
+ self.seq_len_cached = None
43
+ self.batch_size_cached = None
44
+ self.cos_cached: torch.Tensor | None = None
45
+ self.sin_cached: torch.Tensor | None = None
46
+
47
+ def cos_sin(
48
+ self,
49
+ seq_len: int,
50
+ device="cuda",
51
+ dtype=torch.bfloat16,
52
+ ) -> torch.Tensor:
53
+ if seq_len != self.seq_len_cached:
54
+ self.seq_len_cached = seq_len
55
+ t = torch.arange(seq_len, device=device).type_as(self.inv_freq)
56
+ freqs = torch.einsum("i,j->ij", t, self.inv_freq)
57
+ emb = torch.cat((freqs, freqs), dim=-1).to(device)
58
+
59
+ if dtype in [torch.float16, torch.bfloat16]:
60
+ emb = emb.float()
61
+
62
+ self.cos_cached = emb.cos()[None, :, :]
63
+ self.sin_cached = emb.sin()[None, :, :]
64
+
65
+ self.cos_cached = self.cos_cached.type(dtype)
66
+ self.sin_cached = self.sin_cached.type(dtype)
67
+
68
+ return self.cos_cached, self.sin_cached
69
+
70
+ def forward(self, _q, _k):
71
+ batch, seq_len, num_heads, head_dim = _q.shape
72
+ q = _q.permute(0, 2, 1, 3).contiguous().reshape(-1, seq_len, head_dim)
73
+ k = _k.permute(0, 2, 1, 3).contiguous().reshape(-1, seq_len, head_dim)
74
+ cos, sin = self.cos_sin(seq_len, q.device, q.dtype)
75
+ return (q * cos) + (rotate_half(q) * sin), (k * cos) + (rotate_half(k) * sin)
76
+
77
+
78
+ class FalconAttentionFused(nn.Module):
79
+ def __init__(self, args):
80
+ super().__init__()
81
+ self.args = args
82
+ self.n_local_heads = args.n_head
83
+ self.head_dim = args.hidden_size // args.n_head
84
+
85
+ self.query_key_value = nn.Linear(
86
+ args.hidden_size,
87
+ args.n_head * self.head_dim + 2 * self.head_dim,
88
+ bias=False,
89
+ )
90
+
91
+ self.dense = nn.Linear(
92
+ args.n_head * self.head_dim,
93
+ args.hidden_size,
94
+ bias=False,
95
+ )
96
+
97
+ # following fastertransformer definition
98
+
99
+ self.cache_v = (
100
+ torch.zeros(
101
+ (
102
+ max_batch_size,
103
+ 1,
104
+ max_seq_len,
105
+ self.head_dim,
106
+ )
107
+ )
108
+ .cuda()
109
+ .half()
110
+ ) # added to half
111
+ # 8: pack 8 fp16 in FT, if fp32 then use 4
112
+ self.cache_k = (
113
+ torch.zeros(
114
+ (
115
+ max_batch_size,
116
+ 1,
117
+ self.head_dim // 8,
118
+ max_seq_len,
119
+ 8,
120
+ )
121
+ )
122
+ .cuda()
123
+ .half()
124
+ ) # added to half
125
+
126
+ self.rotary_emb = RotaryEmbedding(self.head_dim)
127
+ self.rope_theta = args.rope_theta
128
+ self.rope_scaling = args.rope_scaling
129
+ if self.rope_scaling is None:
130
+ self.rope_scaling = 1.0
131
+ else:
132
+ self.rope_scaling = 1.0 / self.rope_scaling["factor"]
133
+
134
+ def forward(
135
+ self,
136
+ x: torch.Tensor,
137
+ start_pos: int,
138
+ mask: Optional[torch.Tensor],
139
+ ):
140
+ bsz, seqlen, _ = x.shape
141
+
142
+ xqkv = self.query_key_value(x)
143
+ xqkv = xqkv.view(bsz, seqlen, self.n_local_heads + 2, self.head_dim)
144
+ xq = xqkv[:, :, :-2]
145
+ xk = xqkv[:, :, [-2]]
146
+ xv = xqkv[:, :, [-1]]
147
+
148
+ if seqlen > 1:
149
+ xq = xq.view(bsz, seqlen, self.n_local_heads, self.head_dim)
150
+ xk = xk.view(bsz, seqlen, 1, self.head_dim)
151
+ xv = xv.view(bsz, seqlen, 1, self.head_dim)
152
+
153
+ xq, xk = self.rotary_emb(xq, xk)
154
+ xq = (
155
+ xq.reshape(bsz, self.n_local_heads, seqlen, self.head_dim)
156
+ .permute(0, 2, 1, 3)
157
+ .contiguous()
158
+ )
159
+ xk = (
160
+ xk.reshape(bsz, 1, seqlen, self.head_dim)
161
+ .permute(0, 2, 1, 3)
162
+ .contiguous()
163
+ )
164
+
165
+ self.cache_k = self.cache_k.to(xq)
166
+ self.cache_v = self.cache_v.to(xq)
167
+
168
+ values_store = xv.transpose(2, 1)
169
+ keys_store = (
170
+ xk.reshape(bsz, seqlen, 1, self.head_dim // 8, 8)
171
+ .permute(0, 2, 3, 1, 4)
172
+ .contiguous()
173
+ )
174
+
175
+ self.cache_v[:bsz, :, start_pos : start_pos + seqlen, :] = values_store
176
+ self.cache_k[:bsz, :, :, start_pos : start_pos + seqlen, :] = keys_store
177
+
178
+ keys = xk
179
+ values = xv
180
+
181
+ xq = xq.transpose(1, 2)
182
+ keys = keys.transpose(1, 2)
183
+ values = values.transpose(1, 2)
184
+ scores = torch.matmul(xq, keys.transpose(2, 3)) / math.sqrt(self.head_dim)
185
+ if mask is not None:
186
+ scores = scores + mask # (bs, n_local_heads, slen, cache_len + slen)
187
+ scores = F.softmax(scores.float(), dim=-1).type_as(xq)
188
+ output = torch.matmul(scores, values) # (bs, n_local_heads, slen, head_dim)
189
+ output = output.transpose(1, 2).contiguous().view(bsz, seqlen, -1)
190
+ else:
191
+ # xq = xq[:, 0, :, :]
192
+ # xk = xk[:, 0, :, :]
193
+ # xv = xv[:, 0, :, :]
194
+ xq = xq.view(bsz, self.n_local_heads, self.head_dim)
195
+ xk = xk.view(bsz, 1, self.head_dim)
196
+ xv = xv.view(bsz, 1, self.head_dim)
197
+
198
+ output = awq_inference_engine.single_query_attention(
199
+ xq,
200
+ xk,
201
+ xv,
202
+ self.cache_k,
203
+ self.cache_v,
204
+ None,
205
+ # alibi position encodings
206
+ None,
207
+ start_pos,
208
+ self.head_dim,
209
+ self.rope_theta,
210
+ self.rope_scaling,
211
+ True,
212
+ )
213
+ output = output.reshape(bsz, 1, -1)
214
+
215
+ return self.dense(output)
216
+
217
+
218
+ class FalconMLP(nn.Module):
219
+ def __init__(
220
+ self,
221
+ dim: int,
222
+ ):
223
+ super().__init__()
224
+ self.dense_h_to_4h = nn.Linear(dim, 4 * dim, bias=False)
225
+ self.act = nn.GELU()
226
+ self.dense_4h_to_h = nn.Linear(4 * dim, dim, bias=False)
227
+
228
+ def forward(self, x):
229
+ x = self.act(self.dense_h_to_4h(x))
230
+ x = self.dense_4h_to_h(x)
231
+ return x
232
+
233
+
234
+ class TransformerBlock(nn.Module):
235
+ def __init__(self, layer_id: int, args):
236
+ super().__init__()
237
+ self.n_heads = args.n_head
238
+ self.dim = args.hidden_size
239
+ self.head_dim = args.hidden_size // args.n_head
240
+ self.self_attention = FalconAttentionFused(args)
241
+ self.mlp = FalconMLP(dim=args.hidden_size)
242
+ self.layer_id = layer_id
243
+ self.input_layernorm = nn.LayerNorm(
244
+ args.hidden_size, eps=args.layer_norm_epsilon
245
+ )
246
+ # self.post_attention_layernorm = nn.LayerNorm(args.dim, eps=args.norm_eps)
247
+
248
+ def forward(
249
+ self,
250
+ x: torch.Tensor,
251
+ start_pos: int,
252
+ mask: Optional[torch.Tensor],
253
+ ):
254
+ layernorm_output = self.input_layernorm(x)
255
+ h_attn = x + self.self_attention.forward(layernorm_output, start_pos, mask)
256
+ h_mlp = self.mlp(layernorm_output)
257
+ out = h_attn + h_mlp
258
+ return out
259
+
260
+
261
+ class Transformer(nn.Module):
262
+ def __init__(self, params):
263
+ super().__init__()
264
+ self.params = params
265
+ self.vocab_size = params.vocab_size
266
+ self.n_layers = params.n_layer
267
+
268
+ self.word_embeddings = nn.Embedding(params.vocab_size, params.hidden_size)
269
+
270
+ self.h = torch.nn.ModuleList()
271
+ for layer_id in range(params.n_layer):
272
+ self.h.append(TransformerBlock(layer_id, params))
273
+
274
+ self.ln_f = nn.LayerNorm(params.hidden_size, eps=params.layer_norm_epsilon)
275
+
276
+ @torch.inference_mode()
277
+ def forward(self, tokens: torch.Tensor, start_pos: int):
278
+ _bsz, seqlen = tokens.shape
279
+ h = self.word_embeddings(tokens)
280
+
281
+ mask = None
282
+ if seqlen > 1:
283
+ mask = torch.full(
284
+ (1, 1, seqlen, seqlen), float("-inf"), device=tokens.device
285
+ )
286
+ mask = torch.triu(mask, diagonal=start_pos + 1).type_as(h)
287
+ for layer in self.h:
288
+ h = layer(h, start_pos, mask)
289
+ h = self.ln_f(h)
290
+ return h
291
+
292
+
293
+ class FalconForCausalLM(nn.Module):
294
+ def __init__(self, params):
295
+ super().__init__()
296
+ self.config = params
297
+ self.transformer = Transformer(params)
298
+ self.lm_head = nn.Linear(params.hidden_size, params.vocab_size, bias=False)
299
+
300
+ @torch.inference_mode()
301
+ def forward(self, tokens: torch.Tensor, start_pos: int):
302
+ h = self.transformer(tokens, start_pos)
303
+ output = self.lm_head(h) # only compute last logits
304
+ return output.float()
llm-awq/tinychat/models/internvl3.py ADDED
@@ -0,0 +1,383 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from collections import defaultdict, deque
3
+ from typing import Dict, List, Optional, Tuple, Union, Any
4
+ import warnings
5
+ from time import time
6
+
7
+ import torch
8
+ import torch.utils.checkpoint
9
+ from torch import nn
10
+ from torch.nn import CrossEntropyLoss
11
+
12
+ import transformers
13
+ from transformers import (AutoConfig,
14
+ AutoModel,
15
+ AutoTokenizer,
16
+ GenerationConfig,
17
+ PretrainedConfig,
18
+ PreTrainedModel)
19
+ from transformers.modeling_outputs import CausalLMOutputWithPast
20
+ from transformers.modeling_utils import PreTrainedModel
21
+ from transformers.utils import ModelOutput, logging
22
+ from transformers import modeling_utils
23
+
24
+ from .internvl.configuration_internvl import InternVisionConfig, InternVLChatConfig
25
+ from .internvl.internvit import InternVisionModel
26
+ from .internvl.conversation import get_conv_template
27
+ from .internvl.media import load_image, load_video
28
+
29
+ from llava.media import Image, Video
30
+
31
+ from .qwen2 import Qwen2ForCausalLM
32
+ from .llama import LlamaForCausalLM
33
+
34
+ try:
35
+ import flash_attn
36
+ has_flash_attn = True
37
+ except ImportError:
38
+ print('FlashAttention2 is not installed.')
39
+ has_flash_attn = False
40
+
41
+ def skip(*args, **kwargs):
42
+ pass
43
+
44
+ torch.nn.init.kaiming_uniform_ = skip
45
+ torch.nn.init.kaiming_normal_ = skip
46
+ torch.nn.init.uniform_ = skip
47
+ torch.nn.init.normal_ = skip
48
+
49
+ modeling_utils._init_weights = False
50
+
51
+
52
+ logger = logging.get_logger(__name__)
53
+
54
+
55
+ class InternVL3(PreTrainedModel):
56
+ config_class = InternVLChatConfig
57
+ main_input_name = 'pixel_values'
58
+ base_model_prefix = 'language_model'
59
+ _supports_flash_attn_2 = True
60
+ supports_gradient_checkpointing = True
61
+ _no_split_modules = ['InternVisionModel', 'LlamaDecoderLayer', 'Qwen2DecoderLayer']
62
+
63
+ def __init__(self, config: InternVLChatConfig, vision_model=None, language_model=None, use_flash_attn=True):
64
+ super().__init__(config)
65
+
66
+ self.tokenizer = AutoTokenizer.from_pretrained(config.name_or_path, trust_remote_code=True, use_fast=False)
67
+
68
+ image_size = config.force_image_size or config.vision_config.image_size
69
+ patch_size = config.vision_config.patch_size
70
+ self.patch_size = patch_size
71
+ self.select_layer = config.select_layer
72
+ self.template = config.template
73
+ self.num_image_token = int((image_size // patch_size) ** 2 * (config.downsample_ratio ** 2))
74
+ self.downsample_ratio = config.downsample_ratio
75
+ self.ps_version = config.ps_version
76
+ use_flash_attn = use_flash_attn if has_flash_attn else False
77
+ config.vision_config.use_flash_attn = True if use_flash_attn else False
78
+ config.llm_config._attn_implementation = 'flash_attention_2' if use_flash_attn else 'eager'
79
+
80
+ logger.info(f'num_image_token: {self.num_image_token}')
81
+ logger.info(f'ps_version: {self.ps_version}')
82
+ if vision_model is not None:
83
+ self.vision_model = vision_model
84
+ else:
85
+ self.vision_model = InternVisionModel(config.vision_config)
86
+ if language_model is not None:
87
+ self.language_model = language_model
88
+ else:
89
+ if config.llm_config.architectures[0] == 'LlamaForCausalLM':
90
+ self.language_model = LlamaForCausalLM(config.llm_config)
91
+ elif config.llm_config.architectures[0] == 'Qwen2ForCausalLM':
92
+ self.language_model = Qwen2ForCausalLM(config.llm_config)
93
+ else:
94
+ raise NotImplementedError(f'{config.llm_config.architectures[0]} is not implemented.')
95
+
96
+ vit_hidden_size = config.vision_config.hidden_size
97
+ llm_hidden_size = config.llm_config.hidden_size
98
+
99
+ self.mlp1 = nn.Sequential(
100
+ nn.LayerNorm(vit_hidden_size * int(1 / self.downsample_ratio) ** 2),
101
+ nn.Linear(vit_hidden_size * int(1 / self.downsample_ratio) ** 2, llm_hidden_size),
102
+ nn.GELU(),
103
+ nn.Linear(llm_hidden_size, llm_hidden_size)
104
+ )
105
+
106
+ self.img_context_token_id = None
107
+ self.conv_template = get_conv_template(self.template)
108
+ self.system_message = self.conv_template.system_message
109
+
110
+ def freezed_module_patch(self):
111
+ self.vision_model.eval()
112
+ self.language_model.eval()
113
+ self.mlp1.eval()
114
+
115
+ def pixel_shuffle(self, x, scale_factor=0.5):
116
+ n, w, h, c = x.size()
117
+ # N, W, H, C --> N, W, H * scale, C // scale
118
+ x = x.view(n, w, int(h * scale_factor), int(c / scale_factor))
119
+ # N, W, H * scale, C // scale --> N, H * scale, W, C // scale
120
+ x = x.permute(0, 2, 1, 3).contiguous()
121
+ # N, H * scale, W, C // scale --> N, H * scale, W * scale, C // (scale ** 2)
122
+ x = x.view(n, int(h * scale_factor), int(w * scale_factor),
123
+ int(c / (scale_factor * scale_factor)))
124
+ if self.ps_version == 'v1':
125
+ warnings.warn("In ps_version 'v1', the height and width have not been swapped back, "
126
+ 'which results in a transposed image.')
127
+ else:
128
+ x = x.permute(0, 2, 1, 3).contiguous()
129
+ return x
130
+
131
+ @torch.inference_mode()
132
+ def prepare_media(self, conversation):
133
+ prompt = conversation[0]["value"]
134
+ media = {"image": [], "video": []}
135
+ for item in prompt:
136
+ if isinstance(item, Image):
137
+ media["image"].append(load_image(item.path))
138
+ if isinstance(item, Video):
139
+ pixel_values, num_patches_list = load_video(item.path)
140
+ media["video"].extend(pixel_values)
141
+
142
+ return media, num_patches_list if media["video"] else None
143
+
144
+ @torch.inference_mode()
145
+ def extract_features(self, pixel_values):
146
+ if self.select_layer == -1:
147
+ vit_embeds = self.vision_model(
148
+ pixel_values=pixel_values,
149
+ output_hidden_states=False,
150
+ return_dict=True).last_hidden_state
151
+ else:
152
+ vit_embeds = self.vision_model(
153
+ pixel_values=pixel_values,
154
+ output_hidden_states=True,
155
+ return_dict=True).hidden_states[self.select_layer]
156
+ vit_embeds = vit_embeds[:, 1:, :]
157
+
158
+ h = w = int(vit_embeds.shape[1] ** 0.5)
159
+ vit_embeds = vit_embeds.reshape(vit_embeds.shape[0], h, w, -1)
160
+ vit_embeds = self.pixel_shuffle(vit_embeds, scale_factor=self.downsample_ratio)
161
+ vit_embeds = vit_embeds.reshape(vit_embeds.shape[0], -1, vit_embeds.shape[-1])
162
+ vit_embeds = self.mlp1(vit_embeds)
163
+ return vit_embeds
164
+
165
+ @torch.inference_mode()
166
+ def _embed(
167
+ self,
168
+ input_ids: torch.Tensor,
169
+ media: Dict[str, List[torch.Tensor]],
170
+ media_config: Dict[str, Dict[str, Any]],
171
+ labels: Optional[torch.Tensor],
172
+ attention_mask: Optional[torch.Tensor],
173
+ ):
174
+ attention_mask = (
175
+ attention_mask
176
+ if attention_mask is not None
177
+ else torch.ones_like(input_ids, dtype=torch.bool)
178
+ )
179
+
180
+ if media["image"]:
181
+ pixel_values = torch.cat(media["image"], dim=0).half().cuda()
182
+ elif media["video"]:
183
+ pixel_values = torch.cat(media["video"], dim=0).half().cuda()
184
+
185
+ vit_embeds = self.extract_features(pixel_values)
186
+
187
+ input_embeds = self.language_model.get_input_embeddings()(input_ids)
188
+ B, N, C = input_embeds.shape
189
+ input_embeds = input_embeds.reshape(B * N, C)
190
+
191
+ input_ids = input_ids.reshape(B * N)
192
+ selected = (input_ids == self.img_context_token_id)
193
+
194
+ input_embeds[selected] = input_embeds[selected] * 0.0 + vit_embeds.reshape(-1, C)
195
+
196
+ input_embeds = input_embeds.reshape(B, N, C)
197
+
198
+ return input_embeds, None, attention_mask
199
+
200
+ @torch.inference_mode()
201
+ def benchmark(self, prompt: Union[str, List], quant_llm) -> None:
202
+ media = {"image": [], "video": []}
203
+ question = ""
204
+ for item in prompt:
205
+ if isinstance(item, str):
206
+ question += item
207
+ if isinstance(item, Image):
208
+ media["image"].append(load_image(item.path))
209
+ if isinstance(item, Video):
210
+ pixel_values, num_patches_list = load_video(item.path)
211
+ media["video"].extend(pixel_values)
212
+
213
+ if media["image"]:
214
+ num_patches_list = [image.size(0) for image in media["image"]]
215
+
216
+ if media["image"] and '<image>' not in question:
217
+ question = '<image>\n' + question
218
+
219
+ if media["video"] and '<image>' not in question:
220
+ video_prefix = ''.join([f'Frame{i+1}: <image>\n' for i in range(len(num_patches_list))])
221
+ question = video_prefix + question
222
+
223
+ template = get_conv_template(self.template)
224
+ template.system_message = self.system_message
225
+ eos_token_id = self.tokenizer.convert_tokens_to_ids(template.sep.strip())
226
+
227
+ template.append_message(template.roles[0], question)
228
+ template.append_message(template.roles[1], None)
229
+ query = template.get_prompt()
230
+
231
+ IMG_START_TOKEN = '<img>'
232
+ IMG_END_TOKEN = '</img>'
233
+ IMG_CONTEXT_TOKEN = '<IMG_CONTEXT>'
234
+
235
+ img_context_token_id = self.tokenizer.convert_tokens_to_ids(IMG_CONTEXT_TOKEN)
236
+ self.img_context_token_id = img_context_token_id
237
+
238
+ for num_patches in num_patches_list:
239
+ image_tokens = IMG_START_TOKEN + IMG_CONTEXT_TOKEN * self.num_image_token * num_patches + IMG_END_TOKEN
240
+ query = query.replace('<image>', image_tokens, 1)
241
+
242
+ model_inputs = self.tokenizer(query, return_tensors='pt')
243
+ input_ids = model_inputs['input_ids'].to(self.device)
244
+ attention_mask = model_inputs['attention_mask'].to(self.device)
245
+
246
+ for i in range(10):
247
+ torch.cuda.synchronize()
248
+ t_st = time()
249
+ inputs_embeds, _, attention_mask = self._embed(
250
+ input_ids=input_ids,
251
+ media=media,
252
+ media_config=None,
253
+ labels=None,
254
+ attention_mask=attention_mask
255
+ )
256
+ torch.cuda.synchronize()
257
+ t_ed = time()
258
+ torch.cuda.empty_cache()
259
+
260
+ if media["image"]:
261
+ print(
262
+ "Time of vision tower and others is {:.5f} s for {} images ({} x {} x {})".format(
263
+ t_ed - t_st, sum(num_patches_list), media["image"][0].shape[1], media["image"][0].shape[2], media["image"][0].shape[3]
264
+ )
265
+ )
266
+ elif media["video"]:
267
+ print(
268
+ "Time of vision tower and others is {:.5f} s for {} video frames ({} x {} x {})".format(
269
+ t_ed - t_st, sum(num_patches_list), media["video"][0].shape[1], media["video"][0].shape[2], media["video"][0].shape[3]
270
+ )
271
+ )
272
+ output = self.language_model.benchmark(
273
+ inputs_embeds=inputs_embeds,
274
+ attention_mask=attention_mask,
275
+ quant_llm=quant_llm
276
+ )
277
+ response = self.tokenizer.decode(output[0], skip_special_tokens=True).strip()
278
+
279
+ return response
280
+
281
+ @torch.inference_mode()
282
+ def stream_gen(
283
+ self,
284
+ input_ids,
285
+ media,
286
+ media_cfg,
287
+ start_pos,
288
+ chunk_prefilling,
289
+ quant_llm,
290
+ attention_mask=None,
291
+ ) -> str:
292
+ if media is None:
293
+ inputs_embeds = self.language_model.get_input_embeddings()(input_ids ).clone()
294
+ else:
295
+ inputs_embeds, _, _ = self._embed(input_ids, media, None, None, attention_mask)
296
+
297
+ length = inputs_embeds.shape[1]
298
+ if quant_llm:
299
+ out = self.language_model(None, start_pos, inputs_embeds, chunk_prefilling)
300
+ else:
301
+ out = self.language_model.forwardfp16(None, start_pos, inputs_embeds, chunk_prefilling)
302
+ return out, length
303
+
304
+ @torch.inference_mode()
305
+ def forward(
306
+ self,
307
+ pixel_values: torch.FloatTensor,
308
+ input_ids: torch.LongTensor = None,
309
+ attention_mask: Optional[torch.Tensor] = None,
310
+ position_ids: Optional[torch.LongTensor] = None,
311
+ image_flags: Optional[torch.LongTensor] = None,
312
+ past_key_values: Optional[List[torch.FloatTensor]] = None,
313
+ labels: Optional[torch.LongTensor] = None,
314
+ use_cache: Optional[bool] = None,
315
+ output_attentions: Optional[bool] = None,
316
+ output_hidden_states: Optional[bool] = None,
317
+ return_dict: Optional[bool] = None,
318
+ ) -> Union[Tuple, CausalLMOutputWithPast]:
319
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
320
+
321
+ image_flags = image_flags.squeeze(-1)
322
+ input_embeds = self.language_model.get_input_embeddings()(input_ids).clone()
323
+
324
+ vit_embeds = self.extract_feature(pixel_values)
325
+ vit_embeds = vit_embeds[image_flags == 1]
326
+ vit_batch_size = pixel_values.shape[0]
327
+
328
+ B, N, C = input_embeds.shape
329
+ input_embeds = input_embeds.reshape(B * N, C)
330
+
331
+ if torch.distributed.is_initialized() and torch.distributed.get_rank() == 0:
332
+ print(f'dynamic ViT batch size: {vit_batch_size}, images per sample: {vit_batch_size / B}, dynamic token length: {N}')
333
+
334
+ input_ids = input_ids.reshape(B * N)
335
+ selected = (input_ids == self.img_context_token_id)
336
+ try:
337
+ input_embeds[selected] = input_embeds[selected] * 0.0 + vit_embeds.reshape(-1, C)
338
+ except Exception as e:
339
+ vit_embeds = vit_embeds.reshape(-1, C)
340
+ print(f'warning: {e}, input_embeds[selected].shape={input_embeds[selected].shape}, '
341
+ f'vit_embeds.shape={vit_embeds.shape}')
342
+ n_token = min(selected.sum(), vit_embeds.size(0))
343
+ input_embeds[selected][:n_token] = input_embeds[selected][:n_token] * 0.0 + vit_embeds[:n_token]
344
+
345
+ input_embeds = input_embeds.reshape(B, N, C)
346
+
347
+ outputs = self.language_model(
348
+ inputs_embeds=input_embeds,
349
+ attention_mask=attention_mask,
350
+ position_ids=position_ids,
351
+ past_key_values=past_key_values,
352
+ use_cache=use_cache,
353
+ output_attentions=output_attentions,
354
+ output_hidden_states=output_hidden_states,
355
+ return_dict=return_dict,
356
+ )
357
+ logits = outputs.logits
358
+
359
+ loss = None
360
+ if labels is not None:
361
+ # Shift so that tokens < n predict n
362
+ shift_logits = logits[..., :-1, :].contiguous()
363
+ shift_labels = labels[..., 1:].contiguous()
364
+ # Flatten the tokens
365
+ loss_fct = CrossEntropyLoss()
366
+ shift_logits = shift_logits.view(-1, self.language_model.config.vocab_size)
367
+ shift_labels = shift_labels.view(-1)
368
+ # Enable model parallelism
369
+ shift_labels = shift_labels.to(shift_logits.device)
370
+ loss = loss_fct(shift_logits, shift_labels)
371
+
372
+ if not return_dict:
373
+ output = (logits,) + outputs[1:]
374
+ return (loss,) + output if loss is not None else output
375
+
376
+ return CausalLMOutputWithPast(
377
+ loss=loss,
378
+ logits=logits,
379
+ past_key_values=outputs.past_key_values,
380
+ hidden_states=outputs.hidden_states,
381
+ attentions=outputs.attentions,
382
+ )
383
+
llm-awq/tinychat/models/nvila/builder.py ADDED
@@ -0,0 +1,291 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2024 NVIDIA CORPORATION & AFFILIATES
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ #
15
+ # SPDX-License-Identifier: Apache-2.0
16
+
17
+ import math
18
+ import os
19
+ import os.path as osp
20
+ import warnings
21
+ from dataclasses import asdict
22
+ from typing import Tuple
23
+
24
+ import torch
25
+ from huggingface_hub import file_exists, repo_exists
26
+ from huggingface_hub.utils import HFValidationError
27
+ from transformers import (
28
+ AutoConfig,
29
+ AutoModelForCausalLM,
30
+ AutoTokenizer,
31
+ PretrainedConfig,
32
+ PreTrainedModel,
33
+ PreTrainedTokenizer,
34
+ )
35
+
36
+ from llava.constants import MEDIA_TOKENS
37
+ from llava.model.utils import packing
38
+ from llava.utils.logging import logger
39
+ from llava.utils.tokenizer import infer_stop_tokens
40
+
41
+
42
+ def has_tokenizer(repo_id_or_path: str) -> bool:
43
+ # Check if the tokenizer is in a local directory
44
+ if osp.exists(osp.join(repo_id_or_path, "tokenizer_config.json")):
45
+ return True
46
+
47
+ # Check if the tokenizer is in a Hugging Face Hub repo
48
+ try:
49
+ return repo_exists(repo_id_or_path) and file_exists(
50
+ repo_id_or_path, "tokenizer_config.json"
51
+ )
52
+ except HFValidationError:
53
+ return False
54
+
55
+
56
+ def context_length_extension(config):
57
+ orig_ctx_len = getattr(config, "max_position_embeddings", None)
58
+ model_max_length = getattr(config, "model_max_length", None)
59
+ if orig_ctx_len and model_max_length > orig_ctx_len:
60
+ print(f"Scaling RoPE from {orig_ctx_len} to {model_max_length}")
61
+ scaling_factor = float(math.ceil(model_max_length / orig_ctx_len))
62
+ config.rope_scaling = {"type": "linear", "factor": scaling_factor}
63
+ return config
64
+
65
+
66
+ def build_llm_and_tokenizer(
67
+ model_name_or_path: str,
68
+ config: PretrainedConfig,
69
+ attn_implementation=None,
70
+ model_max_length=None,
71
+ *args,
72
+ **kwargs,
73
+ ) -> Tuple[PreTrainedModel, PreTrainedTokenizer]:
74
+ # print(model_name_or_path)
75
+ llm_cfg = AutoConfig.from_pretrained(model_name_or_path)
76
+ llm_cfg._attn_implementation = attn_implementation
77
+ llm_cfg.model_max_length = model_max_length
78
+ if model_max_length is not None:
79
+ context_length_extension(llm_cfg)
80
+
81
+ # Quantization related
82
+ quantization_restore_from_checkpoint = False
83
+ if kwargs.get("quantize_model_class") is not None:
84
+ assert kwargs.get("model_args") is not None
85
+ quantize_model_class = kwargs.pop("quantize_model_class", None)
86
+ model_args = kwargs.pop("model_args", None)
87
+
88
+ if (
89
+ quantize_model_class == "QLlamaForCausalLM"
90
+ ): # TODO: Also change the name of this class
91
+ from .qllama import QLlamaConfig
92
+
93
+ llm_cfg.architectures = "QLlamaForCausalLM"
94
+ _attn_implementation = llm_cfg._attn_implementation
95
+ llm_cfg = QLlamaConfig(**llm_cfg.to_dict())
96
+ llm_cfg._attn_implementation = _attn_implementation
97
+ elif (
98
+ quantize_model_class == "QMemLlamaForCausalLM"
99
+ ): # TODO: Also change the name of this class
100
+ from .qmemllama import QMemLlamaConfig
101
+
102
+ llm_cfg.architectures = "QMemLlamaForCausalLM"
103
+ llm_cfg = QMemLlamaConfig(**llm_cfg.to_dict())
104
+ elif quantize_model_class == "FP8LinearQwen2ForCausalLM":
105
+ from .configuration_quantize import QuantizationConfig
106
+ from .fp8linearqwen2 import FP8LinearQwen2Config
107
+
108
+ llm_cfg.architectures = "FP8LinearQwen2ForCausalLM"
109
+ coat_fp8_args = QuantizationConfig(**asdict(model_args))
110
+
111
+ # Remove the quantization args from llm_cfg and make it a independent config
112
+ model_args_dict = asdict(model_args)
113
+ for key in asdict(coat_fp8_args).keys():
114
+ model_args_dict.pop(key, None)
115
+
116
+ llm_cfg.coat_fp8_args = asdict(coat_fp8_args)
117
+ _attn_implementation = llm_cfg._attn_implementation
118
+
119
+ llm_cfg = FP8LinearQwen2Config(**llm_cfg.to_dict())
120
+ llm_cfg._attn_implementation = _attn_implementation
121
+
122
+ elif quantize_model_class == "FP8ActivationQwen2ForCausalLM":
123
+ from ..coat.activation.models._fp8_quantization_config import (
124
+ QuantizationConfig,
125
+ )
126
+ from .fp8activationqwen2 import FP8ActivationQwen2Config
127
+
128
+ quantization_restore_from_checkpoint = True
129
+
130
+ llm_cfg.architectures = "FP8ActivationQwen2ForCausalLM"
131
+ coat_fp8_args = QuantizationConfig(**asdict(model_args))
132
+
133
+ # Remove the quantization args from llm_cfg and make it a independent config
134
+ model_args_dict = asdict(model_args)
135
+ for key in asdict(coat_fp8_args).keys():
136
+ model_args_dict.pop(key, None)
137
+
138
+ llm_cfg.coat_fp8_args = asdict(coat_fp8_args)
139
+ _attn_implementation = llm_cfg._attn_implementation
140
+
141
+ llm_cfg = FP8ActivationQwen2Config(**llm_cfg.to_dict())
142
+ llm_cfg._attn_implementation = _attn_implementation
143
+
144
+ elif quantize_model_class == "FP8ActivationResidualQwen2ForCausalLM":
145
+ from ..coat.activation.models._fp8_quantization_config import (
146
+ QuantizationConfig,
147
+ )
148
+ from .fp8activationresidualqwen2 import FP8ActivationResidualQwen2Config
149
+
150
+ quantization_restore_from_checkpoint = True
151
+
152
+ llm_cfg.architectures = "FP8ActivationResidualQwen2ForCausalLM"
153
+ coat_fp8_args = QuantizationConfig(**asdict(model_args))
154
+
155
+ # Remove the quantization args from llm_cfg and make it a independent config
156
+ model_args_dict = asdict(model_args)
157
+ for key in asdict(coat_fp8_args).keys():
158
+ model_args_dict.pop(key, None)
159
+
160
+ llm_cfg.coat_fp8_args = asdict(coat_fp8_args)
161
+ _attn_implementation = llm_cfg._attn_implementation
162
+
163
+ llm_cfg = FP8ActivationResidualQwen2Config(**llm_cfg.to_dict())
164
+ llm_cfg._attn_implementation = _attn_implementation
165
+ else:
166
+ raise ValueError(
167
+ f"{quantize_model_class} is not supported quantize_model_class."
168
+ )
169
+
170
+ kwargs.pop("quantize_model_class", None)
171
+
172
+ if quantize_model_class in [
173
+ "FP8LinearQwen2ForCausalLM",
174
+ "FP8ActivationQwen2ForCausalLM",
175
+ "FP8ActivationResidualQwen2ForCausalLM",
176
+ ]: # Remove the quantization args from llm_cfg and make it a independent config
177
+ llm_cfg.update(model_args_dict)
178
+ else:
179
+ llm_cfg.update(asdict(model_args))
180
+ # print(model_args)
181
+
182
+ if quantization_restore_from_checkpoint:
183
+ fp8_model_name_or_path = kwargs.pop("fp8_llm_cfg", None)
184
+
185
+ llm = AutoModelForCausalLM.from_pretrained(
186
+ fp8_model_name_or_path,
187
+ config=llm_cfg,
188
+ torch_dtype=eval(config.model_dtype),
189
+ *args,
190
+ **kwargs,
191
+ )
192
+
193
+ else:
194
+ llm = AutoModelForCausalLM.from_pretrained(
195
+ model_name_or_path,
196
+ config=llm_cfg,
197
+ torch_dtype=eval(config.model_dtype),
198
+ *args,
199
+ **kwargs,
200
+ )
201
+ packing.patch(llm)
202
+
203
+ # Locate the tokenizer.
204
+ llm_path = model_name_or_path
205
+ if not has_tokenizer(llm_path):
206
+ llm_path = osp.join(llm_path, "llm")
207
+ if not has_tokenizer(llm_path):
208
+ raise ValueError(f"Cannot find tokenizer in {llm_path}.")
209
+
210
+ tokenizer = AutoTokenizer.from_pretrained(
211
+ llm_path, padding_side="right", use_fast=False, legacy=False
212
+ )
213
+ if model_max_length is not None:
214
+ tokenizer.model_max_length = model_max_length
215
+
216
+ # Load chat template if specified.
217
+ if getattr(config, "chat_template", None) is not None:
218
+ logger.info(f"Using chat template: {config.chat_template}")
219
+ fpath = os.path.join(
220
+ os.path.dirname(__file__), "chat_templates", f"{config.chat_template}.jinja"
221
+ )
222
+ with open(fpath) as fd:
223
+ chat_template = fd.read()
224
+ tokenizer.chat_template = chat_template.replace(" ", "").replace("\n", "")
225
+
226
+ # Set stop tokens for the tokenizer
227
+ tokenizer.stop_tokens = infer_stop_tokens(tokenizer)
228
+ tokenizer.stop_token_ids = tokenizer.convert_tokens_to_ids(tokenizer.stop_tokens)
229
+
230
+ # Add media tokens to the tokenizer
231
+ tokenizer.media_tokens = MEDIA_TOKENS
232
+ tokenizer.media_token_ids = {}
233
+ for name, token in MEDIA_TOKENS.items():
234
+ tokenizer.add_tokens([token], special_tokens=True)
235
+ tokenizer.media_token_ids[name] = tokenizer.convert_tokens_to_ids(token)
236
+
237
+ # TODO(ligeng): is this necessary for llava?
238
+ config.hidden_size = llm.config.hidden_size
239
+ return llm, tokenizer
240
+
241
+
242
+ def build_tokenizer(
243
+ model_name_or_path: str,
244
+ config: PretrainedConfig,
245
+ attn_implementation=None,
246
+ model_max_length=None,
247
+ *args,
248
+ **kwargs,
249
+ ) -> Tuple[PreTrainedModel, PreTrainedTokenizer]:
250
+ # print(model_name_or_path)
251
+ llm_cfg = AutoConfig.from_pretrained(model_name_or_path)
252
+ llm_cfg._attn_implementation = attn_implementation
253
+ llm_cfg.model_max_length = model_max_length
254
+ if model_max_length is not None:
255
+ context_length_extension(llm_cfg)
256
+
257
+ # Locate the tokenizer.
258
+ llm_path = model_name_or_path
259
+ if not has_tokenizer(llm_path):
260
+ llm_path = osp.join(llm_path, "llm")
261
+ if not has_tokenizer(llm_path):
262
+ raise ValueError(f"Cannot find tokenizer in {llm_path}.")
263
+
264
+ tokenizer = AutoTokenizer.from_pretrained(
265
+ llm_path, padding_side="right", use_fast=False, legacy=False
266
+ )
267
+ if model_max_length is not None:
268
+ tokenizer.model_max_length = model_max_length
269
+
270
+ # Load chat template if specified.
271
+ if getattr(config, "chat_template", None) is not None:
272
+ logger.info(f"Using chat template: {config.chat_template}")
273
+ fpath = os.path.join(
274
+ os.path.dirname(__file__), "chat_templates", f"{config.chat_template}.jinja"
275
+ )
276
+ with open(fpath) as fd:
277
+ chat_template = fd.read()
278
+ tokenizer.chat_template = chat_template.replace(" ", "").replace("\n", "")
279
+
280
+ # Set stop tokens for the tokenizer
281
+ tokenizer.stop_tokens = infer_stop_tokens(tokenizer)
282
+ tokenizer.stop_token_ids = tokenizer.convert_tokens_to_ids(tokenizer.stop_tokens)
283
+
284
+ # Add media tokens to the tokenizer
285
+ tokenizer.media_tokens = MEDIA_TOKENS
286
+ tokenizer.media_token_ids = {}
287
+ for name, token in MEDIA_TOKENS.items():
288
+ tokenizer.add_tokens([token], special_tokens=True)
289
+ tokenizer.media_token_ids[name] = tokenizer.convert_tokens_to_ids(token)
290
+
291
+ return tokenizer
llm-awq/tinychat/models/nvila/llava_arch.py ADDED
@@ -0,0 +1,909 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Copyright 2023 Haotian Liu
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import copy
16
+ import json
17
+ import logging
18
+ import os
19
+ import os.path as osp
20
+ import warnings
21
+ from abc import ABC
22
+ from collections import OrderedDict, defaultdict, deque
23
+ from itertools import chain
24
+ from typing import Any, Dict, List, Optional, Tuple, Union
25
+
26
+ import torch
27
+ import torch.distributed as dist
28
+ import torch.nn.functional as F
29
+ from einops import rearrange
30
+ from hydra.utils import instantiate
31
+ from transformers import AutoConfig, GenerationConfig, PreTrainedModel
32
+ from transformers.modeling_utils import ContextManagers, no_init_weights
33
+ from time import time
34
+ from llava.constants import DEFAULT_IMAGE_TOKEN, IGNORE_INDEX
35
+ from llava.mm_utils import process_image, process_images
36
+ from llava.model.configuration_llava import LlavaConfig
37
+ from llava.model.language_model.builder import build_llm_and_tokenizer
38
+ from llava.model.multimodal_encoder.builder import build_vision_tower
39
+ from llava.model.multimodal_projector.builder import build_mm_projector
40
+ from llava.model.utils import get_model_config
41
+
42
+ # from llava.train.sequence_parallel import get_pg_manager
43
+ from llava.utils import distributed as dist
44
+ from llava.utils.media import extract_media
45
+ from llava.utils.tokenizer import tokenize_conversation
46
+ from .builder import build_tokenizer
47
+
48
+
49
+ class LlavaMetaModel(ABC):
50
+ def init_vlm(self, config, *args, **kwargs):
51
+ # TODO(ligeng): figure out how from_config and from_pretrained works in HF implementation.
52
+ if (
53
+ hasattr(self, "llm")
54
+ or hasattr(self, "vision_tower")
55
+ or hasattr(self, "mm_projector")
56
+ ):
57
+ # already initialized, skipped
58
+ return
59
+
60
+ model_dtype = getattr(config, "model_dtype", "torch.float16")
61
+ if not hasattr(config, "model_dtype"):
62
+ warnings.warn(
63
+ "model_dtype not found in config, defaulting to torch.float16."
64
+ )
65
+ config.model_dtype = model_dtype
66
+
67
+ cfgs = get_model_config(config)
68
+ if len(cfgs) == 3:
69
+ self.llm_cfg, vision_tower_cfg, mm_projector_cfg = cfgs
70
+ else:
71
+ raise ValueError(
72
+ "`llm_cfg` `mm_projector_cfg` `vision_tower_cfg` not found in the config."
73
+ )
74
+ self.tokenizer = build_tokenizer(self.llm_cfg, config, *args, **kwargs)
75
+ self.vision_tower = build_vision_tower(vision_tower_cfg, config)
76
+ self.mm_projector = build_mm_projector(mm_projector_cfg, config)
77
+
78
+ self.encoders = {}
79
+ for name in ["image", "video"]:
80
+ config = getattr(self.config, f"{name}_encoder")
81
+ if isinstance(config, str):
82
+ config = json.loads(config)
83
+ self.encoders[name] = instantiate(config, parent=self)
84
+
85
+ self.post_config()
86
+ self.is_loaded = True
87
+
88
+ assert (
89
+ self.vision_tower is not None or self.mm_projector is not None
90
+ ), "At least one of the components must be instantiated."
91
+
92
+ @classmethod
93
+ def load_from_config(cls, model_path_or_config, *args, **kwargs):
94
+ pass
95
+
96
+ ## FIXME we will use this function to load model in the future
97
+ @classmethod
98
+ def load_pretrained(cls, model_path_or_config, *args, **kwargs):
99
+ kwargs.pop("config", None)
100
+
101
+ if isinstance(model_path_or_config, str):
102
+ config = AutoConfig.from_pretrained(model_path_or_config)
103
+ elif isinstance(model_path_or_config, LlavaConfig):
104
+ config = model_path_or_config
105
+ else:
106
+ raise NotImplementedError(
107
+ f"wrong type, {type(model_path_or_config)} \
108
+ {isinstance(model_path_or_config, LlavaConfig)}"
109
+ )
110
+
111
+ model_dtype = getattr(config, "model_dtype", "torch.float16")
112
+ if not hasattr(config, "model_dtype"):
113
+ warnings.warn(
114
+ "model_dtype not found in config, defaulting to torch.float16."
115
+ )
116
+ config.model_dtype = model_dtype
117
+
118
+ cfgs = get_model_config(config)
119
+ if len(cfgs) == 3:
120
+ llm_cfg, vision_tower_cfg, mm_projector_cfg = cfgs
121
+ else:
122
+ raise ValueError(
123
+ "`llm_cfg` `mm_projector_cfg` `vision_tower_cfg` not found in the config."
124
+ )
125
+
126
+ # print(llm_cfg, vision_tower_cfg, mm_projector_cfg); input("DEBUG load_pretrained")
127
+ init_context = [
128
+ no_init_weights(_enable=True),
129
+ ]
130
+ # print("Before Init Context")
131
+ # if hasattr(config, "deepspeed") and "mics" in config.deepspeed:
132
+ # print("Using MiCS_Init")
133
+ # import deepspeed
134
+ # init_context.append(deepspeed.zero.MiCS_Init(config_dict_or_path=config.deepspeed))
135
+ with ContextManagers(init_context):
136
+ vlm = cls(config, *args, **kwargs)
137
+ # print(llm_cfg, vision_tower_cfg, mm_projector_cfg); input("DEBUG load_pretrained finish")
138
+
139
+ if (
140
+ hasattr(vlm, "llm")
141
+ or hasattr(vlm, "vision_tower")
142
+ or hasattr(vlm, "mm_projector")
143
+ ):
144
+ if vlm.is_loaded:
145
+ return vlm
146
+
147
+ vlm.llm, vlm.tokenizer = build_llm_and_tokenizer(
148
+ llm_cfg, config, *args, **kwargs
149
+ )
150
+ vlm.vision_tower = build_vision_tower(vision_tower_cfg, config)
151
+ vlm.mm_projector = build_mm_projector(mm_projector_cfg, config)
152
+
153
+ self.post_config()
154
+ self.is_loaded = True
155
+
156
+ # FIXME(ligeng, yunhao): llm should never be none here.
157
+ assert (
158
+ vlm.llm is not None
159
+ or vlm.vision_tower is not None
160
+ or vlm.mm_projector is not None
161
+ ), "At least one of the components must be instantiated."
162
+ return vlm
163
+
164
+ ## FIXME we will use this function to save the model in the future
165
+ def save_pretrained(self, output_dir, state_dict=None):
166
+ if state_dict is None:
167
+ # other wise fetch from deepspeed
168
+ # state_dict = accelerator.get_state_dict(is_deepspeed_enabled)
169
+ state_dict = self.state_dict()
170
+
171
+ if getattr(self, "tokenizer", None):
172
+ self.tokenizer.save_pretrained(osp.join(output_dir, "llm"))
173
+
174
+ if self.get_llm():
175
+ print(f"saving llm to {osp.join(output_dir, 'llm')}")
176
+ self.llm.config._name_or_path = osp.join(output_dir, "llm")
177
+ llm_state_dict = OrderedDict(
178
+ {k.split("llm.")[-1]: v for k, v in state_dict.items() if "llm" in k}
179
+ )
180
+ self.llm.save_pretrained(
181
+ os.path.join(output_dir, "llm"), state_dict=llm_state_dict
182
+ )
183
+ self.config.llm_cfg = self.llm.config
184
+
185
+ if self.get_vision_tower():
186
+ print(f"saving vision_tower to {osp.join(output_dir, 'vision_tower')}")
187
+ self.vision_tower.config._name_or_path = osp.join(
188
+ output_dir, "vision_tower"
189
+ )
190
+ vision_tower_state_dict = OrderedDict(
191
+ {
192
+ k.split("vision_tower.vision_tower.")[-1]: v
193
+ for k, v in state_dict.items()
194
+ if "vision_tower" in k
195
+ }
196
+ )
197
+ self.vision_tower.vision_tower.save_pretrained(
198
+ os.path.join(output_dir, "vision_tower"),
199
+ state_dict=vision_tower_state_dict,
200
+ )
201
+ self.vision_tower.image_processor.save_pretrained(
202
+ os.path.join(output_dir, "vision_tower")
203
+ )
204
+ self.config.vision_tower_cfg = self.vision_tower.config
205
+ if hasattr(self.config.vision_tower_cfg, "auto_map"):
206
+ if "radio" not in self.get_vision_tower().__class__.__name__.lower():
207
+ delattr(self.config.vision_tower_cfg, "auto_map")
208
+
209
+ if self.get_mm_projector():
210
+ print(f"saving mm_projector to {osp.join(output_dir, 'mm_projector')}")
211
+ self.mm_projector.config._name_or_path = osp.join(
212
+ output_dir, "mm_projector"
213
+ )
214
+ mm_projector_state_dict = OrderedDict(
215
+ {
216
+ k.split("mm_projector.")[-1]: v
217
+ for k, v in state_dict.items()
218
+ if "mm_projector" in k
219
+ }
220
+ )
221
+ self.mm_projector.save_pretrained(
222
+ os.path.join(output_dir, "mm_projector"),
223
+ state_dict=mm_projector_state_dict,
224
+ )
225
+ self.config.mm_projector_cfg = self.mm_projector.config
226
+ ## update and save top-level config
227
+ self.config._name_or_path = output_dir
228
+ self.config.architectures = [self.__class__.__name__]
229
+ self.config.save_pretrained(output_dir)
230
+
231
+ def get_llm(self):
232
+ llm = getattr(self, "llm", None)
233
+ if type(llm) is list:
234
+ llm = llm[0]
235
+ return llm
236
+
237
+ def get_lm_head(self):
238
+ lm_head = getattr(self.get_llm(), "lm_head", None)
239
+ return lm_head
240
+
241
+ def get_vision_tower(self):
242
+ vision_tower = getattr(self, "vision_tower", None)
243
+ if type(vision_tower) is list:
244
+ vision_tower = vision_tower[0]
245
+ return vision_tower
246
+
247
+ def get_mm_projector(self):
248
+ mm_projector = getattr(self, "mm_projector", None)
249
+ if type(mm_projector) is list:
250
+ mm_projector = mm_projector[0]
251
+ return mm_projector
252
+
253
+ def post_config(self):
254
+
255
+ if getattr(self.config, "vision_tower_cfg", None) is None:
256
+ self.config.vision_tower_cfg = self.vision_tower.config
257
+ if getattr(self.config, "mm_projector_cfg", None) is None:
258
+ self.config.mm_projector_cfg = self.mm_projector.config
259
+
260
+ @staticmethod
261
+ def merge_chessboard(x, num_split_h, num_split_w):
262
+ """
263
+ x: b * n * c or b * h * w * c
264
+ out: b * c * h * w
265
+ Assuming x contains num_split**2 sub-squares concatenated along batch dimension, merge the sub-squares back to the original whole square.
266
+ """
267
+ B = x.shape[0]
268
+ if x.dim() == 3:
269
+ N = x.shape[1]
270
+ x = rearrange(x, "b (h w) c -> b c h w", h=int(N**0.5), w=int(N**0.5))
271
+
272
+ assert B % (num_split_h * num_split_w) == 0
273
+ b = B // (num_split_h * num_split_w)
274
+
275
+ x_merge = torch.cat(
276
+ [
277
+ torch.cat(
278
+ [
279
+ x[(i * num_split_w + j) * b : (i * num_split_w + j + 1) * b]
280
+ for j in range(num_split_w)
281
+ ],
282
+ dim=-1,
283
+ )
284
+ for i in range(num_split_h)
285
+ ],
286
+ dim=-2,
287
+ )
288
+
289
+ return x_merge
290
+
291
+ @staticmethod
292
+ def split_chessboard(x, num_split_h, num_split_w):
293
+ """
294
+ x: b * c * h * w
295
+ out: b * c * h * w
296
+ Deividing x into num_split**2 sub-squares, and concatenate all the sub-squares on the batch dimension
297
+ """
298
+ B, C, H, W = x.shape
299
+ assert H % num_split_h == 0 and W % num_split_w == 0
300
+ h, w = H // num_split_h, W // num_split_w
301
+ x_split = torch.cat(
302
+ [
303
+ x[:, :, i * h : (i + 1) * h, j * w : (j + 1) * w]
304
+ for i in range(num_split_h)
305
+ for j in range(num_split_w)
306
+ ],
307
+ dim=0,
308
+ )
309
+ return x_split
310
+
311
+ def merge_features_for_dynamic_s2(self, image_features, block_sizes):
312
+ scales = self.get_vision_tower().scales
313
+ resize_output_to_scale_idx = self.get_vision_tower().resize_output_to_scale_idx
314
+
315
+ image_features_each_image = []
316
+ new_block_sizes = []
317
+ block_cnt = 0
318
+ for block_size_each_image in block_sizes:
319
+ if block_size_each_image is None:
320
+ cur_features = image_features[block_cnt : block_cnt + 1]
321
+ cur_features = rearrange(
322
+ cur_features,
323
+ "1 (h w) c -> 1 c h w",
324
+ h=int(cur_features.shape[1] ** 0.5),
325
+ )
326
+ cur_features = cur_features.repeat(1, len(scales), 1, 1)
327
+ image_features_each_image.append(cur_features)
328
+ new_block_sizes.append((1, 1))
329
+ block_cnt += 1
330
+ else:
331
+ cur_features_each_scale = []
332
+ for scale in scales[:-1]:
333
+ num_blocks_this_scale = (scale // scales[0]) ** 2
334
+ cur_features_each_scale.append(
335
+ self.merge_chessboard(
336
+ image_features[
337
+ block_cnt : block_cnt + num_blocks_this_scale
338
+ ],
339
+ num_split_h=scale // scales[0],
340
+ num_split_w=scale // scales[0],
341
+ )
342
+ ) # 1 * C * H * W
343
+ block_cnt += num_blocks_this_scale
344
+ num_blocks_last_scale = (
345
+ block_size_each_image[0] * block_size_each_image[1]
346
+ )
347
+ cur_features_each_scale.append(
348
+ self.merge_chessboard(
349
+ image_features[block_cnt : block_cnt + num_blocks_last_scale],
350
+ num_split_h=block_size_each_image[0],
351
+ num_split_w=block_size_each_image[1],
352
+ )
353
+ ) # 1 * C * H * W
354
+ block_cnt += num_blocks_last_scale
355
+
356
+ # resize and concat features from different scales
357
+ output_size = cur_features_each_scale[resize_output_to_scale_idx].shape[
358
+ -2:
359
+ ]
360
+ cur_features = torch.cat(
361
+ [
362
+ F.interpolate(
363
+ cur_features_each_scale[i].to(torch.float32),
364
+ size=output_size,
365
+ mode="area",
366
+ ).to(cur_features_each_scale[i].dtype)
367
+ for i in range(len(cur_features_each_scale))
368
+ ],
369
+ dim=1,
370
+ )
371
+ # cur_features = rearrange(cur_features, "1 c h w -> (h w) c")
372
+
373
+ image_features_each_image.append(cur_features)
374
+
375
+ if (
376
+ resize_output_to_scale_idx == len(scales) - 1
377
+ or resize_output_to_scale_idx == -1
378
+ ):
379
+ new_block_sizes.append(block_size_each_image)
380
+ else:
381
+ new_block_sizes.append(
382
+ (
383
+ scales[resize_output_to_scale_idx] // scales[0],
384
+ scales[resize_output_to_scale_idx] // scales[0],
385
+ )
386
+ )
387
+
388
+ assert block_cnt == len(image_features)
389
+
390
+ return image_features_each_image, new_block_sizes
391
+
392
+ def encode_images(
393
+ self, images, block_sizes: Optional[Optional[Tuple[int, ...]]] = None
394
+ ):
395
+ if block_sizes is None:
396
+ block_sizes = [None] * len(images)
397
+ if getattr(self.config, "dynamic_s2", False):
398
+ image_features = self.get_vision_tower()(images)
399
+ image_features, new_block_sizes = self.merge_features_for_dynamic_s2(
400
+ image_features, block_sizes
401
+ )
402
+
403
+ image_features = [
404
+ self.split_chessboard(x, block_size[0], block_size[1])
405
+ for x, block_size in zip(image_features, new_block_sizes)
406
+ ] # list of B * C * H * W tensors
407
+ image_features = torch.cat(
408
+ [rearrange(x, "b c h w -> b (h w) c") for x in image_features], dim=0
409
+ ) # B * N * C
410
+ image_features = self.get_mm_projector()(image_features)
411
+ image_features = list(
412
+ image_features.split(
413
+ [block_size[0] * block_size[1] for block_size in new_block_sizes],
414
+ dim=0,
415
+ )
416
+ )
417
+ image_features = [
418
+ self.merge_chessboard(x, block_size[0], block_size[1])
419
+ for x, block_size in zip(image_features, new_block_sizes)
420
+ ] # list of 1 * C * H * W tensors
421
+ image_features = [
422
+ rearrange(x, "1 c h w -> (h w) c") for x in image_features
423
+ ] # list of N * C tensors
424
+ image_features = torch.stack(image_features, dim=0)
425
+ else:
426
+ image_features = self.get_vision_tower()(images)
427
+ image_features = self.get_mm_projector()(image_features)
428
+ return image_features
429
+
430
+ ## @yunhao: is there a better way to handle function call and attributes for llm?
431
+ ## support beam search
432
+ def _temporary_reorder_cache(self, past_key_values, sorted_idx):
433
+ return self.get_llm()._temporary_reorder_cache(past_key_values, sorted_idx)
434
+
435
+ def get_input_embeddings(self):
436
+ return self.get_llm().get_input_embeddings()
437
+
438
+ def get_output_embeddings(self):
439
+ return self.get_llm().get_output_embeddings()
440
+
441
+ def resize_token_embeddings(self, embed_size):
442
+ self.get_llm().resize_token_embeddings(embed_size)
443
+
444
+
445
+ class LlavaMetaForCausalLM(ABC):
446
+ def _embed(
447
+ self,
448
+ input_ids: torch.Tensor,
449
+ media: Dict[str, List[torch.Tensor]],
450
+ media_config: Dict[str, Dict[str, Any]],
451
+ labels: Optional[torch.Tensor],
452
+ attention_mask: Optional[torch.Tensor],
453
+ ) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
454
+ labels = (
455
+ labels if labels is not None else torch.full_like(input_ids, IGNORE_INDEX)
456
+ )
457
+ attention_mask = (
458
+ attention_mask
459
+ if attention_mask is not None
460
+ else torch.ones_like(input_ids, dtype=torch.bool)
461
+ )
462
+
463
+ # Extract text and media embeddings
464
+ text_embeds = self.llm.model.embed_tokens(input_ids)
465
+ media_embeds = self.__embed_media_tokens(media, media_config)
466
+
467
+ # This is a workaround to make sure the dummy embeddings are consumed
468
+ while media_embeds.get("dummy"):
469
+ dummy_embed = media_embeds["dummy"].popleft()
470
+ text_embeds += torch.sum(dummy_embed) * 0
471
+ # Remove padding
472
+ batch_size = labels.shape[0]
473
+ text_embeds = [text_embeds[k][attention_mask[k]] for k in range(batch_size)]
474
+ labels = [labels[k][attention_mask[k]] for k in range(batch_size)]
475
+
476
+ # Build inverse mapping from token ID to media name
477
+ media_tokens = {}
478
+ for name, token_id in self.tokenizer.media_token_ids.items():
479
+ media_tokens[token_id] = name
480
+
481
+ # Fuse text and media embeddings
482
+ inputs_m, labels_m = [], []
483
+ for k in range(batch_size):
484
+ inputs_mk, labels_mk = [], []
485
+ pos = 0
486
+ while pos < len(labels[k]):
487
+ if input_ids[k][pos].item() in media_tokens:
488
+ end = pos + 1
489
+ name = media_tokens[input_ids[k][pos].item()]
490
+ input = media_embeds[name].popleft()
491
+ label = torch.full(
492
+ [input.shape[0]],
493
+ IGNORE_INDEX,
494
+ device=labels[k].device,
495
+ dtype=labels[k].dtype,
496
+ )
497
+ else:
498
+ end = pos
499
+ while (
500
+ end < len(labels[k])
501
+ and input_ids[k][end].item() not in media_tokens
502
+ ):
503
+ end += 1
504
+ input = text_embeds[k][pos:end]
505
+ label = labels[k][pos:end]
506
+ inputs_mk.append(input)
507
+ labels_mk.append(label)
508
+ pos = end
509
+ inputs_m.append(torch.cat(inputs_mk, dim=0))
510
+ labels_m.append(torch.cat(labels_mk, dim=0))
511
+ inputs, labels = inputs_m, labels_m
512
+
513
+ # Check if all media embeddings are consumed
514
+ for name in media_embeds:
515
+ if media_embeds[name]:
516
+ raise ValueError(f"Not all {name} embeddings are consumed!")
517
+
518
+ # Truncate sequences to `model_max_length` as media embeddings are inserted
519
+ inputs, labels = self.__truncate_sequence(inputs, labels)
520
+
521
+ # Pad sequences to the longest one in the batch
522
+ return self.__batchify_sequence(inputs, labels)
523
+
524
+ def __embed_media_tokens(
525
+ self,
526
+ media: Dict[str, List[torch.Tensor]],
527
+ media_config: Dict[str, Dict[str, Any]],
528
+ ) -> Dict[str, List[torch.Tensor]]:
529
+ embeds = defaultdict(deque)
530
+ for name in media:
531
+ embeds[name] = deque(self.encoders[name](media[name], media_config[name]))
532
+ return embeds
533
+
534
+ def __truncate_sequence(
535
+ self, inputs: List[torch.Tensor], labels: List[torch.Tensor]
536
+ ) -> Tuple[torch.Tensor, torch.Tensor]:
537
+ if any(len(input) > self.tokenizer.model_max_length for input in inputs):
538
+ warnings.warn(
539
+ f"Truncating sequences to `model_max_length` ({self.tokenizer.model_max_length})."
540
+ )
541
+ inputs = [input[: self.tokenizer.model_max_length] for input in inputs]
542
+ labels = [label[: self.tokenizer.model_max_length] for label in labels]
543
+ return inputs, labels
544
+
545
+ def __batchify_sequence(
546
+ self, inputs: List[torch.Tensor], labels: List[torch.Tensor]
547
+ ) -> Tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
548
+ batch_size = len(inputs)
549
+ device = inputs[0].device
550
+ hidden_size = inputs[0].shape[1]
551
+ max_length = max(inputs[k].shape[0] for k in range(batch_size))
552
+ attention_mask = torch.ones(
553
+ (batch_size, max_length), dtype=torch.bool, device=device
554
+ )
555
+
556
+ inputs_p, labels_p = [], []
557
+ for k in range(batch_size):
558
+ size_pk = max_length - inputs[k].shape[0]
559
+ inputs_pk = torch.zeros(
560
+ (size_pk, hidden_size), dtype=inputs[k].dtype, device=device
561
+ )
562
+ labels_pk = torch.full(
563
+ (size_pk,), IGNORE_INDEX, dtype=labels[k].dtype, device=device
564
+ )
565
+ if self.tokenizer.padding_side == "right":
566
+ attention_mask[k, inputs[k].shape[0] :] = False
567
+ inputs_pk = torch.cat([inputs[k], inputs_pk], dim=0)
568
+ labels_pk = torch.cat([labels[k], labels_pk], dim=0)
569
+ else:
570
+ attention_mask[k, : -inputs[k].shape[0]] = False
571
+ inputs_pk = torch.cat([inputs_pk, inputs[k]], dim=0)
572
+ labels_pk = torch.cat([labels_pk, labels[k]], dim=0)
573
+ inputs_p.append(inputs_pk)
574
+ labels_p.append(labels_pk)
575
+
576
+ inputs = torch.stack(inputs_p, dim=0)
577
+ labels = torch.stack(labels_p, dim=0)
578
+ return inputs, labels, attention_mask
579
+
580
+ @torch.inference_mode()
581
+ def generate(
582
+ self,
583
+ input_ids: Optional[torch.FloatTensor] = None,
584
+ media: Optional[Dict[str, List[torch.Tensor]]] = None,
585
+ media_config: Dict[str, Dict[str, Any]] = None,
586
+ attention_mask: Optional[torch.LongTensor] = None,
587
+ quant_llm: Optional[bool] = True,
588
+ **generation_kwargs,
589
+ ):
590
+ inputs_embeds, _, attention_mask = self._embed(
591
+ input_ids, media, media_config, None, attention_mask
592
+ )
593
+ return self.llm.generate(
594
+ inputs_embeds=inputs_embeds,
595
+ attention_mask=attention_mask,
596
+ quant_llm=quant_llm,
597
+ **generation_kwargs,
598
+ )
599
+
600
+ @torch.inference_mode()
601
+ def generate_content(
602
+ self,
603
+ prompt: Union[str, List],
604
+ generation_config: Optional[GenerationConfig] = None,
605
+ quant_llm: Optional[bool] = True,
606
+ ) -> str:
607
+ # TODO(zhijianl): Support directly taking conversation as input
608
+ conversation = [{"from": "human", "value": prompt}]
609
+
610
+ # Extract media from the conversation
611
+
612
+ # TODO (extract and preprocess should be done together, as the preprocess of image and video can be different, i.e. when dynamic res is used)
613
+ media = extract_media(conversation, self.config)
614
+
615
+ # Process media
616
+ media_config = defaultdict(dict)
617
+ for name in media:
618
+ if name == "image":
619
+ if len(media["image"]) == 1 and self.config.image_aspect_ratio in [
620
+ "dynamic",
621
+ "dynamic_s2",
622
+ ]:
623
+ self.config.image_processor = self.vision_tower.image_processor
624
+ if self.config.image_aspect_ratio == "dynamic":
625
+ images = process_image(
626
+ media["image"][0],
627
+ self.config,
628
+ None,
629
+ enable_dynamic_res=True,
630
+ ).half()
631
+ conversation[0]["value"] = conversation[0]["value"].replace(
632
+ DEFAULT_IMAGE_TOKEN,
633
+ f"{DEFAULT_IMAGE_TOKEN}\n" * images.shape[0],
634
+ )
635
+ else:
636
+ if type(self.config.s2_scales) is str:
637
+ self.config.s2_scales = list(
638
+ map(int, self.config.s2_scales.split(","))
639
+ )
640
+ images, block_sizes = process_image(
641
+ media["image"][0], self.config, None, enable_dynamic_s2=True
642
+ )
643
+ images = images.half()
644
+ media_config[name]["block_sizes"] = [block_sizes]
645
+ else:
646
+ images = process_images(
647
+ media["image"], self.vision_tower.image_processor, self.config
648
+ ).half()
649
+ media[name] = [image for image in images]
650
+ elif name == "video":
651
+ media[name] = [
652
+ process_images(
653
+ images, self.vision_tower.image_processor, self.config
654
+ ).half()
655
+ for images in media[name]
656
+ ]
657
+ else:
658
+ raise ValueError(f"Unsupported media type: {name}")
659
+
660
+ # Tokenize the conversation
661
+ input_ids = (
662
+ tokenize_conversation(
663
+ conversation, self.tokenizer, add_generation_prompt=True
664
+ )
665
+ .cuda()
666
+ .unsqueeze(0)
667
+ )
668
+
669
+ # Set up the generation config
670
+ generation_config = generation_config or self.default_generation_config
671
+ # Generate the response
672
+ try:
673
+ output_ids = self.generate(
674
+ input_ids=input_ids,
675
+ media=media,
676
+ media_config=media_config,
677
+ generation_config=generation_config,
678
+ quant_llm=quant_llm,
679
+ )
680
+ except ValueError:
681
+ if not generation_config.do_sample:
682
+ raise
683
+ # FIXME(zhijianl): This is a temporary workaround for the sampling issue
684
+ logging.warning(
685
+ "Generation failed with sampling, retrying with greedy decoding."
686
+ )
687
+ generation_config.do_sample = False
688
+ output_ids = self.generate(
689
+ input_ids=input_ids,
690
+ media=media,
691
+ media_config=media_config,
692
+ generation_config=generation_config,
693
+ )
694
+
695
+ # Decode the response
696
+ response = self.tokenizer.decode(
697
+ output_ids[0], skip_special_tokens=True
698
+ ).strip()
699
+ return response
700
+
701
+ @torch.inference_mode()
702
+ def benchmark(self, prompt: Union[str, List], quant_llm) -> None:
703
+ # TODO(zhijianl): Support directly taking conversation as input
704
+ conversation = [{"from": "human", "value": prompt}]
705
+
706
+ # Extract media from the conversation
707
+
708
+ # TODO (extract and preprocess should be done together, as the preprocess of image and video can be different, i.e. when dynamic res is used)
709
+ media = extract_media(conversation, self.config)
710
+
711
+ # Process media
712
+ media_config = defaultdict(dict)
713
+ image_num = 0
714
+ for name in media:
715
+ if name == "image":
716
+ if len(media["image"]) == 1 and self.config.image_aspect_ratio in [
717
+ "dynamic",
718
+ "dynamic_s2",
719
+ ]:
720
+ self.config.image_processor = self.vision_tower.image_processor
721
+ if self.config.image_aspect_ratio == "dynamic":
722
+ images = process_image(
723
+ media["image"][0],
724
+ self.config,
725
+ None,
726
+ enable_dynamic_res=True,
727
+ ).half()
728
+ if len(images.shape) == 3:
729
+ images = images.reshape(1, *images.shape)
730
+ image_num += images.shape[0]
731
+ size = images.shape[1:]
732
+ conversation[0]["value"] = conversation[0]["value"].replace(
733
+ DEFAULT_IMAGE_TOKEN,
734
+ f"{DEFAULT_IMAGE_TOKEN}\n" * images.shape[0],
735
+ )
736
+ else:
737
+ if type(self.config.s2_scales) is str:
738
+ self.config.s2_scales = list(
739
+ map(int, self.config.s2_scales.split(","))
740
+ )
741
+ images, block_sizes = process_image(
742
+ media["image"][0], self.config, None, enable_dynamic_s2=True
743
+ )
744
+ images = images.half()
745
+ if len(images.shape) == 3:
746
+ images = images.reshape(1, *images.shape)
747
+ image_num += images.shape[0]
748
+ size = images.shape[1:]
749
+ media_config[name]["block_sizes"] = [block_sizes]
750
+ else:
751
+ images = process_images(
752
+ media["image"], self.vision_tower.image_processor, self.config
753
+ ).half()
754
+ image_num += images.shape[0]
755
+ size = images.shape[1:]
756
+ media[name] = [image for image in images]
757
+ elif name == "video":
758
+ media[name] = [
759
+ process_images(
760
+ images, self.vision_tower.image_processor, self.config
761
+ ).half()
762
+ for images in media[name]
763
+ ]
764
+ for images in media[name]:
765
+ image_num += images.shape[0]
766
+ size = images.shape[1:]
767
+ else:
768
+ raise ValueError(f"Unsupported media type: {name}")
769
+
770
+ # Tokenize the conversation
771
+ input_ids = (
772
+ tokenize_conversation(
773
+ conversation, self.tokenizer, add_generation_prompt=True
774
+ )
775
+ .cuda()
776
+ .unsqueeze(0)
777
+ )
778
+
779
+ # Set up the generation config
780
+ for i in range(10):
781
+ torch.cuda.synchronize()
782
+ t_st = time()
783
+ inputs_embeds, _, attention_mask = self._embed(
784
+ input_ids, media, media_config, None, None
785
+ )
786
+ torch.cuda.synchronize()
787
+ t_ed = time()
788
+ torch.cuda.empty_cache()
789
+ print(
790
+ "Time of vision tower and others is {:.5f} s for {} images ({} x {} x {})".format(
791
+ t_ed - t_st, image_num, size[0], size[1], size[2]
792
+ )
793
+ )
794
+ output = self.llm.benchmark(
795
+ inputs_embeds=inputs_embeds,
796
+ attention_mask=attention_mask,
797
+ quant_llm=quant_llm,
798
+ )
799
+ # response = self.tokenizer.decode(output, skip_special_tokens=True).strip()
800
+ return
801
+
802
+ @property
803
+ def default_generation_config(self) -> GenerationConfig:
804
+ generation_config = copy.deepcopy(self.generation_config or GenerationConfig())
805
+ if self.tokenizer.eos_token_id is None:
806
+ raise ValueError("Tokenizer must have an EOS token")
807
+ if generation_config.max_length == GenerationConfig().max_length:
808
+ generation_config.max_length = self.tokenizer.model_max_length
809
+ if generation_config.pad_token_id is None:
810
+ generation_config.pad_token_id = (
811
+ self.tokenizer.pad_token_id or self.tokenizer.eos_token_id
812
+ )
813
+ if generation_config.bos_token_id is None:
814
+ generation_config.bos_token_id = (
815
+ self.tokenizer.bos_token_id or self.tokenizer.eos_token_id
816
+ )
817
+ if generation_config.eos_token_id is None:
818
+ generation_config.eos_token_id = self.tokenizer.stop_token_ids
819
+ return generation_config
820
+
821
+ # Prepare media
822
+
823
+ # Process media
824
+ @torch.inference_mode()
825
+ def prepare_media(self, conversation):
826
+ media = extract_media(conversation, self.config)
827
+
828
+ # Process media
829
+ media_config = defaultdict(dict)
830
+ for name in media:
831
+ if name == "image":
832
+ if len(media["image"]) == 1 and self.config.image_aspect_ratio in [
833
+ "dynamic",
834
+ "dynamic_s2",
835
+ ]:
836
+ self.config.image_processor = self.vision_tower.image_processor
837
+ if self.config.image_aspect_ratio == "dynamic":
838
+ images = process_image(
839
+ media["image"][0],
840
+ self.config,
841
+ None,
842
+ enable_dynamic_res=True,
843
+ ).half()
844
+ conversation[0]["value"] = conversation[0]["value"].replace(
845
+ DEFAULT_IMAGE_TOKEN,
846
+ f"{DEFAULT_IMAGE_TOKEN}\n" * images.shape[0],
847
+ )
848
+ else:
849
+ if type(self.config.s2_scales) is str:
850
+ self.config.s2_scales = list(
851
+ map(int, self.config.s2_scales.split(","))
852
+ )
853
+ images, block_sizes = process_image(
854
+ media["image"][0], self.config, None, enable_dynamic_s2=True
855
+ )
856
+ images = images.half()
857
+ media_config[name]["block_sizes"] = [block_sizes]
858
+ else:
859
+ images = process_images(
860
+ media["image"], self.vision_tower.image_processor, self.config
861
+ ).half()
862
+ media[name] = [image for image in images]
863
+ elif name == "video":
864
+ media[name] = [
865
+ process_images(
866
+ images, self.vision_tower.image_processor, self.config
867
+ ).half()
868
+ for images in media[name]
869
+ ]
870
+ else:
871
+ raise ValueError(f"Unsupported media type: {name}")
872
+ return media, media_config
873
+
874
+ @torch.inference_mode()
875
+ def stream_gen(
876
+ self,
877
+ input_ids,
878
+ media,
879
+ media_cfg,
880
+ start_pos,
881
+ chunk_prefilling,
882
+ quant_llm,
883
+ attention_mask=None,
884
+ ) -> str:
885
+ if media is None:
886
+ inputs_embeds = self.llm.model.embed_tokens(input_ids)
887
+ else:
888
+ image_num = torch.sum(input_ids == 151649)
889
+ if image_num == 1 and self.config.image_aspect_ratio == "dynamic":
890
+ patch_num = len(media["image"])
891
+ new_input_ids = []
892
+ for i, id in enumerate(input_ids[0]):
893
+ if id == 151649:
894
+ new_input_ids.extend(input_ids[0, 0:i])
895
+ new_input_ids.extend([198, 151649, 198] * patch_num)
896
+ new_input_ids.extend(input_ids[0, i + 1 :])
897
+ break
898
+ input_ids = torch.tensor(
899
+ [new_input_ids], dtype=torch.int, device="cuda"
900
+ )
901
+ inputs_embeds, _, _ = self._embed(
902
+ input_ids, media, media_cfg, None, attention_mask=None
903
+ )
904
+ length = inputs_embeds.shape[1]
905
+ if quant_llm:
906
+ out = self.llm(None, start_pos, inputs_embeds, chunk_prefilling)
907
+ else:
908
+ out = self.llm.forwardfp16(None, start_pos, inputs_embeds, chunk_prefilling)
909
+ return out, length
llm-awq/tinychat/models/qwen2.py ADDED
@@ -0,0 +1,511 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Modified from https://github.com/huggingface/transformers/blob/main/src/transformers/models/qwen2/modeling_qwen2.py
2
+ """PyTorch Qwen2 model."""
3
+
4
+ import math
5
+ from typing import List, Optional, Tuple, Union
6
+
7
+ import torch
8
+ import torch.utils.checkpoint
9
+ from torch import nn
10
+ import awq_inference_engine
11
+ from torch.nn import BCEWithLogitsLoss, CrossEntropyLoss, MSELoss
12
+ from transformers.models.qwen2.configuration_qwen2 import Qwen2Config
13
+ from transformers.activations import ACT2FN
14
+ import tinychat
15
+ import torch.nn.functional as F
16
+ import time
17
+ from tqdm import tqdm
18
+ from transformers import GenerationMixin
19
+ from transformers.models.qwen2 import Qwen2ForCausalLM
20
+ from flash_attn import flash_attn_func
21
+
22
+ max_batch_size = tinychat.utils.constants.max_batch_size
23
+ max_seq_len = tinychat.utils.constants.max_seq_len
24
+
25
+
26
+ class Qwen2RMSNorm(nn.Module):
27
+ def __init__(self, dim: int, eps: float = 1e-6):
28
+ super().__init__()
29
+ self.eps = eps
30
+ self.weight = nn.Parameter(torch.ones(dim))
31
+
32
+ def _norm(self, x):
33
+ return x * torch.rsqrt(x.pow(2).mean(-1, keepdim=True) + self.eps)
34
+
35
+ def forward(self, x):
36
+ output = torch.empty_like(x)
37
+ awq_inference_engine.layernorm_forward_cuda(x, self.weight, output, self.eps)
38
+ return output
39
+
40
+
41
+ def precompute_freqs_cis(
42
+ dim: int, end: int, theta: float = 10000.0, scale: float = 1.0
43
+ ):
44
+ freqs = 1.0 / (theta ** (torch.arange(0, dim, 2)[: (dim // 2)].float() / dim))
45
+ t = torch.arange(end, device=freqs.device) # type: ignore
46
+ freqs = torch.outer(t * scale, freqs).float() # type: ignore
47
+
48
+ freqs_cis = torch.polar(torch.ones_like(freqs), freqs) # complex64
49
+ return freqs_cis
50
+
51
+
52
+ def precompute_freqs(
53
+ dim: int, end: int, theta: float = 10000.0, scale: float = 1.0, device=None
54
+ ):
55
+ inv_freq = 1.0 / (theta ** (torch.arange(0, dim, 2).float().to(device) / dim))
56
+ seq = torch.arange(end, dtype=inv_freq.dtype, device=device)
57
+ freqs = torch.einsum("i , j -> i j", seq, inv_freq)
58
+ freqs = freqs.reshape(freqs.shape[0], 1, 1, -1)
59
+ return torch.cat((freqs, freqs), dim=-1)
60
+
61
+
62
+ def reshape_for_broadcast(freqs_cis: torch.Tensor, x: torch.Tensor):
63
+ ndim = x.ndim
64
+ assert 0 <= 1 < ndim
65
+ assert freqs_cis.shape == (x.shape[1], x.shape[-1])
66
+ shape = [d if i == 1 or i == ndim - 1 else 1 for i, d in enumerate(x.shape)]
67
+ return freqs_cis.view(*shape)
68
+
69
+
70
+ def apply_rotary_emb(
71
+ xq: torch.Tensor,
72
+ xk: torch.Tensor,
73
+ freqs_cis: torch.Tensor,
74
+ ) -> Tuple[torch.Tensor, torch.Tensor]:
75
+ # xq_ = torch.view_as_complex(xq.float().reshape(*xq.shape[:-1], -1, 2))
76
+ # k_ = torch.view_as_complex(xk.float().reshape(*xk.shape[:-1], -1, 2))
77
+ xq_ = torch.view_as_complex(
78
+ xq.float().reshape(*xq.shape[:-1], 2, -1).transpose(-2, -1).contiguous()
79
+ )
80
+ xk_ = torch.view_as_complex(
81
+ xk.float().reshape(*xk.shape[:-1], 2, -1).transpose(-2, -1).contiguous()
82
+ )
83
+ freqs_cis = reshape_for_broadcast(freqs_cis, xq_)
84
+ xq_out = torch.view_as_real(xq_ * freqs_cis).transpose(-2, -1).flatten(3)
85
+ xk_out = torch.view_as_real(xk_ * freqs_cis).transpose(-2, -1).flatten(3)
86
+ return xq_out.type_as(xq), xk_out.type_as(xk)
87
+
88
+
89
+ class Qwen2MLP(nn.Module):
90
+ def __init__(self, config):
91
+ super().__init__()
92
+ self.hidden_size = config.hidden_size
93
+ self.intermediate_size = config.intermediate_size
94
+ self.gate_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
95
+ self.up_proj = nn.Linear(self.hidden_size, self.intermediate_size, bias=False)
96
+ self.down_proj = nn.Linear(self.intermediate_size, self.hidden_size, bias=False)
97
+ self.act_fn = ACT2FN[config.hidden_act]
98
+
99
+ def forward(self, hidden_state):
100
+ return self.down_proj(
101
+ self.act_fn(self.gate_proj(hidden_state)) * self.up_proj(hidden_state)
102
+ )
103
+
104
+
105
+ # Copied from transformers.models.llama.modeling_llama.repeat_kv
106
+ def repeat_kv(x: torch.Tensor, n_rep: int) -> torch.Tensor:
107
+ """
108
+ This is the equivalent of torch.repeat_interleave(x, dim=1, repeats=n_rep). The hidden states go from (batch,
109
+ num_key_value_heads, seqlen, head_dim) to (batch, num_attention_heads, seqlen, head_dim)
110
+ """
111
+ batch, num_key_value_heads, slen, head_dim = x.shape
112
+ if n_rep == 1:
113
+ return x
114
+ x = x[:, :, None, :, :].expand(batch, num_key_value_heads, n_rep, slen, head_dim)
115
+ return x.reshape(batch, num_key_value_heads * n_rep, slen, head_dim)
116
+
117
+
118
+ class Qwen2AttentionFused(nn.Module):
119
+ """
120
+ Multi-headed attention from 'Attention Is All You Need' paper. Modified to use sliding window attention: Longformer
121
+ and "Generating Long Sequences with Sparse Transformers".
122
+ """
123
+
124
+ def __init__(self, config: Qwen2Config, layer_idx: Optional[int] = None):
125
+ super().__init__()
126
+ self.args = config
127
+ self.layer_idx = layer_idx
128
+ if layer_idx is None:
129
+ print(
130
+ f"Instantiating {self.__class__.__name__} without passing `layer_idx` is not recommended and will "
131
+ "to errors during the forward call, if caching is used. Please make sure to provide a `layer_idx` "
132
+ "when creating this class."
133
+ )
134
+
135
+ self.hidden_size = config.hidden_size
136
+ self.num_heads = config.num_attention_heads
137
+ self.head_dim = self.hidden_size // self.num_heads
138
+ self.num_key_value_heads = config.num_key_value_heads
139
+ self.num_key_value_groups = self.num_heads // self.num_key_value_heads
140
+ self.max_position_embeddings = config.max_position_embeddings
141
+ self.rope_theta = config.rope_theta
142
+ self.is_causal = True
143
+ self.attention_dropout = config.attention_dropout
144
+ self.rope_scaling = config.rope_scaling
145
+ if self.rope_scaling is None:
146
+ self.rope_scaling = 1.0
147
+ elif isinstance(self.rope_scaling, dict):
148
+ self.rope_scaling = self.rope_scaling.get("factor", 1.0)
149
+
150
+ if (self.head_dim * self.num_heads) != self.hidden_size:
151
+ raise ValueError(
152
+ f"hidden_size must be divisible by num_heads (got `hidden_size`: {self.hidden_size}"
153
+ f" and `num_heads`: {self.num_heads})."
154
+ )
155
+ self.q_proj = nn.Linear(
156
+ self.hidden_size, self.num_heads * self.head_dim, bias=True
157
+ )
158
+ self.k_proj = nn.Linear(
159
+ self.hidden_size, self.num_key_value_heads * self.head_dim, bias=True
160
+ )
161
+ self.v_proj = nn.Linear(
162
+ self.hidden_size, self.num_key_value_heads * self.head_dim, bias=True
163
+ )
164
+ self.o_proj = nn.Linear(
165
+ self.num_heads * self.head_dim, self.hidden_size, bias=False
166
+ )
167
+ self.kv_max_seq_len = min(max_seq_len, self.max_position_embeddings)
168
+ # following fastertransformer definition
169
+ self.cache_v = (
170
+ torch.zeros(
171
+ (
172
+ max_batch_size,
173
+ self.num_key_value_heads,
174
+ # args.max_position_embeddings,
175
+ self.kv_max_seq_len,
176
+ self.head_dim,
177
+ )
178
+ )
179
+ .cuda()
180
+ .half()
181
+ ) # added to half
182
+ # 8: pack 8 fp16 in FT, if fp32 then use 4
183
+ self.cache_k = (
184
+ torch.zeros(
185
+ (
186
+ max_batch_size,
187
+ self.num_key_value_heads,
188
+ self.head_dim // 8,
189
+ # args.max_position_embeddings,
190
+ self.kv_max_seq_len,
191
+ 8,
192
+ )
193
+ )
194
+ .cuda()
195
+ .half()
196
+ ) # added to half
197
+
198
+ def forward(
199
+ self,
200
+ x: torch.Tensor,
201
+ start_pos: int,
202
+ freqs: torch.Tensor,
203
+ mask: Optional[torch.Tensor],
204
+ chunk_prefilling: bool = False,
205
+ ):
206
+ bsz, seqlen, _ = x.shape
207
+
208
+ query_states = self.q_proj(x)
209
+ key_states = self.k_proj(x)
210
+ value_states = self.v_proj(x)
211
+
212
+ if seqlen > 1:
213
+ xq = query_states.view(bsz, seqlen, self.num_heads, self.head_dim)
214
+ xk = key_states.view(bsz, seqlen, self.num_key_value_heads, self.head_dim)
215
+ xv = value_states.view(bsz, seqlen, self.num_key_value_heads, self.head_dim)
216
+
217
+ xq, xk = apply_rotary_emb(xq, xk, freqs_cis=freqs)
218
+
219
+ self.cache_k = self.cache_k.to(xq)
220
+ self.cache_v = self.cache_v.to(xq)
221
+
222
+ values_store = xv.transpose(2, 1)
223
+
224
+ keys_store = (
225
+ xk.reshape(bsz, seqlen, self.num_key_value_heads, self.head_dim // 8, 8)
226
+ .permute(0, 2, 3, 1, 4)
227
+ .contiguous()
228
+ )
229
+
230
+ self.cache_v[:bsz, :, start_pos : start_pos + seqlen, :] = values_store
231
+ self.cache_k[:bsz, :, :, start_pos : start_pos + seqlen, :] = keys_store
232
+ if chunk_prefilling:
233
+ keys = self.cache_k[:, :, :, 0 : start_pos + seqlen, :]
234
+ keys = (
235
+ keys.permute(0, 3, 1, 2, 4)
236
+ .reshape(
237
+ bsz, start_pos + seqlen, self.num_key_value_heads, self.head_dim
238
+ )
239
+ .contiguous()
240
+ )
241
+ values = self.cache_v[:, :, 0 : start_pos + seqlen, :]
242
+ values = (
243
+ values.transpose(2, 1)
244
+ .reshape(
245
+ bsz, start_pos + seqlen, self.num_key_value_heads, self.head_dim
246
+ )
247
+ .contiguous()
248
+ )
249
+ else:
250
+ keys = xk
251
+ values = xv
252
+ output = flash_attn_func(
253
+ q=xq,
254
+ k=keys,
255
+ v=values,
256
+ causal=True,
257
+ )
258
+ output = output.contiguous().view(bsz, seqlen, -1)
259
+ else:
260
+ xq = query_states.view(bsz, self.num_heads, self.head_dim)
261
+ xk = key_states.view(bsz, self.num_key_value_heads, self.head_dim)
262
+ xv = value_states.view(bsz, self.num_key_value_heads, self.head_dim)
263
+
264
+ output = awq_inference_engine.single_query_attention(
265
+ xq,
266
+ xk,
267
+ xv,
268
+ self.cache_k,
269
+ self.cache_v,
270
+ None,
271
+ # alibi position encodings
272
+ None,
273
+ start_pos,
274
+ self.head_dim,
275
+ self.rope_theta,
276
+ self.rope_scaling,
277
+ True,
278
+ )
279
+ output = output.reshape(bsz, 1, -1)
280
+
281
+ return self.o_proj(output)
282
+
283
+
284
+ class Qwen2DecoderLayer(nn.Module):
285
+ def __init__(self, config: Qwen2Config, layer_idx: int):
286
+ super().__init__()
287
+ self.hidden_size = config.hidden_size
288
+
289
+ self.self_attn = Qwen2AttentionFused(config, layer_idx)
290
+
291
+ self.mlp = Qwen2MLP(config)
292
+ self.input_layernorm = Qwen2RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
293
+ self.post_attention_layernorm = Qwen2RMSNorm(
294
+ config.hidden_size, eps=config.rms_norm_eps
295
+ )
296
+
297
+ def forward(
298
+ self,
299
+ x: torch.Tensor,
300
+ start_pos: int,
301
+ freqs: torch.Tensor,
302
+ mask: Optional[torch.Tensor],
303
+ chunk_prefilling: bool = False,
304
+ ):
305
+ residual = x
306
+ x = self.input_layernorm(x)
307
+
308
+ # Self Attention
309
+ x = self.self_attn(
310
+ x=x,
311
+ start_pos=start_pos,
312
+ freqs=freqs,
313
+ mask=mask,
314
+ chunk_prefilling=chunk_prefilling,
315
+ )
316
+ x = residual + x
317
+
318
+ # Fully Connected
319
+ residual = x
320
+ x = self.post_attention_layernorm(x)
321
+ x = self.mlp(x)
322
+ x = residual + x
323
+ return x
324
+
325
+
326
+ class Qwen2Model(nn.Module):
327
+ def __init__(self, config: Qwen2Config):
328
+ super().__init__()
329
+ self.padding_idx = config.pad_token_id
330
+ self.vocab_size = config.vocab_size
331
+
332
+ self.embed_tokens = nn.Embedding(
333
+ config.vocab_size, config.hidden_size, self.padding_idx
334
+ )
335
+ self.layers = nn.ModuleList(
336
+ [
337
+ Qwen2DecoderLayer(config, layer_idx)
338
+ for layer_idx in range(config.num_hidden_layers)
339
+ ]
340
+ )
341
+ self.norm = Qwen2RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
342
+ # Note (Haotian): rope_theta has to be defined here, otherwise context stage is wrong.
343
+ rope_scale = config.rope_scaling
344
+ if rope_scale is None:
345
+ rope_scale = 1.0
346
+ else:
347
+ rope_scale = 1.0 / rope_scale["factor"]
348
+ self.freqs = precompute_freqs(
349
+ config.hidden_size // config.num_attention_heads,
350
+ config.max_position_embeddings * 2,
351
+ config.rope_theta,
352
+ rope_scale,
353
+ )
354
+ self.freqs_cis = precompute_freqs_cis(
355
+ config.hidden_size // config.num_attention_heads,
356
+ config.max_position_embeddings * 2,
357
+ config.rope_theta,
358
+ rope_scale,
359
+ )
360
+
361
+ def forward(
362
+ self,
363
+ input_ids: torch.LongTensor = None,
364
+ start_pos: Optional[int] = 0,
365
+ inputs_embeds: Optional[torch.FloatTensor] = None,
366
+ chunk_prefilling: bool = False,
367
+ ):
368
+ if inputs_embeds is None:
369
+ inputs_embeds = self.embed_tokens(input_ids)
370
+ seqlen = inputs_embeds.shape[1]
371
+
372
+ self.freqs = self.freqs.to(inputs_embeds.device)
373
+ freqs = self.freqs[start_pos : start_pos + seqlen]
374
+
375
+ mask = None
376
+ if seqlen > 1:
377
+ mask = torch.full(
378
+ (1, 1, seqlen, seqlen), float("-inf"), device=inputs_embeds.device
379
+ )
380
+ mask = torch.triu(mask, diagonal=1).type_as(inputs_embeds)
381
+ if chunk_prefilling:
382
+ mask_history = torch.zeros(
383
+ (1, 1, seqlen, start_pos),
384
+ dtype=torch.float16,
385
+ device=inputs_embeds.device,
386
+ ).type_as(inputs_embeds)
387
+ mask = torch.cat((mask_history, mask), dim=-1)
388
+ x = inputs_embeds
389
+
390
+ for decoder_layer in self.layers:
391
+ x = decoder_layer(x, start_pos, freqs, mask, chunk_prefilling)
392
+ x = x[:, -1:, :]
393
+ x = self.norm(x)
394
+
395
+ return x
396
+
397
+ def forwardfp16(
398
+ self,
399
+ input_ids: torch.LongTensor = None,
400
+ start_pos: Optional[int] = 0,
401
+ inputs_embeds: Optional[torch.FloatTensor] = None,
402
+ chunk_prefilling: bool = False,
403
+ ):
404
+ if inputs_embeds is None:
405
+ inputs_embeds = self.embed_tokens(input_ids)
406
+ seqlen = inputs_embeds.shape[1]
407
+
408
+ self.freqs_cis = self.freqs_cis.to(inputs_embeds.device)
409
+ freqs_cis = self.freqs_cis[start_pos : start_pos + seqlen]
410
+
411
+ mask = None
412
+ if seqlen > 1:
413
+ mask = torch.full(
414
+ (1, 1, seqlen, seqlen), float("-inf"), device=inputs_embeds.device
415
+ )
416
+ mask = torch.triu(mask, diagonal=1).type_as(inputs_embeds)
417
+ if chunk_prefilling:
418
+ mask_history = torch.zeros(
419
+ (1, 1, seqlen, start_pos),
420
+ dtype=torch.float16,
421
+ device=inputs_embeds.device,
422
+ ).type_as(inputs_embeds)
423
+ mask = torch.cat((mask_history, mask), dim=-1)
424
+ x = inputs_embeds
425
+
426
+ for decoder_layer in self.layers:
427
+ x = decoder_layer(x, start_pos, freqs_cis, mask, chunk_prefilling)
428
+ x = x[:, -1:, :]
429
+ x = self.norm(x)
430
+
431
+ return x
432
+
433
+
434
+ class Qwen2ForCausalLM(Qwen2ForCausalLM):
435
+ def __init__(self, config):
436
+
437
+ def skip(*args, **kwargs):
438
+ pass
439
+
440
+ torch.nn.init.kaiming_uniform_ = skip
441
+ torch.nn.init.kaiming_normal_ = skip
442
+ torch.nn.init.uniform_ = skip
443
+ torch.nn.init.normal_ = skip
444
+ from transformers import modeling_utils
445
+
446
+ modeling_utils._init_weights = False
447
+
448
+ super().__init__(config)
449
+ self.model = Qwen2Model(config)
450
+ self.vocab_size = config.vocab_size
451
+ self.lm_head = nn.Linear(config.hidden_size, config.vocab_size, bias=False)
452
+ self.config = config
453
+
454
+ @torch.inference_mode()
455
+ def forward(
456
+ self,
457
+ input_ids: torch.Tensor,
458
+ start_pos: int = 0,
459
+ inputs_embeds: torch.Tensor = None,
460
+ chunk_prefilling: bool = False,
461
+ quant=True,
462
+ ):
463
+ if quant:
464
+ outputs = self.model(
465
+ input_ids=input_ids,
466
+ inputs_embeds=inputs_embeds,
467
+ start_pos=start_pos,
468
+ chunk_prefilling=chunk_prefilling,
469
+ )
470
+ else:
471
+ outputs = self.model.forwardfp16(
472
+ input_ids=input_ids,
473
+ inputs_embeds=inputs_embeds,
474
+ start_pos=start_pos,
475
+ chunk_prefilling=chunk_prefilling,
476
+ )
477
+ logits = self.lm_head(outputs)
478
+ return logits
479
+
480
+ def benchmark(self, inputs_embeds, attention_mask, max_output=128, quant_llm=True):
481
+ output_list = []
482
+ start_pos = 0
483
+ for i in range(10):
484
+ torch.cuda.synchronize()
485
+ tst = time.time()
486
+ token = self.forward(None, start_pos, inputs_embeds, quant=quant_llm)
487
+ torch.cuda.synchronize()
488
+ ted = time.time()
489
+ print(
490
+ "LLM TTFT: {:.6f} s for {} tokens".format(
491
+ (ted - tst), inputs_embeds.shape[1]
492
+ )
493
+ )
494
+ start_pos = inputs_embeds.shape[1]
495
+ token = torch.argmax(token, keepdim=True)[0]
496
+ output_list.append(token)
497
+
498
+ torch.cuda.synchronize()
499
+ tst = time.time()
500
+ for _ in range(max_output):
501
+ token = self.forward(token, start_pos)
502
+ token = torch.argmax(token, keepdim=True)[
503
+ 0
504
+ ] # Only fixed-length eager decoding is supported now
505
+ output_list.append(token)
506
+ start_pos += 1
507
+ torch.cuda.synchronize()
508
+ ted = time.time()
509
+ print("Decoding througput: {:.6f} tokens/s".format(max_output / (ted - tst)))
510
+
511
+ return torch.cat(output_list, dim=1)
llm-awq/tinychat/models/vila_llama.py ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import warnings
3
+ import shutil
4
+ import torch
5
+ import torch.nn as nn
6
+ from typing import List, Optional, Tuple, Union
7
+ import time
8
+
9
+ from transformers import AutoConfig, PreTrainedModel
10
+ from transformers.modeling_outputs import CausalLMOutputWithPast
11
+
12
+ from llava.model.utils import get_model_config
13
+ from llava.model.language_model.builder import build_llm_and_tokenizer
14
+ from llava.model.multimodal_encoder.builder import build_vision_tower
15
+ from llava.model.multimodal_projector.builder import build_mm_projector
16
+ from llava.model.llava_arch import LlavaMetaModel, LlavaMetaForCausalLM
17
+ from .llama import LlamaForCausalLM, Transformer
18
+
19
+
20
+ class VilaLlamaForCausalLM(LlavaMetaModel, LlavaMetaForCausalLM, PreTrainedModel):
21
+ def __init__(self, config):
22
+ super().__init__(config)
23
+ self.init_vlm(config)
24
+
25
+ def init_vlm(self, config=None, *args, **kwargs):
26
+ if (
27
+ hasattr(self, "llm")
28
+ or hasattr(self, "vision_tower")
29
+ or hasattr(self, "mm_projector")
30
+ ):
31
+ # already initialized, skipped
32
+ return
33
+
34
+ model_dtype = getattr(config, "model_dtype", "torch.float16")
35
+ if not hasattr(config, "model_dtype"):
36
+ warnings.warn(
37
+ "model_dtype not found in config, defaulting to torch.float16."
38
+ )
39
+ config.model_dtype = model_dtype
40
+
41
+ # print("init_vlm(): config", config); input("DEBUG init_vlm")
42
+ cfgs = get_model_config(config)
43
+ if len(cfgs) == 3:
44
+ llm_cfg, vision_tower_cfg, mm_projector_cfg = cfgs
45
+ else:
46
+ raise ValueError(
47
+ "`llm_cfg` `mm_projector_cfg` `vision_tower_cfg` not found in the config."
48
+ )
49
+ # print("init_vlm():", cfgs); input("DEBUG init_vlm")
50
+ llm_cfg = AutoConfig.from_pretrained(llm_cfg)
51
+
52
+ # self.llm, self.tokenizer = build_llm_and_tokenizer(llm_cfg, config, *args, **kwargs)
53
+ self.llm = LlamaForCausalLM(llm_cfg)
54
+ self.vision_tower = build_vision_tower(vision_tower_cfg, config)
55
+ self.mm_projector = build_mm_projector(mm_projector_cfg, config)
56
+
57
+ self.post_config()
58
+ self.is_loaded = True
59
+
60
+ assert (
61
+ self.llm is not None
62
+ or self.vision_tower is not None
63
+ or self.mm_projector is not None
64
+ ), "At least one of the components must be instantiated."
65
+
66
+ def forward(
67
+ self,
68
+ input_ids: torch.LongTensor = None,
69
+ start_pos: int = None,
70
+ attention_mask: Optional[torch.Tensor] = None,
71
+ position_ids: Optional[torch.LongTensor] = None,
72
+ past_key_values: Optional[List[torch.FloatTensor]] = None,
73
+ inputs_embeds: Optional[torch.FloatTensor] = None,
74
+ labels: Optional[torch.LongTensor] = None,
75
+ use_cache: Optional[bool] = None,
76
+ output_attentions: Optional[bool] = None,
77
+ output_hidden_states: Optional[bool] = None,
78
+ images: Optional[torch.FloatTensor] = None,
79
+ return_dict: Optional[bool] = None,
80
+ special_token: bool = False,
81
+ chunk_prefilling: bool = False,
82
+ ) -> Union[Tuple, CausalLMOutputWithPast]:
83
+ self.freezed_module_patch()
84
+ if inputs_embeds is None:
85
+ (
86
+ _,
87
+ _,
88
+ _,
89
+ _,
90
+ inputs_embeds,
91
+ _,
92
+ ) = self.prepare_inputs_labels_for_multimodal(
93
+ input_ids, position_ids, attention_mask, past_key_values, labels, images
94
+ )
95
+ if inputs_embeds is not None:
96
+ outputs = self.llm.forward(
97
+ tokens=None,
98
+ start_pos=start_pos,
99
+ inputs_embeds=inputs_embeds,
100
+ chunk_prefilling=chunk_prefilling,
101
+ )
102
+ else: # tokens
103
+ outputs = self.llm.forward(
104
+ tokens=input_ids,
105
+ start_pos=start_pos,
106
+ inputs_embeds=None,
107
+ chunk_prefilling=chunk_prefilling,
108
+ )
109
+ return outputs
llm-awq/tinychat/modules/fused_attn.py ADDED
@@ -0,0 +1,634 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ import torch
3
+ import torch.nn as nn
4
+ from torch.nn import functional as F
5
+ from transformers.models.llama.modeling_llama import (
6
+ LlamaAttention,
7
+ LlamaRotaryEmbedding,
8
+ apply_rotary_pos_emb,
9
+ )
10
+ from typing import Optional
11
+ from awq.quantize.qmodule import WQLinear
12
+ import awq_inference_engine
13
+ from tinychat.models.llama import apply_rotary_emb
14
+ import gc
15
+
16
+ import tinychat.utils.constants
17
+ from flash_attn import flash_attn_func
18
+ from tinychat.models.llama import LlamaAttentionFused
19
+ from tinychat.models.qwen2 import Qwen2AttentionFused
20
+
21
+ max_batch_size = tinychat.utils.constants.max_batch_size
22
+ max_seq_len = tinychat.utils.constants.max_seq_len
23
+
24
+
25
+ class QuantLlamaRotaryEmbedding(nn.Module):
26
+ def __init__(self, dim, max_position_embeddings=2048, base=10000, device=None):
27
+ super().__init__()
28
+
29
+ self.dim = dim
30
+ self.max_position_embeddings = max_position_embeddings
31
+ self.base = base
32
+ inv_freq = 1.0 / (
33
+ self.base ** (torch.arange(0, self.dim, 2).float().to(device) / self.dim)
34
+ )
35
+ self.register_buffer("inv_freq", inv_freq)
36
+ # Build here to make `torch.jit.trace` work.
37
+ self._set_cos_sin_cache(
38
+ seq_len=max_position_embeddings,
39
+ device=self.inv_freq.device,
40
+ dtype=torch.get_default_dtype(),
41
+ )
42
+
43
+ def _set_cos_sin_cache(self, seq_len, device, dtype):
44
+ self.max_seq_len_cached = seq_len
45
+ t = torch.arange(
46
+ self.max_seq_len_cached, device=device, dtype=self.inv_freq.dtype
47
+ )
48
+
49
+ freqs = torch.einsum("i,j->ij", t, self.inv_freq)
50
+ # Different from paper, but it uses a different permutation in order to obtain the same calculation
51
+ # emb = torch.cat((freqs, freqs), dim=-1)
52
+
53
+ cos = freqs.cos()
54
+ sin = freqs.sin()
55
+ cache = torch.cat((cos, sin), dim=-1)
56
+
57
+ # self.register_buffer("cos_cached", emb.cos()[None, None, :, :].to(dtype), persistent=False)
58
+ # self.register_buffer("sin_cached", emb.sin()[None, None, :, :].to(dtype), persistent=False)
59
+ self.register_buffer("cos_sin_cache", cache.half(), persistent=False)
60
+
61
+ def forward(
62
+ self,
63
+ query: torch.Tensor,
64
+ key: torch.Tensor,
65
+ positions: torch.Tensor,
66
+ ):
67
+ # Apply rotary embedding to the query and key before passing them
68
+ # to the attention op.
69
+ # print(positions.shape, query.shape, key.shape, self.cos_sin_cache.shape)
70
+ query = query.contiguous()
71
+ key = key.contiguous()
72
+ awq_inference_engine.rotary_embedding_neox(
73
+ positions,
74
+ query,
75
+ key,
76
+ self.dim,
77
+ self.cos_sin_cache,
78
+ )
79
+ return query, key
80
+
81
+
82
+ class QuantLlamaAttention(nn.Module):
83
+ """Multi-headed attention from 'Attention Is All You Need' paper"""
84
+
85
+ def __init__(self, hidden_size, num_heads, qkv_proj, o_proj, dev):
86
+ super().__init__()
87
+ self.hidden_size = hidden_size
88
+ self.num_heads = num_heads
89
+ self.head_dim = hidden_size // num_heads
90
+
91
+ if (self.head_dim * num_heads) != self.hidden_size:
92
+ raise ValueError(
93
+ f"hidden_size must be divisible by num_heads (got `hidden_size`: {self.hidden_size}"
94
+ f" and `num_heads`: {num_heads})."
95
+ )
96
+ self.qkv_proj = qkv_proj
97
+ self.o_proj = o_proj
98
+ self.rotary_emb = QuantLlamaRotaryEmbedding(
99
+ self.head_dim, max_position_embeddings=2048, device=dev
100
+ )
101
+
102
+ def forward(
103
+ self,
104
+ hidden_states,
105
+ past_key_value=None,
106
+ attention_mask=None,
107
+ position_ids=None,
108
+ output_attentions=False,
109
+ use_cache=False,
110
+ ):
111
+ """Input shape: Batch x Time x Channel"""
112
+
113
+ bsz, q_len, _ = hidden_states.size()
114
+
115
+ qkv_states = self.qkv_proj(hidden_states)
116
+ qkv_states = qkv_states.view(bsz, q_len, 3, self.num_heads, self.head_dim)
117
+
118
+ # This updates the query and key states in-place, saving VRAM.
119
+ query_states, key_states, value_states = torch.split(qkv_states, 1, dim=2)
120
+ query_states, key_states = self.rotary_emb(
121
+ query_states, key_states, position_ids
122
+ )
123
+
124
+ del qkv_states
125
+ query_states = query_states.view(
126
+ bsz, q_len, self.num_heads, self.head_dim
127
+ ).transpose(1, 2)
128
+ key_states = key_states.view(
129
+ bsz, q_len, self.num_heads, self.head_dim
130
+ ).transpose(1, 2)
131
+ value_states = value_states.view(
132
+ bsz, q_len, self.num_heads, self.head_dim
133
+ ).transpose(1, 2)
134
+
135
+ is_causal = past_key_value is None
136
+
137
+ kv_seq_len = q_len
138
+ if past_key_value is not None:
139
+ kv_seq_len += past_key_value[0].shape[-2]
140
+
141
+ value_states = value_states.to("cuda:0")
142
+
143
+ if past_key_value is not None:
144
+ # reuse k, v, self_attention
145
+ key_states = torch.cat([past_key_value[0], key_states], dim=2)
146
+ value_states = torch.cat([past_key_value[1], value_states], dim=2)
147
+
148
+ if use_cache:
149
+ # Since qkv_proj is fused, query_states etc will hold a reference to the original qkv_states tensor
150
+ # which can cause excessive memory usage by the cache. `contiguous` is a convenient way to workaround this.
151
+ key_states = key_states.contiguous()
152
+ value_states = value_states.contiguous()
153
+ query_states = query_states.contiguous()
154
+
155
+ past_key_value = (key_states, value_states) if use_cache else None
156
+
157
+ # with torch.backends.cuda.sdp_kernel(enable_math=False):
158
+ attn_output = F.scaled_dot_product_attention(
159
+ query_states, key_states, value_states, is_causal=is_causal
160
+ )
161
+ del query_states, key_states, value_states
162
+
163
+ attn_output = attn_output.transpose(1, 2).reshape(bsz, q_len, self.hidden_size)
164
+ attn_output = self.o_proj(attn_output)
165
+
166
+ return attn_output, None, past_key_value
167
+
168
+
169
+ class QuantLlamaAttentionFused(nn.Module):
170
+ def __init__(
171
+ self, hidden_size, num_heads, kv_max_seq_len, qkv_layer, o_proj, dev, args
172
+ ):
173
+ super().__init__()
174
+
175
+ self.args = args
176
+ self.n_local_heads = args.num_attention_heads
177
+ self.hidden_size = args.hidden_size
178
+ self.num_heads = args.num_attention_heads
179
+ self.head_dim = self.hidden_size // self.num_heads
180
+
181
+ self.num_key_value_heads = args.num_key_value_heads
182
+ self.num_key_value_groups = self.num_heads // self.num_key_value_heads
183
+ self.max_position_embeddings = args.max_position_embeddings
184
+ self.rope_theta = args.rope_theta
185
+ self.rope_scaling = args.rope_scaling
186
+ if self.rope_scaling is None:
187
+ self.rope_scaling = 1.0
188
+ if isinstance(self.rope_scaling, dict):
189
+ self.rope_scaling = self.rope_scaling.get("factor", 1.0)
190
+
191
+ self.qkv_proj = qkv_layer
192
+ self.o_proj = o_proj
193
+
194
+ self.kv_max_seq_len = kv_max_seq_len
195
+
196
+ # following fastertransformer definition
197
+ self.cache_v = (
198
+ torch.zeros(
199
+ (
200
+ max_batch_size,
201
+ self.num_key_value_heads,
202
+ # args.max_position_embeddings,
203
+ self.kv_max_seq_len,
204
+ self.head_dim,
205
+ )
206
+ )
207
+ .to(dev)
208
+ .half()
209
+ ) # added to half
210
+ # 8: pack 8 fp16 in FT, if fp32 then use 4
211
+ self.cache_k = (
212
+ torch.zeros(
213
+ (
214
+ max_batch_size,
215
+ self.num_key_value_heads,
216
+ self.head_dim // 8,
217
+ # args.max_position_embeddings,
218
+ self.kv_max_seq_len,
219
+ 8,
220
+ )
221
+ )
222
+ .to(dev)
223
+ .half()
224
+ ) # added to half
225
+
226
+ def forward(
227
+ self,
228
+ x: torch.Tensor,
229
+ start_pos: int,
230
+ freqs: torch.Tensor,
231
+ mask: Optional[torch.Tensor],
232
+ chunk_prefilling: bool = False,
233
+ ):
234
+ bsz, seqlen, _ = x.shape
235
+ xqkv = self.qkv_proj(x)
236
+ xqkv = xqkv.view(
237
+ bsz,
238
+ seqlen,
239
+ self.n_local_heads + self.num_key_value_heads * 2,
240
+ self.head_dim,
241
+ )
242
+ xq = xqkv[:, :, 0 : self.n_local_heads]
243
+ xk = xqkv[
244
+ :, :, self.n_local_heads : (self.n_local_heads + self.num_key_value_heads)
245
+ ]
246
+ xv = xqkv[:, :, -self.num_key_value_heads :]
247
+
248
+ if seqlen > 1:
249
+ xq = xq.view(bsz, seqlen, self.n_local_heads, self.head_dim)
250
+ xk = xk.view(bsz, seqlen, self.num_key_value_heads, self.head_dim)
251
+ xv = xv.view(bsz, seqlen, self.num_key_value_heads, self.head_dim)
252
+
253
+ xq = awq_inference_engine.fused_rope_with_pos_forward_func(xq, freqs, True)
254
+ xk = awq_inference_engine.fused_rope_with_pos_forward_func(xk, freqs, True)
255
+
256
+ self.cache_k = self.cache_k.to(xq)
257
+ self.cache_v = self.cache_v.to(xq)
258
+
259
+ values_store = xv.transpose(2, 1)
260
+ keys_store = (
261
+ xk.reshape(bsz, seqlen, self.num_key_value_heads, self.head_dim // 8, 8)
262
+ .permute(0, 2, 3, 1, 4)
263
+ .contiguous()
264
+ )
265
+
266
+ self.cache_v[:bsz, :, start_pos : start_pos + seqlen, :] = values_store
267
+ self.cache_k[:bsz, :, :, start_pos : start_pos + seqlen, :] = keys_store
268
+ if chunk_prefilling:
269
+ keys = self.cache_k[:, :, :, 0:start_pos, :]
270
+ keys = (
271
+ keys.permute(0, 3, 1, 2, 4)
272
+ .reshape(bsz, start_pos, self.num_key_value_heads, self.head_dim)
273
+ .contiguous()
274
+ )
275
+ keys = torch.cat((keys, xk), dim=1)
276
+ values = self.cache_v[:, :, 0:start_pos, :]
277
+ values = (
278
+ values.transpose(2, 1)
279
+ .reshape(bsz, start_pos, self.num_key_value_heads, self.head_dim)
280
+ .contiguous()
281
+ )
282
+ values = torch.cat((values, xv), dim=1)
283
+ else:
284
+ keys = xk
285
+ values = xv
286
+
287
+ keys = torch.repeat_interleave(
288
+ keys, dim=2, repeats=self.num_key_value_groups
289
+ )
290
+ values = torch.repeat_interleave(
291
+ values, dim=2, repeats=self.num_key_value_groups
292
+ )
293
+
294
+ xq = xq.transpose(1, 2)
295
+ keys = keys.transpose(1, 2)
296
+ values = values.transpose(1, 2)
297
+ scores = torch.matmul(xq, keys.transpose(2, 3)) / math.sqrt(self.head_dim)
298
+ if mask is not None:
299
+ scores = scores + mask # (bs, n_local_heads, slen, cache_len + slen)
300
+ scores = F.softmax(scores.float(), dim=-1).type_as(xq)
301
+ output = torch.matmul(scores, values) # (bs, n_local_heads, slen, head_dim)
302
+ output = output.transpose(1, 2).contiguous().view(bsz, seqlen, -1)
303
+ else:
304
+ xq = xq.view(bsz, self.n_local_heads, self.head_dim)
305
+ xk = xk.view(bsz, self.num_key_value_heads, self.head_dim)
306
+ xv = xv.view(bsz, self.num_key_value_heads, self.head_dim)
307
+
308
+ output = awq_inference_engine.single_query_attention(
309
+ xq,
310
+ xk,
311
+ xv,
312
+ self.cache_k,
313
+ self.cache_v,
314
+ None,
315
+ None,
316
+ start_pos,
317
+ self.head_dim,
318
+ self.rope_theta,
319
+ self.rope_scaling,
320
+ True,
321
+ )
322
+ output = output.reshape(bsz, 1, -1)
323
+
324
+ return self.o_proj(output)
325
+
326
+
327
+ class QuantLlamaAttentionFusedFlash(nn.Module):
328
+ """Flash_attn_func from 'Flash{A}ttention-2: Faster Attention with Better Parallelism and Work Partitioning' paper"""
329
+
330
+ """This function is faster than the varlen one but only supports single-batch inference"""
331
+
332
+ def __init__(
333
+ self, hidden_size, num_heads, kv_max_seq_len, qkv_layer, o_proj, dev, args
334
+ ):
335
+ super().__init__()
336
+
337
+ self.args = args
338
+ self.n_local_heads = args.num_attention_heads
339
+ self.hidden_size = args.hidden_size
340
+ self.num_heads = args.num_attention_heads
341
+ self.head_dim = self.hidden_size // self.num_heads
342
+
343
+ self.num_key_value_heads = args.num_key_value_heads
344
+ self.num_key_value_groups = self.num_heads // self.num_key_value_heads
345
+ self.max_position_embeddings = args.max_position_embeddings
346
+ self.rope_theta = args.rope_theta
347
+ self.rope_scaling = args.rope_scaling
348
+ if self.rope_scaling is None:
349
+ self.rope_scaling = 1.0
350
+ elif isinstance(self.rope_scaling, dict):
351
+ self.rope_scaling = self.rope_scaling.get("factor", 1.0)
352
+
353
+ self.qkv_proj = qkv_layer
354
+ self.o_proj = o_proj
355
+
356
+ self.kv_max_seq_len = kv_max_seq_len
357
+ # following fastertransformer definition
358
+ # For short seqlence, we use fused kernel to accelerate decoding.
359
+ if self.kv_max_seq_len <= 8192:
360
+ self.cache_v = (
361
+ torch.zeros(
362
+ (
363
+ max_batch_size,
364
+ self.num_key_value_heads,
365
+ # args.max_position_embeddings,
366
+ self.kv_max_seq_len,
367
+ self.head_dim,
368
+ )
369
+ )
370
+ .to(dev)
371
+ .half()
372
+ ) # added to half
373
+ # 8: pack 8 fp16 in FT, if fp32 then use 4
374
+ self.cache_k = (
375
+ torch.zeros(
376
+ (
377
+ max_batch_size,
378
+ self.num_key_value_heads,
379
+ self.head_dim // 8,
380
+ # args.max_position_embeddings,
381
+ kv_max_seq_len,
382
+ 8,
383
+ )
384
+ )
385
+ .to(dev)
386
+ .half()
387
+ ) # added to half
388
+ self.forward = self.short_forward
389
+ # For long sequence, we use flash attantion for both prefilling and decoding to avoid OOM.
390
+ else:
391
+ self.cache_v = (
392
+ torch.zeros(
393
+ (
394
+ max_batch_size,
395
+ self.kv_max_seq_len,
396
+ self.num_key_value_heads,
397
+ self.head_dim,
398
+ )
399
+ )
400
+ .to(dev)
401
+ .half()
402
+ ) # added to half
403
+ self.cache_k = (
404
+ torch.zeros(
405
+ (
406
+ max_batch_size,
407
+ self.kv_max_seq_len,
408
+ self.num_key_value_heads,
409
+ self.head_dim,
410
+ )
411
+ )
412
+ .to(dev)
413
+ .half()
414
+ ) # added to half
415
+ self.forward = self.long_forward
416
+
417
+ def short_forward(
418
+ self,
419
+ x: torch.Tensor,
420
+ start_pos: int,
421
+ freqs: torch.Tensor,
422
+ mask: Optional[torch.Tensor],
423
+ chunk_prefilling: bool = False,
424
+ ):
425
+ bsz, seqlen, _ = x.shape
426
+ xqkv = self.qkv_proj(x)
427
+ xqkv = xqkv.view(
428
+ bsz,
429
+ seqlen,
430
+ self.n_local_heads + self.num_key_value_heads * 2,
431
+ self.head_dim,
432
+ )
433
+ xq = xqkv[:, :, 0 : self.n_local_heads]
434
+ xk = xqkv[
435
+ :, :, self.n_local_heads : (self.n_local_heads + self.num_key_value_heads)
436
+ ]
437
+ xv = xqkv[:, :, -self.num_key_value_heads :]
438
+
439
+ if seqlen > 1:
440
+ xq = awq_inference_engine.fused_rope_with_pos_forward_func(xq, freqs, True)
441
+ xk = awq_inference_engine.fused_rope_with_pos_forward_func(xk, freqs, True)
442
+
443
+ self.cache_k = self.cache_k.to(xq)
444
+ self.cache_v = self.cache_v.to(xq)
445
+
446
+ values_store = xv.transpose(2, 1)
447
+ keys_store = (
448
+ xk.reshape(bsz, seqlen, self.num_key_value_heads, self.head_dim // 8, 8)
449
+ .permute(0, 2, 3, 1, 4)
450
+ .contiguous()
451
+ )
452
+
453
+ self.cache_v[:bsz, :, start_pos : start_pos + seqlen, :] = values_store
454
+ self.cache_k[:bsz, :, :, start_pos : start_pos + seqlen, :] = keys_store
455
+
456
+ if chunk_prefilling:
457
+ keys = self.cache_k[:, :, :, 0 : start_pos + seqlen, :]
458
+ keys = (
459
+ keys.permute(0, 3, 1, 2, 4)
460
+ .reshape(
461
+ bsz, start_pos + seqlen, self.num_key_value_heads, self.head_dim
462
+ )
463
+ .contiguous()
464
+ )
465
+ values = self.cache_v[:, :, 0 : start_pos + seqlen, :]
466
+ values = (
467
+ values.transpose(2, 1)
468
+ .reshape(
469
+ bsz, start_pos + seqlen, self.num_key_value_heads, self.head_dim
470
+ )
471
+ .contiguous()
472
+ )
473
+ else:
474
+ keys = xk
475
+ values = xv
476
+
477
+ output = flash_attn_func(
478
+ q=xq,
479
+ k=keys,
480
+ v=values,
481
+ causal=True,
482
+ )
483
+ output = output.contiguous().view(bsz, seqlen, -1)
484
+ else:
485
+ xq = xq.view(bsz, self.n_local_heads, self.head_dim)
486
+ xk = xk.view(bsz, self.num_key_value_heads, self.head_dim)
487
+ xv = xv.view(bsz, self.num_key_value_heads, self.head_dim)
488
+ output = awq_inference_engine.single_query_attention(
489
+ xq,
490
+ xk,
491
+ xv,
492
+ self.cache_k,
493
+ self.cache_v,
494
+ None,
495
+ None,
496
+ start_pos,
497
+ self.head_dim,
498
+ self.rope_theta,
499
+ self.rope_scaling,
500
+ True,
501
+ )
502
+ output = output.reshape(bsz, 1, -1)
503
+ return self.o_proj(output)
504
+
505
+ def long_forward(
506
+ self,
507
+ x: torch.Tensor,
508
+ start_pos: int,
509
+ freqs: torch.Tensor,
510
+ mask: Optional[torch.Tensor],
511
+ chunk_prefilling: bool = False,
512
+ ):
513
+ bsz, seqlen, _ = x.shape
514
+ xqkv = self.qkv_proj(x)
515
+ xqkv = xqkv.view(
516
+ bsz,
517
+ seqlen,
518
+ self.n_local_heads + self.num_key_value_heads * 2,
519
+ self.head_dim,
520
+ )
521
+ xq = xqkv[:, :, 0 : self.n_local_heads]
522
+ xk = xqkv[
523
+ :, :, self.n_local_heads : (self.n_local_heads + self.num_key_value_heads)
524
+ ]
525
+ xv = xqkv[:, :, -self.num_key_value_heads :]
526
+
527
+ xq = awq_inference_engine.fused_rope_with_pos_forward_func(xq, freqs, True)
528
+ xk = awq_inference_engine.fused_rope_with_pos_forward_func(xk, freqs, True)
529
+
530
+ self.cache_k = self.cache_k.to(xq)
531
+ self.cache_v = self.cache_v.to(xq)
532
+
533
+ self.cache_v[:bsz, start_pos : start_pos + seqlen] = xv
534
+ self.cache_k[:bsz, start_pos : start_pos + seqlen] = xk
535
+
536
+ keys = self.cache_k[:, 0 : start_pos + seqlen]
537
+ values = self.cache_v[:, 0 : start_pos + seqlen]
538
+
539
+ output = flash_attn_func(
540
+ q=xq,
541
+ k=keys,
542
+ v=values,
543
+ causal=True,
544
+ )
545
+ output = output.view(bsz, seqlen, -1)
546
+ return self.o_proj(output)
547
+
548
+
549
+ def make_quant_attn(model, dev, flash_attn=True):
550
+ """
551
+ Replace all LlamaAttention modules with QuantLlamaAttention modules, fusing the q, k, v projections.
552
+ """
553
+ model = model.cpu()
554
+ for name, m in model.named_modules():
555
+ if not m.__class__.__name__ in [
556
+ "LlamaAttention",
557
+ "LlamaAttentionFused",
558
+ "Qwen2AttentionFused",
559
+ ]:
560
+ continue
561
+
562
+ q_proj = m.q_proj
563
+ k_proj = m.k_proj
564
+ v_proj = m.v_proj
565
+
566
+ qweights = torch.cat([q_proj.qweight, k_proj.qweight, v_proj.qweight], dim=0)
567
+ scaled_zeros = torch.cat(
568
+ [q_proj.scaled_zeros, k_proj.scaled_zeros, v_proj.scaled_zeros], dim=1
569
+ ).contiguous()
570
+ scales = torch.cat(
571
+ [q_proj.scales, k_proj.scales, v_proj.scales], dim=1
572
+ ).contiguous()
573
+ # g_idx = torch.cat([q_proj.g_idx, k_proj.g_idx, v_proj.g_idx], dim=0)
574
+ g_idx = None
575
+ bias = (
576
+ torch.cat([q_proj.bias, k_proj.bias, v_proj.bias], dim=0)
577
+ if q_proj.bias is not None
578
+ else None
579
+ )
580
+
581
+ qkv_layer = WQLinear(
582
+ q_proj.w_bit,
583
+ q_proj.group_size,
584
+ q_proj.in_features,
585
+ q_proj.out_features + k_proj.out_features + v_proj.out_features,
586
+ q_proj.bias is not None,
587
+ q_proj.qweight.device,
588
+ )
589
+ qkv_layer.qweight = qweights
590
+ qkv_layer.scaled_zeros = scaled_zeros
591
+ qkv_layer.scales = scales
592
+
593
+ qkv_layer.bias = bias
594
+ qkv_layer.split_k_iters = q_proj.split_k_iters
595
+ # We're dropping the rotary embedding layer m.rotary_emb here. We don't need it in the triton branch.
596
+ if isinstance(m, LlamaAttention):
597
+ attn = QuantLlamaAttention(
598
+ m.hidden_size, m.num_heads, qkv_layer, m.o_proj, dev
599
+ )
600
+ else:
601
+ if flash_attn:
602
+ attn = QuantLlamaAttentionFusedFlash(
603
+ m.args.hidden_size,
604
+ m.args.num_attention_heads,
605
+ m.kv_max_seq_len,
606
+ qkv_layer,
607
+ m.o_proj,
608
+ dev,
609
+ m.args,
610
+ )
611
+ else:
612
+ attn = QuantLlamaAttentionFused(
613
+ m.args.hidden_size,
614
+ m.args.num_attention_heads,
615
+ m.kv_max_seq_len,
616
+ qkv_layer,
617
+ m.o_proj,
618
+ dev,
619
+ m.args,
620
+ )
621
+ if "." in name:
622
+ parent_name = name.rsplit(".", 1)[0]
623
+ child_name = name[len(parent_name) + 1 :]
624
+ parent = model.get_submodule(parent_name)
625
+ else:
626
+ parent_name = ""
627
+ parent = model
628
+ child_name = name
629
+
630
+ # print(f"Replacing {name} with quant_attn; parent: {parent_name}, child's name: {child_name}")
631
+ setattr(parent, child_name, attn)
632
+ gc.collect()
633
+ torch.cuda.empty_cache()
634
+ model = model.to(dev)
llm-awq/tinychat/modules/fused_internencoder.py ADDED
@@ -0,0 +1,237 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Optional, Tuple, Union
2
+
3
+ import torch
4
+ import torch.nn.functional as F
5
+ import torch.utils.checkpoint
6
+ from einops import rearrange
7
+ from timm.layers import DropPath
8
+ from torch import nn
9
+ from transformers.activations import ACT2FN
10
+ from transformers.modeling_outputs import (BaseModelOutput,
11
+ BaseModelOutputWithPooling)
12
+ from transformers.modeling_utils import PreTrainedModel
13
+ from transformers.utils import logging
14
+
15
+ from awq.quantize import W8A8OF16LinearDynamicInputScale
16
+ import awq_inference_engine
17
+
18
+ from tinychat.models.internvl.internvit import (FlashAttention,
19
+ InternRMSNorm,
20
+ InternVisionEmbeddings,
21
+ InternAttention,
22
+ InternMLP,
23
+ InternVisionEncoderLayer,
24
+ InternVisionEncoder)
25
+ from tinychat.models.internvl.configuration_internvl import InternVisionConfig
26
+
27
+ try:
28
+ from flash_attn.bert_padding import pad_input, unpad_input
29
+ from flash_attn.flash_attn_interface import \
30
+ flash_attn_varlen_qkvpacked_func
31
+ has_flash_attn = True
32
+ except:
33
+ print('FlashAttention2 is not installed.')
34
+ has_flash_attn = False
35
+
36
+ logger = logging.get_logger(__name__)
37
+
38
+
39
+ class QuantInternVisionEncoder(nn.Module):
40
+ """
41
+ Transformer encoder consisting of `config.num_hidden_layers` self attention layers. Each layer is a
42
+ [`InternEncoderLayer`].
43
+
44
+ Args:
45
+ config (`InternConfig`):
46
+ The corresponding vision configuration for the `InternEncoder`.
47
+ """
48
+
49
+ def __init__(self, module: InternVisionEncoder, bsz=64, seqlen=1024):
50
+ super().__init__()
51
+ self.config = module.config
52
+ # stochastic depth decay rule
53
+ self.layers = nn.ModuleList([QuantInternVisionEncoderLayer(layer, self.config) for layer in module.layers])
54
+ self.gradient_checkpointing = True
55
+ self.bsz = bsz
56
+ self.seqlen = seqlen
57
+
58
+ def forward(
59
+ self,
60
+ inputs_embeds,
61
+ attention_mask: Optional[torch.Tensor] = None,
62
+ output_attentions: Optional[bool] = None,
63
+ output_hidden_states: Optional[bool] = None,
64
+ return_dict: Optional[bool] = None,
65
+ ) -> Union[Tuple, BaseModelOutput]:
66
+ r"""
67
+ Args:
68
+ inputs_embeds (`torch.FloatTensor` of shape `(batch_size, sequence_length, hidden_size)`):
69
+ Embedded representation of the inputs. Should be float, not int tokens.
70
+ output_hidden_states (`bool`, *optional*):
71
+ Whether or not to return the hidden states of all layers. See `hidden_states` under returned tensors
72
+ for more detail.
73
+ return_dict (`bool`, *optional*):
74
+ Whether or not to return a [`~utils.ModelOutput`] instead of a plain tuple.
75
+ """
76
+ output_hidden_states = (
77
+ output_hidden_states if output_hidden_states is not None else self.config.output_hidden_states
78
+ )
79
+ return_dict = return_dict if return_dict is not None else self.config.use_return_dict
80
+
81
+ encoder_states = () if output_hidden_states else None
82
+ hidden_states = inputs_embeds
83
+
84
+ for idx, encoder_layer in enumerate(self.layers):
85
+ if output_hidden_states:
86
+ encoder_states = encoder_states + (hidden_states,)
87
+ if self.gradient_checkpointing and self.training:
88
+ layer_outputs = torch.utils.checkpoint.checkpoint(
89
+ encoder_layer,
90
+ hidden_states)
91
+ else:
92
+ layer_outputs = encoder_layer(
93
+ hidden_states,
94
+ )
95
+ hidden_states = layer_outputs
96
+
97
+ if output_hidden_states:
98
+ encoder_states = encoder_states + (hidden_states,)
99
+
100
+ if not return_dict:
101
+ return tuple(v for v in [hidden_states, encoder_states] if v is not None)
102
+ return BaseModelOutput(
103
+ last_hidden_state=hidden_states, hidden_states=encoder_states
104
+ )
105
+
106
+ class QuantInternRMSNorm(nn.Module):
107
+ def __init__(self, module: nn.Module, use_per_token_quant=True):
108
+ super().__init__()
109
+ self.weight = nn.Parameter(module.weight.data, requires_grad=False)
110
+ self.bias = nn.Parameter(module.bias.data, requires_grad=False)
111
+ self.variance_epsilon = module.eps
112
+ self.use_per_token_quant = use_per_token_quant
113
+
114
+ def forward(self, hidden_states):
115
+ bsz, seqlen, hidden_size = hidden_states.shape
116
+ output = torch.empty((bsz * seqlen), hidden_size, device=hidden_states.device, dtype=torch.int8)
117
+ scale = torch.empty((bsz * seqlen), device=hidden_states.device, dtype=hidden_states.dtype)
118
+ awq_inference_engine.rms_norm_general(
119
+ output,
120
+ hidden_states,
121
+ self.weight,
122
+ self.bias,
123
+ scale,
124
+ self.variance_epsilon,
125
+ self.use_per_token_quant,
126
+ )
127
+ return output, scale
128
+
129
+ class QuantInternAttention(nn.Module):
130
+ def __init__(self, module: InternAttention, config: InternVisionConfig, init_only=False):
131
+ super().__init__()
132
+ self.config = config
133
+ self.embed_dim = module.embed_dim
134
+ self.num_heads = module.num_heads
135
+ self.head_dim = self.embed_dim // self.num_heads
136
+ self.scale = module.scale
137
+ self.use_flash_attn = config.use_flash_attn
138
+
139
+ self.qkv = W8A8OF16LinearDynamicInputScale.from_linear(module.qkv, init_only=init_only)
140
+ self.proj = W8A8OF16LinearDynamicInputScale.from_linear(module.proj, init_only=init_only)
141
+
142
+ self.qk_normalization = module.qk_normalization
143
+ if self.qk_normalization:
144
+ self.q_norm = QuantInternRMSNorm(module.q_norm)
145
+ self.k_norm = QuantInternRMSNorm(module.k_norm)
146
+
147
+ if self.use_flash_attn:
148
+ from tinychat.models.internvl.internvit import FlashAttention
149
+ self.inner_attn = FlashAttention(attention_dropout=config.attention_dropout)
150
+
151
+ def forward(self, hidden_states: torch.Tensor, scale_in: torch.Tensor):
152
+ bsz, seqlen, hidden_size = hidden_states.shape
153
+
154
+ qkv_out = torch.empty(bsz * seqlen, 3 * hidden_size, dtype=torch.float16, device=hidden_states.device)
155
+ self.qkv(hidden_states.reshape(-1, hidden_size), scale_in, qkv_out)
156
+
157
+ qkv = rearrange(qkv_out.view(bsz, seqlen, -1), 'b s (three h d) -> b s three h d', three=3, h=self.num_heads)
158
+
159
+ if self.qk_normalization:
160
+ q, k, v = qkv.unbind(2)
161
+ q, _ = self.q_norm(q.flatten(-2, -1)); q = q.view_as(q)
162
+ k, _ = self.k_norm(k.flatten(-2, -1)); k = k.view_as(k)
163
+ qkv = torch.stack([q, k, v], dim=2)
164
+
165
+ attn_out, _ = self.inner_attn(qkv, need_weights=False, causal=False)
166
+ attn_out = rearrange(attn_out, 'b s h d -> (b s) (h d)')
167
+
168
+ quant_out = torch.empty_like(attn_out, dtype=torch.int8)
169
+ scale_proj_in = torch.empty(bsz * seqlen, device=hidden_states.device, dtype=torch.float16)
170
+ awq_inference_engine.invoke_quant(quant_out, attn_out, scale_proj_in)
171
+
172
+ proj_out = torch.empty_like(attn_out)
173
+ self.proj(quant_out, scale_proj_in, proj_out)
174
+
175
+ return proj_out
176
+
177
+ class QuantInternMLP(nn.Module):
178
+ def __init__(self, module: InternMLP, config: InternVisionConfig):
179
+ super().__init__()
180
+ self.config = config
181
+ self.act = module.act
182
+ self.fc1 = W8A8OF16LinearDynamicInputScale.from_linear(module.fc1)
183
+ self.fc2 = W8A8OF16LinearDynamicInputScale.from_linear(module.fc2)
184
+
185
+ def forward(self, hidden_states: torch.Tensor, scale_in: torch.Tensor):
186
+ bsz, seqlen, hidden_size = hidden_states.shape
187
+ device = hidden_states.device
188
+
189
+ fc1_out = torch.empty((bsz * seqlen), self.config.intermediate_size, dtype=torch.float16, device=device)
190
+ self.fc1(hidden_states.reshape(-1, hidden_size), scale_in, fc1_out)
191
+
192
+ tmp = torch.empty(
193
+ ((bsz * seqlen) * self.config.intermediate_size),
194
+ device=device,
195
+ dtype=torch.float16,
196
+ )
197
+ act_out = torch.empty_like(fc1_out, dtype=torch.int8)
198
+ scale_act = torch.empty(bsz * seqlen, device=device, dtype=torch.float16)
199
+ awq_inference_engine.gelu_and_quant(act_out, fc1_out, scale_act, tmp)
200
+
201
+ fc2_out = torch.empty((bsz * seqlen), hidden_size, dtype=torch.float16, device=device)
202
+ self.fc2(act_out, scale_act, fc2_out)
203
+
204
+ return fc2_out
205
+
206
+ class QuantInternVisionEncoderLayer(nn.Module):
207
+ def __init__(self, module: InternVisionEncoderLayer, config: InternVisionConfig):
208
+ super().__init__()
209
+ self.config = config
210
+ self.embed_dim = config.hidden_size
211
+ self.intermediate_size = config.intermediate_size
212
+
213
+ self.attn = QuantInternAttention(module.attn, config)
214
+ self.mlp = QuantInternMLP(module.mlp, config)
215
+
216
+ self.norm1 = QuantInternRMSNorm(module.norm1)
217
+ self.norm2 = QuantInternRMSNorm(module.norm2)
218
+
219
+ self.ls1 = module.ls1
220
+ self.ls2 = module.ls2
221
+
222
+ def forward(self, hidden_states: torch.Tensor):
223
+ bsz, seqlen, hidden_size = hidden_states.shape
224
+
225
+ residual = hidden_states
226
+ norm1_out, scale1 = self.norm1(hidden_states)
227
+ attn_out = self.attn(norm1_out.view(bsz, seqlen, hidden_size), scale1)
228
+ hidden_states = residual + attn_out.view(bsz, seqlen, hidden_size) * self.ls1
229
+
230
+ residual = hidden_states
231
+ norm2_out, scale2 = self.norm2(hidden_states)
232
+ mlp_out = self.mlp(norm2_out.view(bsz, seqlen, hidden_size), scale2)
233
+ hidden_states = residual + mlp_out.view(bsz, seqlen, hidden_size) * self.ls2
234
+
235
+ return hidden_states
236
+
237
+
llm-awq/tinychat/modules/fused_norm.py ADDED
@@ -0,0 +1,46 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ from torch import nn
3
+ from transformers.models.llama.modeling_llama import LlamaRMSNorm
4
+ import awq_inference_engine
5
+
6
+
7
+ class FTLlamaRMSNorm(nn.Module):
8
+ def __init__(self, weight, eps=1e-6):
9
+ """
10
+ LlamaRMSNorm is equivalent to T5LayerNorm
11
+ """
12
+ super().__init__()
13
+ self.weight = weight
14
+ self.variance_epsilon = eps
15
+
16
+ def forward(self, x):
17
+ output = torch.empty_like(x)
18
+ awq_inference_engine.layernorm_forward_cuda(
19
+ x, self.weight, output, self.variance_epsilon
20
+ )
21
+ return output
22
+
23
+
24
+ def make_quant_norm(model):
25
+ """
26
+ Replace all LlamaRMSNorm modules with FTLlamaRMSNorm modules
27
+ """
28
+
29
+ for name, m in model.named_modules():
30
+ if not isinstance(m, LlamaRMSNorm):
31
+ continue
32
+
33
+ norm = FTLlamaRMSNorm(m.weight, m.variance_epsilon)
34
+
35
+ if "." in name:
36
+ parent_name = name.rsplit(".", 1)[0]
37
+ child_name = name[len(parent_name) + 1 :]
38
+ parent = model.get_submodule(parent_name)
39
+ else:
40
+ parent_name = ""
41
+ parent = model
42
+ child_name = name
43
+
44
+ # print(f"Replacing {name} with quant_attn; parent: {parent_name}, child's name: {child_name}")
45
+
46
+ setattr(parent, child_name, norm)
llm-awq/tinychat/modules/fused_siglipdecoder.py ADDED
@@ -0,0 +1,282 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import torch
3
+ import torch.nn as nn
4
+ import torch.nn.functional as F
5
+ from awq.quantize import W8A8OF16LinearDynamicInputScale
6
+ from llava.model.multimodal_encoder.siglip.modeling_siglip import (
7
+ SiglipMLP,
8
+ SiglipEncoder,
9
+ SiglipAttention,
10
+ SiglipEncoderLayer,
11
+ )
12
+ from tinychat.utils.input_metadata import ActivationBuffer
13
+ from transformers.modeling_outputs import BaseModelOutput
14
+ from typing import Optional, Tuple, Union
15
+ from flash_attn import flash_attn_func
16
+ import time
17
+
18
+ CLIP_RANGE = 5
19
+
20
+
21
+ import awq_inference_engine
22
+
23
+
24
+ class QuantSiglipEncoder(nn.Module):
25
+ def __init__(self, module: SiglipEncoder, bsz=64, seqlen=1024):
26
+ super().__init__()
27
+ self.config = module.config
28
+ self.layers = [QuantSiglipEncoderLayer(layer) for layer in module.layers]
29
+ self.buffer = ActivationBuffer(module)
30
+ self.bsz = bsz
31
+ self.seqlen = seqlen
32
+ self.buffer.allocate_activation_buffer(self.bsz * self.seqlen)
33
+
34
+ # Ignore copy
35
+ def forward(
36
+ self,
37
+ inputs_embeds,
38
+ attention_mask: Optional[torch.Tensor] = None,
39
+ output_attentions: Optional[bool] = None, # dummy
40
+ output_hidden_states: Optional[bool] = None,
41
+ return_dict: Optional[bool] = None,
42
+ ) -> Union[Tuple, BaseModelOutput]:
43
+ # TODO Find why this code is necessary
44
+ # torch.sum(inputs_embeds!=inputs_embeds)
45
+ bsz, seqlen, _ = inputs_embeds.shape
46
+ if self.bsz != bsz or self.seqlen != seqlen:
47
+ self.buffer.allocate_activation_buffer(bsz * seqlen)
48
+ self.bsz = bsz
49
+ self.seqlen = seqlen
50
+
51
+ output_hidden_states = (
52
+ output_hidden_states
53
+ if output_hidden_states is not None
54
+ else self.config.output_hidden_states
55
+ )
56
+ return_dict = (
57
+ return_dict if return_dict is not None else self.config.use_return_dict
58
+ )
59
+
60
+ encoder_states = () if output_hidden_states else None
61
+
62
+ hidden_states = inputs_embeds
63
+ for i, encoder_layer in enumerate(self.layers):
64
+ if output_hidden_states:
65
+ encoder_states = encoder_states + (
66
+ hidden_states.reshape(bsz, seqlen, -1),
67
+ )
68
+ hidden_states = encoder_layer(
69
+ hidden_states, self.buffer, attention_mask, bsz, seqlen
70
+ )
71
+
72
+ if output_hidden_states:
73
+ encoder_states = encoder_states + (hidden_states.reshape(bsz, seqlen, -1),)
74
+ if not return_dict:
75
+ return tuple(v for v in [hidden_states, encoder_states] if v is not None)
76
+ return BaseModelOutput(
77
+ last_hidden_state=hidden_states.reshape(bsz, seqlen, -1),
78
+ hidden_states=encoder_states,
79
+ attentions=None,
80
+ )
81
+
82
+
83
+ class QuantSiglipMLP(nn.Module):
84
+ def __init__(self, siglipmlp, init_only=False):
85
+ super().__init__()
86
+ self.config = siglipmlp.config
87
+ self.activation_fn = siglipmlp.activation_fn
88
+ self.fc1 = W8A8OF16LinearDynamicInputScale.from_linear(
89
+ siglipmlp.fc1, init_only=init_only, fc1=False
90
+ )
91
+ self.fc2 = W8A8OF16LinearDynamicInputScale.from_linear(
92
+ siglipmlp.fc2, init_only=init_only
93
+ )
94
+ self.invoke_quant = self.invoke_quant_mlp
95
+
96
+ def invoke_quant_mlp(self, buffer, actfn_output):
97
+ awq_inference_engine.invoke_quant(
98
+ buffer.quantized_mlp_act_buffer,
99
+ actfn_output,
100
+ buffer.quantized_scale_buffer,
101
+ )
102
+
103
+ def forward(self, buffer: ActivationBuffer) -> torch.Tensor:
104
+ # INT8 in, FP16 out
105
+ self.fc1(
106
+ buffer.quantized_hidden_states_buffer,
107
+ buffer.quantized_scale_buffer,
108
+ buffer.fc1_buffer,
109
+ )
110
+ # Act & quantization
111
+ awq_inference_engine.gelu_and_quant(
112
+ buffer.quantized_mlp_act_buffer,
113
+ buffer.fc1_buffer,
114
+ buffer.quantized_scale_buffer,
115
+ buffer.tmp,
116
+ )
117
+ # INT8 in, FP16 out
118
+ self.fc2(
119
+ buffer.quantized_mlp_act_buffer,
120
+ buffer.quantized_scale_buffer,
121
+ buffer.in_out_fc2_act_buffer,
122
+ )
123
+
124
+
125
+ class QuantSiglipFlashAttention2(nn.Module):
126
+ def __init__(
127
+ self,
128
+ module: SiglipAttention,
129
+ init_only=False,
130
+ ):
131
+ super().__init__()
132
+ self.config = module.config
133
+ self.embed_dim = module.embed_dim
134
+ self.num_heads = module.num_heads
135
+ self.head_dim = self.embed_dim // self.num_heads
136
+
137
+ self.qkv_proj = W8A8OF16LinearDynamicInputScale.from_qkv(
138
+ module.q_proj, module.k_proj, module.v_proj, init_only=init_only
139
+ )
140
+ self.out_proj = W8A8OF16LinearDynamicInputScale.from_linear(
141
+ module.out_proj, init_only=init_only
142
+ )
143
+ self.invoke_quant = self.invoke_quant_wo
144
+
145
+ def invoke_quant_wo(self, buffer, attn_output):
146
+ awq_inference_engine.invoke_quant(
147
+ buffer.quantized_hidden_states_buffer,
148
+ attn_output,
149
+ buffer.quantized_scale_buffer,
150
+ )
151
+
152
+ # Adapted from transformers.models.llama.modeling_llama.LlamaFlashAttention2.forward
153
+ def forward(
154
+ self, buffer: ActivationBuffer, bsz=64, seqlen=1024
155
+ ) -> Tuple[torch.Tensor, Optional[torch.Tensor], Optional[Tuple[torch.Tensor]]]:
156
+ # qkv
157
+ self.qkv_proj(
158
+ buffer.quantized_hidden_states_buffer,
159
+ buffer.quantized_scale_buffer,
160
+ buffer.qkv_proj_act_buffer,
161
+ )
162
+ q, k, v = buffer.qkv_proj_act_buffer.split(
163
+ [self.embed_dim, self.embed_dim, self.embed_dim], dim=-1
164
+ )
165
+ q = q.reshape(bsz, seqlen, self.num_heads, self.head_dim)
166
+ k = k.reshape(bsz, seqlen, self.num_heads, self.head_dim)
167
+ v = v.reshape(bsz, seqlen, self.num_heads, self.head_dim)
168
+ attn_output = flash_attn_func(q, k, v, softmax_scale=None, causal=False)
169
+ attn_output = attn_output.reshape(bsz * seqlen, -1)
170
+ # FP16 -> int8
171
+ self.invoke_quant(buffer, attn_output)
172
+ # INT8 in, FP16 out
173
+ self.out_proj(
174
+ buffer.quantized_hidden_states_buffer,
175
+ buffer.quantized_scale_buffer,
176
+ buffer.in_out_fc2_act_buffer,
177
+ )
178
+
179
+
180
+ class QuantSiglipEncoderLayer(nn.Module):
181
+ def __init__(self, module: SiglipEncoderLayer):
182
+ super().__init__()
183
+ self.embed_dim = module.embed_dim
184
+ self.self_attn = QuantSiglipFlashAttention2(module.self_attn)
185
+ self.layer_norm1 = RMSNormGeneral(
186
+ module.layer_norm1.weight.data,
187
+ module.layer_norm1.bias.data,
188
+ module.layer_norm1.eps,
189
+ True,
190
+ ).cuda()
191
+ self.mlp = QuantSiglipMLP(module.mlp)
192
+ self.layer_norm2 = RMSNormGeneral(
193
+ module.layer_norm2.weight.data,
194
+ module.layer_norm2.bias.data,
195
+ module.layer_norm2.eps,
196
+ True,
197
+ ).cuda()
198
+ self.quant = self.invoke_quant_norm
199
+
200
+ def invoke_quant_norm(self, buffer, normfn_output):
201
+ awq_inference_engine.invoke_quant(
202
+ buffer.quantized_hidden_states_buffer,
203
+ normfn_output,
204
+ buffer.quantized_scale_buffer,
205
+ )
206
+
207
+ def forward(
208
+ self,
209
+ hidden_states: torch.Tensor,
210
+ buffer: ActivationBuffer,
211
+ attention_mask,
212
+ bsz,
213
+ seqlen,
214
+ ) -> Tuple[torch.FloatTensor]:
215
+ # Attention block
216
+ # FP16 in int8 out, layernorm & quantization
217
+ residual = hidden_states
218
+ self.layer_norm1(
219
+ hidden_states.reshape(-1, self.embed_dim),
220
+ buffer.quantized_hidden_states_buffer,
221
+ buffer.quantized_scale_buffer,
222
+ )
223
+
224
+ # INT8 -> FP16
225
+ self.self_attn(buffer, bsz, seqlen)
226
+ hidden_states = (
227
+ residual.reshape(-1, self.embed_dim) + buffer.in_out_fc2_act_buffer
228
+ )
229
+ # Fully Connected
230
+ residual = hidden_states
231
+ # FP16 in int8 out, layernorm & quantization
232
+ self.layer_norm2(
233
+ hidden_states.reshape(-1, self.embed_dim),
234
+ buffer.quantized_hidden_states_buffer,
235
+ buffer.quantized_scale_buffer,
236
+ )
237
+
238
+ # INT8 -> FP16
239
+ self.mlp(buffer)
240
+ hidden_states = (
241
+ residual.reshape(-1, self.embed_dim) + buffer.in_out_fc2_act_buffer
242
+ )
243
+ return hidden_states
244
+
245
+
246
+ class RMSNormGeneral(nn.Module):
247
+ """Root mean square normalization (w/ per-token or per-tensor quant).
248
+
249
+ Computes x -> w * x / sqrt(E[x^2] + eps) where w is the learned weight.
250
+ Refer to https://arxiv.org/abs/1910.07467
251
+ """
252
+
253
+ def __init__(
254
+ self,
255
+ weight: torch.tensor,
256
+ bias: torch.tensor,
257
+ eps: float = 1e-6,
258
+ use_per_token_quant: bool = True,
259
+ ) -> None:
260
+ super().__init__()
261
+ self.weight = nn.Parameter(weight, requires_grad=False)
262
+ self.bias = nn.Parameter(bias, requires_grad=False)
263
+ self.variance_epsilon = eps
264
+ self.use_per_token_quant = use_per_token_quant
265
+
266
+ def forward(
267
+ self,
268
+ x: torch.Tensor,
269
+ quantized_hidden_states_buffer: torch.Tensor,
270
+ quantized_scale_buffer: torch.Tensor,
271
+ quantized_sum_buffer: torch.Tensor = None,
272
+ ) -> torch.Tensor:
273
+ # quantized_sum_buffer is not used, only to keep the consistency of the interface
274
+ awq_inference_engine.rms_norm_general(
275
+ quantized_hidden_states_buffer,
276
+ x,
277
+ self.weight.data,
278
+ self.bias.data,
279
+ quantized_scale_buffer,
280
+ self.variance_epsilon,
281
+ self.use_per_token_quant,
282
+ )
llm-awq/tinychat/modules/fused_vision_attn.py ADDED
@@ -0,0 +1,272 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import math
2
+ import torch
3
+ import torch.nn as nn
4
+ from torch.nn import functional as F
5
+ from typing import Optional, Tuple
6
+
7
+ # from awq.quantize.qmodule import WQLinear
8
+ # import awq_inference_engine
9
+ # from tinychat.models.llama import apply_rotary_emb
10
+ import gc
11
+
12
+ import tinychat.utils.constants
13
+
14
+ max_batch_size = tinychat.utils.constants.max_batch_size
15
+ max_seq_len = tinychat.utils.constants.max_seq_len
16
+
17
+ from transformers.activations import ACT2FN
18
+ from transformers.models.clip.configuration_clip import (
19
+ CLIPConfig,
20
+ CLIPTextConfig,
21
+ CLIPVisionConfig,
22
+ )
23
+ from transformers.models.clip.modeling_clip import CLIPAttention
24
+
25
+
26
+ class CLIPAttentionFused(nn.Module):
27
+ """Multi-headed attention from 'Attention Is All You Need' paper"""
28
+
29
+ def __init__(
30
+ self, hidden_size, num_heads, qkv_proj, out_proj, dev, attention_dropout=0.0
31
+ ):
32
+ super().__init__()
33
+ self.embed_dim = hidden_size
34
+ self.num_heads = num_heads
35
+ self.head_dim = hidden_size // num_heads
36
+ self.scale = self.head_dim**-0.5
37
+ self.dropout = attention_dropout
38
+
39
+ if (self.head_dim * num_heads) != self.embed_dim:
40
+ raise ValueError(
41
+ f"hidden_size must be divisible by num_heads (got `hidden_size`: {self.hidden_size}"
42
+ f" and `num_heads`: {num_heads})."
43
+ )
44
+ self.qkv_proj = qkv_proj
45
+ self.out_proj = out_proj
46
+
47
+ def _shape(self, tensor: torch.Tensor, seq_len: int, bsz: int):
48
+ return (
49
+ tensor.view(bsz, seq_len, self.num_heads, self.head_dim)
50
+ .transpose(1, 2)
51
+ .contiguous()
52
+ )
53
+
54
+ def forward(
55
+ self,
56
+ hidden_states: torch.Tensor,
57
+ attention_mask: Optional[torch.Tensor] = None,
58
+ causal_attention_mask: Optional[torch.Tensor] = None,
59
+ output_attentions: Optional[bool] = False,
60
+ ) -> Tuple[torch.Tensor, Optional[torch.Tensor], Optional[Tuple[torch.Tensor]]]:
61
+ """Input shape: Batch x Time x Channel"""
62
+
63
+ bsz, tgt_len, embed_dim = hidden_states.size()
64
+
65
+ qkv_states = self.qkv_proj(hidden_states)
66
+ qkv_states = qkv_states.view(bsz, tgt_len, 3, self.num_heads, self.head_dim)
67
+
68
+ # This updates the query and key states in-place, saving VRAM.
69
+ query_states, key_states, value_states = torch.split(qkv_states, 1, dim=2)
70
+ del qkv_states
71
+
72
+ proj_shape = (bsz * self.num_heads, -1, self.head_dim)
73
+
74
+ query_states = (
75
+ query_states.view(bsz, tgt_len, self.num_heads, self.head_dim)
76
+ .transpose(1, 2)
77
+ .view(*proj_shape)
78
+ * self.scale
79
+ )
80
+ key_states = (
81
+ key_states.view(bsz, tgt_len, self.num_heads, self.head_dim)
82
+ .transpose(1, 2)
83
+ .view(*proj_shape)
84
+ )
85
+ value_states = (
86
+ value_states.view(bsz, tgt_len, self.num_heads, self.head_dim)
87
+ .transpose(1, 2)
88
+ .view(*proj_shape)
89
+ )
90
+
91
+ src_len = key_states.size(1)
92
+ attn_weights = torch.bmm(query_states, key_states.transpose(1, 2))
93
+
94
+ if attn_weights.size() != (bsz * self.num_heads, tgt_len, src_len):
95
+ raise ValueError(
96
+ f"Attention weights should be of size {(bsz * self.num_heads, tgt_len, src_len)}, but is"
97
+ f" {attn_weights.size()}"
98
+ )
99
+
100
+ # apply the causal_attention_mask first
101
+ if causal_attention_mask is not None:
102
+ if causal_attention_mask.size() != (bsz, 1, tgt_len, src_len):
103
+ raise ValueError(
104
+ f"Attention mask should be of size {(bsz, 1, tgt_len, src_len)}, but is"
105
+ f" {causal_attention_mask.size()}"
106
+ )
107
+ attn_weights = (
108
+ attn_weights.view(bsz, self.num_heads, tgt_len, src_len)
109
+ + causal_attention_mask
110
+ )
111
+ attn_weights = attn_weights.view(bsz * self.num_heads, tgt_len, src_len)
112
+
113
+ if attention_mask is not None:
114
+ if attention_mask.size() != (bsz, 1, tgt_len, src_len):
115
+ raise ValueError(
116
+ f"Attention mask should be of size {(bsz, 1, tgt_len, src_len)}, but is {attention_mask.size()}"
117
+ )
118
+ attn_weights = (
119
+ attn_weights.view(bsz, self.num_heads, tgt_len, src_len)
120
+ + attention_mask
121
+ )
122
+ attn_weights = attn_weights.view(bsz * self.num_heads, tgt_len, src_len)
123
+
124
+ attn_weights = nn.functional.softmax(attn_weights, dim=-1)
125
+
126
+ if output_attentions:
127
+ # this operation is a bit akward, but it's required to
128
+ # make sure that attn_weights keeps its gradient.
129
+ # In order to do so, attn_weights have to reshaped
130
+ # twice and have to be reused in the following
131
+ attn_weights_reshaped = attn_weights.view(
132
+ bsz, self.num_heads, tgt_len, src_len
133
+ )
134
+ attn_weights = attn_weights_reshaped.view(
135
+ bsz * self.num_heads, tgt_len, src_len
136
+ )
137
+ else:
138
+ attn_weights_reshaped = None
139
+
140
+ attn_probs = nn.functional.dropout(
141
+ attn_weights, p=self.dropout, training=self.training
142
+ )
143
+
144
+ attn_output = torch.bmm(attn_probs, value_states)
145
+
146
+ if attn_output.size() != (bsz * self.num_heads, tgt_len, self.head_dim):
147
+ raise ValueError(
148
+ f"`attn_output` should be of size {(bsz, self.num_heads, tgt_len, self.head_dim)}, but is"
149
+ f" {attn_output.size()}"
150
+ )
151
+
152
+ attn_output = attn_output.view(bsz, self.num_heads, tgt_len, self.head_dim)
153
+ attn_output = attn_output.transpose(1, 2)
154
+ attn_output = attn_output.reshape(bsz, tgt_len, embed_dim)
155
+
156
+ attn_output = self.out_proj(attn_output)
157
+
158
+ return attn_output, attn_weights_reshaped
159
+
160
+
161
+ class CLIPMLP(nn.Module):
162
+ def __init__(self, config):
163
+ super().__init__()
164
+ self.config = config
165
+ self.activation_fn = ACT2FN[config.hidden_act]
166
+ self.fc1 = nn.Linear(config.hidden_size, config.intermediate_size)
167
+ self.fc2 = nn.Linear(config.intermediate_size, config.hidden_size)
168
+
169
+ def forward(self, hidden_states: torch.Tensor) -> torch.Tensor:
170
+ hidden_states = self.fc1(hidden_states)
171
+ hidden_states = self.activation_fn(hidden_states)
172
+ hidden_states = self.fc2(hidden_states)
173
+ return hidden_states
174
+
175
+
176
+ class CLIPEncoderLayer(nn.Module):
177
+ def __init__(self, config: CLIPConfig):
178
+ super().__init__()
179
+ self.embed_dim = config.hidden_size
180
+ self.self_attn = CLIPAttention(config)
181
+ self.layer_norm1 = nn.LayerNorm(self.embed_dim)
182
+ self.mlp = CLIPMLP(config)
183
+ self.layer_norm2 = nn.LayerNorm(self.embed_dim)
184
+
185
+ def forward(
186
+ self,
187
+ hidden_states: torch.Tensor,
188
+ attention_mask: torch.Tensor,
189
+ causal_attention_mask: torch.Tensor,
190
+ output_attentions: Optional[bool] = False,
191
+ ) -> Tuple[torch.FloatTensor]:
192
+ """
193
+ Args:
194
+ hidden_states (`torch.FloatTensor`): input to the layer of shape `(batch, seq_len, embed_dim)`
195
+ attention_mask (`torch.FloatTensor`): attention mask of size
196
+ `(batch, 1, tgt_len, src_len)` where padding elements are indicated by very large negative values.
197
+ `(config.encoder_attention_heads,)`.
198
+ output_attentions (`bool`, *optional*):
199
+ Whether or not to return the attentions tensors of all attention layers. See `attentions` under
200
+ returned tensors for more detail.
201
+ """
202
+ residual = hidden_states
203
+
204
+ hidden_states = self.layer_norm1(hidden_states)
205
+ hidden_states, attn_weights = self.self_attn(
206
+ hidden_states=hidden_states,
207
+ attention_mask=attention_mask,
208
+ causal_attention_mask=causal_attention_mask,
209
+ output_attentions=output_attentions,
210
+ )
211
+ hidden_states = residual + hidden_states
212
+
213
+ residual = hidden_states
214
+ hidden_states = self.layer_norm2(hidden_states)
215
+ hidden_states = self.mlp(hidden_states)
216
+ hidden_states = residual + hidden_states
217
+
218
+ outputs = (hidden_states,)
219
+
220
+ if output_attentions:
221
+ outputs += (attn_weights,)
222
+
223
+ return outputs
224
+
225
+
226
+ def make_fused_vision_attn(model, dev):
227
+ """
228
+ Replace all LlamaAttention modules with QuantLlamaAttention modules, fusing the q, k, v projections.
229
+ """
230
+ model = model.cpu()
231
+ for name, m in model.named_modules():
232
+ if not m.__class__.__name__ in ["CLIPAttention", "CLIPAttentionFused"]:
233
+ continue
234
+
235
+ q_proj = m.q_proj
236
+ k_proj = m.k_proj
237
+ v_proj = m.v_proj
238
+
239
+ weights = torch.cat([q_proj.weight, k_proj.weight, v_proj.weight], dim=0)
240
+ bias = (
241
+ torch.cat([q_proj.bias, k_proj.bias, v_proj.bias], dim=0)
242
+ if q_proj.bias is not None
243
+ else None
244
+ )
245
+
246
+ qkv_layer = nn.Linear(
247
+ q_proj.in_features,
248
+ q_proj.out_features + k_proj.out_features + v_proj.out_features,
249
+ q_proj.bias is not None,
250
+ q_proj.weight.device,
251
+ )
252
+ qkv_layer.weight.data = weights
253
+
254
+ qkv_layer.bias.data = bias
255
+ if isinstance(m, CLIPAttention):
256
+ attn = CLIPAttentionFused(
257
+ m.embed_dim, m.num_heads, qkv_layer, m.out_proj, dev
258
+ )
259
+ if "." in name:
260
+ parent_name = name.rsplit(".", 1)[0]
261
+ child_name = name[len(parent_name) + 1 :]
262
+ parent = model.get_submodule(parent_name)
263
+ else:
264
+ parent_name = ""
265
+ parent = model
266
+ child_name = name
267
+
268
+ # print(f"Replacing {name} with quant_attn; parent: {parent_name}, child's name: {child_name}")
269
+ setattr(parent, child_name, attn)
270
+ gc.collect()
271
+ torch.cuda.empty_cache()
272
+ model = model.to(dev)