bitsandbytes-cpu-fork 0.50.2.dev2__py3-none-win_amd64.whl → 0.50.2.dev4__py3-none-win_amd64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. bitsandbytes/__init__.py +1 -1
  2. bitsandbytes/__main__.py +4 -4
  3. bitsandbytes/_cpu_caps.py +110 -0
  4. bitsandbytes/_ops.py +526 -526
  5. bitsandbytes/autograd/_functions.py +491 -491
  6. bitsandbytes/backends/cpu/ops.py +805 -805
  7. bitsandbytes/backends/cuda/ops.py +1212 -1212
  8. bitsandbytes/backends/default/ops.py +632 -632
  9. bitsandbytes/backends/hpu/ops.py +53 -53
  10. bitsandbytes/backends/mps/ops.py +277 -277
  11. bitsandbytes/backends/triton/kernels_4bit.py +583 -577
  12. bitsandbytes/backends/triton/kernels_8bit_quant.py +195 -195
  13. bitsandbytes/backends/triton/kernels_optim.py +1177 -1177
  14. bitsandbytes/backends/triton/ops.py +304 -304
  15. bitsandbytes/backends/utils.py +94 -94
  16. bitsandbytes/backends/xpu/ops.py +305 -305
  17. bitsandbytes/cextension.py +447 -405
  18. bitsandbytes/cli.py +50 -50
  19. bitsandbytes/consts.py +12 -12
  20. bitsandbytes/cuda_specs.py +111 -111
  21. bitsandbytes/detect_cpu.py +189 -189
  22. bitsandbytes/diagnostics/cuda.py +193 -193
  23. bitsandbytes/diagnostics/main.py +134 -134
  24. bitsandbytes/diagnostics/utils.py +12 -12
  25. bitsandbytes/disk_balancer.py +1276 -1224
  26. bitsandbytes/efst.py +777 -0
  27. bitsandbytes/functional.py +1836 -1836
  28. bitsandbytes/gdn_cpu.py +616 -602
  29. bitsandbytes/libbitsandbytes_cpu.dll +0 -0
  30. bitsandbytes/nn/__init__.py +19 -19
  31. bitsandbytes/nn/modules.py +1220 -1220
  32. bitsandbytes/nn/parametrize.py +206 -206
  33. bitsandbytes/optim/__init__.py +0 -4
  34. bitsandbytes/optim/adagrad.py +187 -187
  35. bitsandbytes/optim/adam.py +346 -346
  36. bitsandbytes/optim/adamw.py +337 -337
  37. bitsandbytes/optim/ademamix.py +410 -410
  38. bitsandbytes/optim/lamb.py +190 -190
  39. bitsandbytes/optim/lars.py +259 -259
  40. bitsandbytes/optim/lion.py +266 -266
  41. bitsandbytes/optim/optimizer.py +756 -756
  42. bitsandbytes/optim/rmsprop.py +170 -170
  43. bitsandbytes/optim/sgd.py +152 -152
  44. bitsandbytes/torch_cpu_kit.py +468 -468
  45. bitsandbytes/utils.py +208 -208
  46. bitsandbytes_cpu_cli.py +1012 -949
  47. {bitsandbytes_cpu_fork-0.50.2.dev2.dist-info → bitsandbytes_cpu_fork-0.50.2.dev4.dist-info}/METADATA +12 -4
  48. bitsandbytes_cpu_fork-0.50.2.dev4.dist-info/RECORD +64 -0
  49. {bitsandbytes_cpu_fork-0.50.2.dev2.dist-info → bitsandbytes_cpu_fork-0.50.2.dev4.dist-info}/licenses/LICENSE +21 -21
  50. bitsandbytes/optim/adamw4bit.py +0 -183
  51. bitsandbytes_cpu_fork-0.50.2.dev2.dist-info/RECORD +0 -63
  52. {bitsandbytes_cpu_fork-0.50.2.dev2.dist-info → bitsandbytes_cpu_fork-0.50.2.dev4.dist-info}/WHEEL +0 -0
  53. {bitsandbytes_cpu_fork-0.50.2.dev2.dist-info → bitsandbytes_cpu_fork-0.50.2.dev4.dist-info}/entry_points.txt +0 -0
  54. {bitsandbytes_cpu_fork-0.50.2.dev2.dist-info → bitsandbytes_cpu_fork-0.50.2.dev4.dist-info}/top_level.txt +0 -0
@@ -1,577 +1,583 @@
1
- import torch
2
-
3
- import triton
4
- import triton.language as tl
5
-
6
-
7
- # Triton implementation of similar CUDA kernel to avoid loading code from csrc/kernels.cu::dQuantizeFP4
8
- # @triton.autotune(
9
- # configs=[
10
- # triton.Config({"SPLIT_NUM_BLOCKS": 1, "grf_mode": "auto"}, num_stages=4, num_warps=32),
11
- # triton.Config({"SPLIT_NUM_BLOCKS": 2, "grf_mode": "auto"}, num_stages=4, num_warps=32),
12
- # triton.Config({"SPLIT_NUM_BLOCKS": 1}),
13
- # triton.Config({"SPLIT_NUM_BLOCKS": 2}),
14
- # triton.Config({"SPLIT_NUM_BLOCKS": 4}),
15
- # triton.Config({"SPLIT_NUM_BLOCKS": 8}),
16
- # ],
17
- # key=["n_elements"],
18
- # )
19
- @triton.jit
20
- def quantize_fp4_blockwise_kernel(
21
- A_ptr,
22
- absmax_ptr,
23
- out_ptr,
24
- n_elements,
25
- BLOCK_SIZE: tl.constexpr,
26
- SPLIT_NUM_BLOCKS: tl.constexpr,
27
- ):
28
- PAIRED_SPLIT_NUM_BLOCKS: tl.constexpr = SPLIT_NUM_BLOCKS * 2
29
- block_start_idx = tl.program_id(0) * PAIRED_SPLIT_NUM_BLOCKS
30
- thread_idx = tl.arange(0, PAIRED_SPLIT_NUM_BLOCKS * BLOCK_SIZE)
31
-
32
- offsets = block_start_idx * BLOCK_SIZE + thread_idx
33
- mask = offsets < n_elements
34
-
35
- A = tl.load(A_ptr + offsets, mask=mask, other=0.0)
36
-
37
- # To be able process several blocks -> (PAIRED_SPLIT_NUM_BLOCKS, BLOCK_SIZE)
38
- A_reshaped = tl.reshape(A, (PAIRED_SPLIT_NUM_BLOCKS, BLOCK_SIZE))
39
-
40
- # Calculating absamax for each block
41
- absmax = tl.max(tl.abs(A_reshaped), axis=1)
42
- tl.store(absmax_ptr + block_start_idx + tl.arange(0, PAIRED_SPLIT_NUM_BLOCKS), absmax)
43
-
44
- A_normalized = A_reshaped / absmax[:, None]
45
- A_normalized = tl.clamp(A_normalized, -1.0, 1.0)
46
-
47
- sign = tl.where(A_normalized < 0, 0b1000, 0b0000)
48
- A_absf = tl.abs(A_normalized)
49
-
50
- result = tl.where(
51
- A_absf > 0.29166667,
52
- tl.where(
53
- A_absf > 0.583333, tl.where(A_absf > 0.8333333, 0b011, 0b010), tl.where(A_absf > 0.4166667, 0b101, 0b100)
54
- ),
55
- tl.where(
56
- A_absf > 0.0859375,
57
- tl.where(A_absf > 0.20833333, 0b0111, 0b0110),
58
- tl.where(A_absf > 0.00260417, 0b0001, 0b0000),
59
- ),
60
- )
61
- quantized = (result ^ sign).to(tl.uint8)
62
-
63
- quantized = quantized.reshape((PAIRED_SPLIT_NUM_BLOCKS, BLOCK_SIZE // 2, 2))
64
- left, right = quantized.split()
65
- packed = left << 4 | (right & 0xF)
66
-
67
- packed_flat = tl.reshape(packed, (BLOCK_SIZE * SPLIT_NUM_BLOCKS,))
68
- out_offsets = block_start_idx * BLOCK_SIZE // 2 + tl.arange(0, SPLIT_NUM_BLOCKS * BLOCK_SIZE)
69
- # Use n - n//2 instead of (n+1)//2 to avoid integer overflow for large n
70
- out_mask = out_offsets < (n_elements - n_elements // 2)
71
- tl.store(out_ptr + out_offsets, packed_flat, mask=out_mask)
72
-
73
-
74
- # Triton implementation of similar CUDA kernel to avoid loading code from csrc/kernels.cu::dQuantizeNF4
75
- # @triton.autotune(
76
- # configs=[
77
- # triton.Config({"SPLIT_NUM_BLOCKS": 1, "grf_mode": "auto"}, num_stages=4, num_warps=32),
78
- # triton.Config({"SPLIT_NUM_BLOCKS": 2, "grf_mode": "auto"}, num_stages=4, num_warps=32),
79
- # triton.Config({"SPLIT_NUM_BLOCKS": 1}),
80
- # triton.Config({"SPLIT_NUM_BLOCKS": 2}),
81
- # triton.Config({"SPLIT_NUM_BLOCKS": 4}),
82
- # triton.Config({"SPLIT_NUM_BLOCKS": 8}),
83
- # ],
84
- # key=["n_elements"],
85
- # )
86
- @triton.jit
87
- def quantize_nf4_blockwise_kernel(
88
- A_ptr,
89
- absmax_ptr,
90
- out_ptr,
91
- n_elements,
92
- BLOCK_SIZE: tl.constexpr,
93
- SPLIT_NUM_BLOCKS: tl.constexpr,
94
- ):
95
- PAIRED_SPLIT_NUM_BLOCKS: tl.constexpr = SPLIT_NUM_BLOCKS * 2
96
- block_start_idx = tl.program_id(0) * PAIRED_SPLIT_NUM_BLOCKS
97
- thread_idx = tl.arange(0, PAIRED_SPLIT_NUM_BLOCKS * BLOCK_SIZE)
98
-
99
- offsets = block_start_idx * BLOCK_SIZE + thread_idx
100
- mask = offsets < n_elements
101
-
102
- A = tl.load(A_ptr + offsets, mask=mask, other=0.0)
103
-
104
- # To be able process several blocks -> (PAIRED_SPLIT_NUM_BLOCKS, BLOCK_SIZE)
105
- A_reshaped = tl.reshape(A, (PAIRED_SPLIT_NUM_BLOCKS, BLOCK_SIZE))
106
-
107
- # Calculating absamax for each block
108
- absmax = tl.max(tl.abs(A_reshaped), axis=1)
109
- tl.store(absmax_ptr + block_start_idx + tl.arange(0, PAIRED_SPLIT_NUM_BLOCKS), absmax)
110
-
111
- A_normalized = A_reshaped / absmax[:, None]
112
- A_normalized = tl.clamp(A_normalized, -1.0, 1.0)
113
-
114
- result = tl.where(
115
- A_normalized > 0.03979014977812767,
116
- tl.where(
117
- A_normalized > 0.3893125355243683,
118
- tl.where(
119
- A_normalized > 0.6427869200706482,
120
- tl.where(A_normalized > 0.8614784181118011, 0b1111, 0b1110),
121
- tl.where(A_normalized > 0.5016634166240692, 0b1101, 0b1100),
122
- ),
123
- tl.where(
124
- A_normalized > 0.2035212516784668,
125
- tl.where(A_normalized > 0.2920137718319893, 0b1011, 0b1010),
126
- tl.where(A_normalized > 0.1202552504837513, 0b1001, 0b1000),
127
- ),
128
- ),
129
- tl.where(
130
- A_normalized > -0.33967943489551544,
131
- tl.where(
132
- A_normalized > -0.13791173323988914,
133
- tl.where(A_normalized > -0.045525018125772476, 0b0111, 0b0110),
134
- tl.where(A_normalized > -0.23460740596055984, 0b0101, 0b0100),
135
- ),
136
- tl.where(
137
- A_normalized > -0.6106329262256622,
138
- tl.where(A_normalized > -0.4599952697753906, 0b0011, 0b0010),
139
- tl.where(A_normalized > -0.8480964004993439, 0b0001, 0b0000),
140
- ),
141
- ),
142
- )
143
- quantized = result.to(tl.uint8)
144
-
145
- quantized = quantized.reshape((PAIRED_SPLIT_NUM_BLOCKS, BLOCK_SIZE // 2, 2))
146
-
147
- left, right = quantized.split()
148
- packed = left << 4 | (right & 0xF)
149
-
150
- packed_flat = tl.reshape(packed, (BLOCK_SIZE * SPLIT_NUM_BLOCKS,))
151
- out_offsets = block_start_idx * BLOCK_SIZE // 2 + tl.arange(0, SPLIT_NUM_BLOCKS * BLOCK_SIZE)
152
- # Use n - n//2 instead of (n+1)//2 to avoid integer overflow for large n
153
- out_mask = out_offsets < (n_elements - n_elements // 2)
154
- tl.store(out_ptr + out_offsets, packed_flat, mask=out_mask)
155
-
156
-
157
- def quantize_4bit_blockwise_triton(A, blocksize, quant_type, blocks, absmax, num_elements, quantized_out):
158
- # grid = lambda META: (triton.cdiv(blocks, META["SPLIT_NUM_BLOCKS"]),)
159
- split_num_blocks = 4
160
- grid = (triton.cdiv(blocks, split_num_blocks),)
161
- if quant_type == "fp4":
162
- quantize_fp4_blockwise_kernel[grid](
163
- A_ptr=A,
164
- absmax_ptr=absmax,
165
- out_ptr=quantized_out,
166
- n_elements=num_elements,
167
- BLOCK_SIZE=blocksize,
168
- SPLIT_NUM_BLOCKS=split_num_blocks,
169
- )
170
- else:
171
- quantize_nf4_blockwise_kernel[grid](
172
- A_ptr=A,
173
- absmax_ptr=absmax,
174
- out_ptr=quantized_out,
175
- n_elements=num_elements,
176
- BLOCK_SIZE=blocksize,
177
- SPLIT_NUM_BLOCKS=split_num_blocks,
178
- )
179
- return quantized_out, absmax
180
-
181
-
182
- @triton.jit
183
- def dequant_4bit_body_util(a, offsets, quant_ptr, absmax_ptr, n_elems, QUANT_BLOCK: tl.constexpr):
184
- PAIRED_QUANT_BLOCK: tl.constexpr = QUANT_BLOCK // 2
185
- mask = offsets < n_elems
186
- higher = a & 0xF
187
- # lower 4bits
188
- lower = a >> 4
189
-
190
- abs_offsets = offsets // PAIRED_QUANT_BLOCK
191
- absmax = tl.load(absmax_ptr + abs_offsets, mask=mask, other=1.0, eviction_policy="evict_last")
192
-
193
- # apply conversion
194
- lower_4 = tl.load(quant_ptr + lower, eviction_policy="evict_last")
195
- higher_4 = tl.load(quant_ptr + higher, eviction_policy="evict_last")
196
-
197
- mul_high = higher_4 * absmax
198
- mul_low = lower_4 * absmax
199
- out_dq = tl.interleave(mul_low, mul_high)
200
- return out_dq
201
-
202
-
203
- # Triton implementation of similar CUDA kernel to avoid loading code from csrc/kernels.cu::dDequantizeFP4Tree
204
- @triton.jit
205
- def dequantize_fp4_tree(val, absmax):
206
- # val: tl.tensor (uint8)
207
- # absmax: tl.tensor (float32/float16)
208
- # 00001100 00001011 00001001 00001111
209
- sign = tl.where((val & 0b1000) == 0b1000, -1.0, 1.0) # -1
210
- third_bit = (val & 0b0100) == 0b0100 # True
211
- second_bit = (val & 0b0010) == 0b0010 # False
212
- first_bit = (val & 0b0001) == 0b0001 # False
213
-
214
- branch1 = tl.where(
215
- second_bit,
216
- tl.where(first_bit, 0.25, 0.16666667), # 1111, 1110
217
- tl.where(first_bit, 0.5, 0.33333333), # 1101, 1100
218
- )
219
- branch2 = tl.where(
220
- second_bit,
221
- tl.where(first_bit, 1.0, 0.66666667), # 1011, 1010
222
- tl.where(first_bit, 0.005208333333, 0.0), # 1001, 1000
223
- )
224
- out = tl.where(third_bit, branch1, branch2)
225
- return out * sign * absmax
226
-
227
-
228
- @triton.jit
229
- def dequant_fp4_body_util(a, offsets, absmax_ptr, n_elems, QUANT_BLOCK: tl.constexpr):
230
- PAIRED_QUANT_BLOCK: tl.constexpr = QUANT_BLOCK // 2
231
- mask = offsets < n_elems
232
- higher = a & 0xF
233
- lower = a >> 4
234
-
235
- abs_offsets = offsets // PAIRED_QUANT_BLOCK
236
- absmax = tl.load(absmax_ptr + abs_offsets, mask=mask, other=1.0, eviction_policy="evict_last")
237
- mul_high = dequantize_fp4_tree(higher, absmax)
238
- mul_low = dequantize_fp4_tree(lower, absmax)
239
- out_dq = tl.interleave(mul_low, mul_high)
240
- return out_dq
241
-
242
-
243
- # Triton implementation of similar CUDA kernel to avoid loading code from csrc/kernels.cu::dDequantizeNF4
244
- @triton.jit
245
- def dequantize_nf4_tree(val):
246
- # val: tl.tensor (uint8)
247
- cond0 = (val & 0b1000) == 0b1000
248
- cond1 = (val & 0b0100) == 0b0100
249
- cond2 = (val & 0b0010) == 0b0010
250
- cond3 = (val & 0b0001) == 0b0001
251
-
252
- # Positive branch (val & 0b1000) == 8
253
- branch_pos = tl.where(
254
- cond1,
255
- tl.where(
256
- cond2,
257
- tl.where(cond3, 1.0, 0.7229568362236023), # 1111, 1110
258
- tl.where(cond3, 0.5626170039176941, 0.44070982933044434), # 1101, 1100
259
- ),
260
- tl.where(
261
- cond2,
262
- tl.where(cond3, 0.33791524171829224, 0.24611230194568634), # 1011, 1010
263
- tl.where(cond3, 0.16093020141124725, 0.07958029955625534), # 1001, 1000
264
- ),
265
- )
266
-
267
- # Negative branch (val & 0b1000) == 0
268
- branch_neg = tl.where(
269
- cond1,
270
- tl.where(
271
- cond2,
272
- tl.where(cond3, 0.0, -0.09105003625154495), # 0111, 0110
273
- tl.where(cond3, -0.18477343022823334, -0.28444138169288635), # 0101, 0100
274
- ),
275
- tl.where(
276
- cond2,
277
- tl.where(cond3, -0.39491748809814453, -0.5250730514526367), # 0011, 0010
278
- tl.where(cond3, -0.6961928009986877, -1.0), # 0001, 0000
279
- ),
280
- )
281
- return tl.where(cond0, branch_pos, branch_neg)
282
-
283
-
284
- @triton.jit
285
- def dequant_nf4_body_util(a, offsets, absmax_ptr, n_elems, QUANT_BLOCK: tl.constexpr):
286
- PAIRED_QUANT_BLOCK: tl.constexpr = QUANT_BLOCK // 2
287
- mask = offsets < n_elems
288
- higher = a & 0xF
289
- # lower 4bits
290
- lower = a >> 4
291
-
292
- abs_offsets = offsets // PAIRED_QUANT_BLOCK
293
- absmax = tl.load(absmax_ptr + abs_offsets, mask=mask, other=1.0, eviction_policy="evict_last")
294
- mul_high = dequantize_nf4_tree(higher) * absmax
295
- mul_low = dequantize_nf4_tree(lower) * absmax
296
- out_dq = tl.interleave(mul_low, mul_high)
297
- return out_dq
298
-
299
-
300
- # All such kernels are similar, so maybe code can be generalised.
301
- # @triton.autotune(
302
- # configs=[
303
- # # # triton.Config({'SPLIT_SIZE': 64}),
304
- # # # # triton.Config({'SPLIT_SIZE': 64, 'grf_mode': 'large'}, num_stages=2, num_warps=32),
305
- # # # # triton.Config({'SPLIT_SIZE': 64, 'grf_mode': 'auto'}, num_stages=2, num_warps=32),
306
- # # # # triton.Config({'SPLIT_SIZE': 64, 'grf_mode': 'large'}, num_stages=4, num_warps=32),
307
- # # # # triton.Config({'SPLIT_SIZE': 64, 'grf_mode': 'auto'}, num_stages=4, num_warps=32),
308
- # triton.Config({'SPLIT_SIZE': 128}),
309
- # triton.Config({'SPLIT_SIZE': 128}, num_warps = 32, num_stages = 2),
310
- # # # triton.Config({'SPLIT_SIZE': 128}, num_warps = 4, num_stages = 4),
311
- # # # # triton.Config({'SPLIT_SIZE': 128, 'grf_mode': 'large'}, num_stages=2, num_warps=32),
312
- # # # # triton.Config({'SPLIT_SIZE': 128, 'grf_mode': 'auto'}, num_stages=2, num_warps=32),
313
- # # # # triton.Config({'SPLIT_SIZE': 128, 'grf_mode': 'large'}, num_stages=4, num_warps=32),
314
- # # # # triton.Config({'SPLIT_SIZE': 128, 'grf_mode': 'auto'}, num_stages=4, num_warps=32),
315
- # triton.Config({'SPLIT_SIZE': 256}),
316
- # triton.Config({'SPLIT_SIZE': 256}, num_warps = 32, num_stages = 2),
317
- # # triton.Config({'SPLIT_SIZE': 256}, num_warps = 4, num_stages = 4),
318
- # triton.Config({'SPLIT_SIZE': 512}),
319
- # triton.Config({'SPLIT_SIZE': 512}, num_warps = 32, num_stages = 2),
320
- # # triton.Config({'SPLIT_SIZE': 512}, num_warps = 4, num_stages = 4),
321
- # # # # triton.Config({'SPLIT_SIZE': 512, 'grf_mode': 'large'}, num_stages=2, num_warps=32),
322
- # # # # triton.Config({'SPLIT_SIZE': 512, 'grf_mode': 'auto'}, num_stages=2, num_warps=32),
323
- # # # # triton.Config({'SPLIT_SIZE': 512, 'grf_mode': 'large'}, num_stages=4, num_warps=32),
324
- # # # # triton.Config({'SPLIT_SIZE': 512, 'grf_mode': 'auto'}, num_stages=4, num_warps=32),
325
- # # # triton.Config({'SPLIT_SIZE': 1024}),
326
- # # # # triton.Config({'SPLIT_SIZE': 2048}),
327
- # # # # triton.Config({'SPLIT_SIZE': 4096}),
328
- # # # # triton.Config({'SPLIT_SIZE': 8192}),
329
- # # # # triton.Config({'SPLIT_SIZE': 16384}),
330
- # ],
331
- # key=['num_paired_elements'],
332
- # )
333
- @triton.jit
334
- def dequant_4bit_kernel(
335
- a_ptr,
336
- c_ptr,
337
- quant_ptr,
338
- absmax_ptr,
339
- num_paired_elements,
340
- num_output_elements,
341
- QUANT_BLOCK: tl.constexpr,
342
- SPLIT_SIZE: tl.constexpr,
343
- ):
344
- pid = tl.program_id(axis=0) # We use a 1D launch grid so axis is 0.
345
- block_start = pid * SPLIT_SIZE
346
- offsets = block_start + tl.arange(0, SPLIT_SIZE)
347
- mask = offsets < num_paired_elements
348
-
349
- a = tl.load(a_ptr + offsets, mask, eviction_policy="evict_first")
350
-
351
- out_dq = dequant_4bit_body_util(
352
- a=a,
353
- offsets=offsets,
354
- quant_ptr=quant_ptr,
355
- absmax_ptr=absmax_ptr,
356
- n_elems=num_paired_elements,
357
- QUANT_BLOCK=QUANT_BLOCK,
358
- )
359
-
360
- out_block_start = pid * SPLIT_SIZE * 2
361
- offs = out_block_start + tl.arange(0, SPLIT_SIZE * 2)
362
- mask = offs < num_output_elements
363
- tl.store(c_ptr + offs, out_dq, mask)
364
-
365
-
366
- # @triton.autotune(
367
- # configs=[
368
- # triton.Config({'SPLIT_SIZE': 128}, num_warps = 32, num_stages = 2),
369
- # triton.Config({'SPLIT_SIZE': 256}),
370
- # triton.Config({'SPLIT_SIZE': 256}, num_warps = 32, num_stages = 2),
371
- # triton.Config({'SPLIT_SIZE': 512}),
372
- # triton.Config({'SPLIT_SIZE': 512}, num_warps = 32, num_stages = 2),
373
- # triton.Config({'SPLIT_SIZE': 1024}, num_warps = 32, num_stages = 2),
374
- # ],
375
- # key=['num_paired_elements'],
376
- # )
377
- @triton.jit
378
- def dequant_fp4_kernel(
379
- a_ptr,
380
- c_ptr,
381
- absmax_ptr,
382
- num_paired_elements,
383
- num_output_elements,
384
- QUANT_BLOCK: tl.constexpr,
385
- SPLIT_SIZE: tl.constexpr,
386
- ):
387
- pid = tl.program_id(axis=0) # We use a 1D launch grid so axis is 0.
388
- block_start = pid * SPLIT_SIZE
389
- offsets = block_start + tl.arange(0, SPLIT_SIZE)
390
- mask = offsets < num_paired_elements
391
-
392
- a = tl.load(a_ptr + offsets, mask, eviction_policy="evict_first")
393
-
394
- out_dq = dequant_fp4_body_util(
395
- a=a,
396
- offsets=offsets,
397
- absmax_ptr=absmax_ptr,
398
- n_elems=num_paired_elements,
399
- QUANT_BLOCK=QUANT_BLOCK,
400
- )
401
-
402
- out_block_start = pid * SPLIT_SIZE * 2
403
- offs = out_block_start + tl.arange(0, SPLIT_SIZE * 2)
404
- mask = offs < num_output_elements
405
- tl.store(c_ptr + offs, out_dq, mask)
406
-
407
-
408
- # @triton.autotune(
409
- # configs=[
410
- # triton.Config({'SPLIT_SIZE': 128}, num_warps = 32, num_stages = 2),
411
- # triton.Config({'SPLIT_SIZE': 256}),
412
- # triton.Config({'SPLIT_SIZE': 256}, num_warps = 32, num_stages = 2),
413
- # triton.Config({'SPLIT_SIZE': 512}),
414
- # triton.Config({'SPLIT_SIZE': 512}, num_warps = 32, num_stages = 2),
415
- # triton.Config({'SPLIT_SIZE': 1024}, num_warps = 32, num_stages = 2),
416
- # ],
417
- # key=['num_paired_elements'],
418
- # )
419
- @triton.jit
420
- def dequant_nf4_kernel(
421
- a_ptr,
422
- c_ptr,
423
- absmax_ptr,
424
- num_paired_elements,
425
- num_output_elements,
426
- QUANT_BLOCK: tl.constexpr,
427
- SPLIT_SIZE: tl.constexpr,
428
- ):
429
- pid = tl.program_id(axis=0) # We use a 1D launch grid so axis is 0.
430
- block_start = pid * SPLIT_SIZE
431
- offsets = block_start + tl.arange(0, SPLIT_SIZE)
432
- mask = offsets < num_paired_elements
433
-
434
- a = tl.load(a_ptr + offsets, mask, eviction_policy="evict_first")
435
-
436
- out_dq = dequant_nf4_body_util(
437
- a=a,
438
- offsets=offsets,
439
- absmax_ptr=absmax_ptr,
440
- n_elems=num_paired_elements,
441
- QUANT_BLOCK=QUANT_BLOCK,
442
- )
443
-
444
- out_block_start = pid * SPLIT_SIZE * 2
445
- offs = out_block_start + tl.arange(0, SPLIT_SIZE * 2)
446
- mask = offs < num_output_elements
447
- tl.store(c_ptr + offs, out_dq, mask)
448
-
449
-
450
- def dequantize_4bit_impl(
451
- A: torch.Tensor,
452
- absmax: torch.Tensor,
453
- blocksize: int,
454
- quant_type: str,
455
- dtype: torch.dtype,
456
- out: torch.Tensor,
457
- ) -> None:
458
- # It's will be processed as an array, so
459
- # actual length is row * col
460
- # Elements are in uint8 format, so interleaved
461
- # so total amount of data is 2 * elem_count
462
- number_of_paired_elements = A.numel()
463
- num_output_elements = out.numel()
464
- # we assume that split_size > quant_blocksize
465
-
466
- SPLIT_SIZE = 256
467
- # grid = lambda META: (triton.cdiv(number_of_paired_elements, META['SPLIT_SIZE']), )
468
- grid = (triton.cdiv(number_of_paired_elements, SPLIT_SIZE),)
469
- if quant_type == "fp4":
470
- dequant_fp4_kernel[grid](A, out, absmax, number_of_paired_elements, num_output_elements, blocksize, SPLIT_SIZE)
471
- else:
472
- dequant_nf4_kernel[grid](A, out, absmax, number_of_paired_elements, num_output_elements, blocksize, SPLIT_SIZE)
473
-
474
-
475
- def dequantize_4bit_impl_passing_code(
476
- A: torch.Tensor,
477
- absmax: torch.Tensor,
478
- blocksize: int,
479
- code: torch.Tensor,
480
- dtype: torch.dtype,
481
- out: torch.Tensor,
482
- ) -> None:
483
- number_of_paired_elements = A.numel()
484
- num_output_elements = out.numel()
485
- # we assume that split_size > quant_blocksize
486
-
487
- SPLIT_SIZE = 256
488
- # grid = lambda META: (triton.cdiv(number_of_paired_elements, META['SPLIT_SIZE']), )
489
- grid = (triton.cdiv(number_of_paired_elements, SPLIT_SIZE),)
490
- dequant_4bit_kernel[grid](
491
- A, out, code, absmax, number_of_paired_elements, num_output_elements, blocksize, SPLIT_SIZE
492
- )
493
-
494
-
495
- ######################### Fallback dequantization functions #########################
496
- ## for debug ##
497
-
498
-
499
- # @triton.autotune(
500
- # configs=[
501
- # # triton.Config({'SPLIT_NUM_BLOCKS': 1, 'grf_mode': 'large'}, num_stages=2, num_warps=32),
502
- # # triton.Config({'SPLIT_NUM_BLOCKS': 1, 'grf_mode': 'auto'}, num_stages=2, num_warps=32),
503
- # # triton.Config({'SPLIT_NUM_BLOCKS': 1, 'grf_mode': 'large'}, num_stages=4, num_warps=32),
504
- # # #
505
- # # triton.Config({"SPLIT_NUM_BLOCKS": 1, "grf_mode": "auto"}, num_stages=4, num_warps=32),
506
- # #
507
- # triton.Config({"SPLIT_NUM_BLOCKS": 2}),
508
- # # triton.Config({"SPLIT_NUM_BLOCKS": 2, "grf_mode": "large"}, num_stages=2, num_warps=32),
509
- # # # triton.Config({'SPLIT_NUM_BLOCKS': 2, 'grf_mode': 'large'}, num_stages=4, num_warps=32),
510
- # # triton.Config({"SPLIT_NUM_BLOCKS": 2, "grf_mode": "auto"}, num_stages=2, num_warps=32),
511
- # # triton.Config({"SPLIT_NUM_BLOCKS": 2, "grf_mode": "auto"}, num_stages=4, num_warps=32),
512
- # # triton.Config({"SPLIT_NUM_BLOCKS": 4, "grf_mode": "large"}, num_stages=2, num_warps=32),
513
- # # triton.Config({"SPLIT_NUM_BLOCKS": 4, "grf_mode": "large"}, num_stages=4, num_warps=32),
514
- # # triton.Config({'SPLIT_NUM_BLOCKS': 8, 'grf_mode': 'large'}, num_stages=2, num_warps=32),
515
- # ],
516
- # key=["n_elements", "BLOCK_SIZE"],
517
- # )
518
- @triton.jit
519
- def quantize_4bit_blockwise_kernel(
520
- A_ptr,
521
- code_ptr,
522
- absmax_ptr,
523
- out_ptr,
524
- n_elements,
525
- BLOCK_SIZE: tl.constexpr,
526
- CODE_SIZE: tl.constexpr,
527
- SPLIT_NUM_BLOCKS: tl.constexpr,
528
- ):
529
- PAIRED_SPLIT_NUM_BLOCKS: tl.constexpr = SPLIT_NUM_BLOCKS * 2
530
- block_start_idx = tl.program_id(0) * PAIRED_SPLIT_NUM_BLOCKS
531
- thread_idx = tl.arange(0, PAIRED_SPLIT_NUM_BLOCKS * BLOCK_SIZE)
532
-
533
- offsets = block_start_idx * BLOCK_SIZE + thread_idx
534
- mask = offsets < n_elements
535
-
536
- A = tl.load(A_ptr + offsets, mask=mask, other=0.0)
537
-
538
- # To be able process several blocks -> (PAIRED_SPLIT_NUM_BLOCKS, BLOCK_SIZE)
539
- A_reshaped = tl.reshape(A, (PAIRED_SPLIT_NUM_BLOCKS, BLOCK_SIZE))
540
-
541
- # Calculating absamax for each block
542
- absmax = tl.max(tl.abs(A_reshaped), axis=1)
543
- tl.store(absmax_ptr + block_start_idx + tl.arange(0, PAIRED_SPLIT_NUM_BLOCKS), absmax)
544
-
545
- A_normalized = A_reshaped / absmax[:, None]
546
- A_normalized = tl.clamp(A_normalized, -1.0, 1.0)
547
-
548
- lower_pivot = tl.zeros((PAIRED_SPLIT_NUM_BLOCKS, BLOCK_SIZE), dtype=tl.int32)
549
- upper_pivot = tl.full((PAIRED_SPLIT_NUM_BLOCKS, BLOCK_SIZE), CODE_SIZE - 1, dtype=tl.int32)
550
-
551
- for _ in range(4): # ceil(log2(code_size)) = 4, actually, in general case should be input parameter
552
- pivot = (lower_pivot + upper_pivot) // 2
553
- val = tl.load(code_ptr + pivot)
554
- is_higher = A_normalized > val # code[pivot]
555
- lower_pivot = tl.where(is_higher, pivot, lower_pivot)
556
- upper_pivot = tl.where(is_higher, upper_pivot, pivot)
557
-
558
- # Choose closest level
559
- lower_val = tl.load(code_ptr + lower_pivot)
560
- upper_val = tl.load(code_ptr + upper_pivot)
561
- lower_dist = tl.abs(A_normalized - lower_val)
562
- upper_dist = tl.abs(A_normalized - upper_val)
563
- quantized = tl.where(lower_dist <= upper_dist, lower_pivot, upper_pivot).to(tl.uint8)
564
-
565
- quantized = quantized.reshape((PAIRED_SPLIT_NUM_BLOCKS, BLOCK_SIZE // 2, 2))
566
- quantized = quantized.to(tl.uint8, bitcast=True)
567
- left, right = quantized.split()
568
- packed = left << 4 | (right & 0xF)
569
-
570
- # Reduce don't guarantee the order of the elements passed to unite_2_int4
571
- # packed = tl.reduce(quantized, axis=2, combine_fn=unite_2_int4)
572
- # packed = packed.to(tl.uint8, bitcast=True)
573
-
574
- packed_flat = tl.reshape(packed, (BLOCK_SIZE * SPLIT_NUM_BLOCKS,))
575
- out_offsets = block_start_idx * BLOCK_SIZE // 2 + tl.arange(0, SPLIT_NUM_BLOCKS * BLOCK_SIZE)
576
- out_mask = out_offsets < n_elements // 2
577
- tl.store(out_ptr + out_offsets, packed_flat, mask=out_mask)
1
+ import torch
2
+
3
+ import triton
4
+ import triton.language as tl
5
+
6
+
7
+ # Triton implementation of similar CUDA kernel to avoid loading code from csrc/kernels.cu::dQuantizeFP4
8
+ # @triton.autotune(
9
+ # configs=[
10
+ # triton.Config({"SPLIT_NUM_BLOCKS": 1, "grf_mode": "auto"}, num_stages=4, num_warps=32),
11
+ # triton.Config({"SPLIT_NUM_BLOCKS": 2, "grf_mode": "auto"}, num_stages=4, num_warps=32),
12
+ # triton.Config({"SPLIT_NUM_BLOCKS": 1}),
13
+ # triton.Config({"SPLIT_NUM_BLOCKS": 2}),
14
+ # triton.Config({"SPLIT_NUM_BLOCKS": 4}),
15
+ # triton.Config({"SPLIT_NUM_BLOCKS": 8}),
16
+ # ],
17
+ # key=["n_elements"],
18
+ # )
19
+ @triton.jit
20
+ def quantize_fp4_blockwise_kernel(
21
+ A_ptr,
22
+ absmax_ptr,
23
+ out_ptr,
24
+ n_elements,
25
+ absmax_elements,
26
+ BLOCK_SIZE: tl.constexpr,
27
+ SPLIT_NUM_BLOCKS: tl.constexpr,
28
+ ):
29
+ PAIRED_SPLIT_NUM_BLOCKS: tl.constexpr = SPLIT_NUM_BLOCKS * 2
30
+ block_start_idx = tl.program_id(0) * PAIRED_SPLIT_NUM_BLOCKS
31
+ thread_idx = tl.arange(0, PAIRED_SPLIT_NUM_BLOCKS * BLOCK_SIZE)
32
+
33
+ offsets = block_start_idx * BLOCK_SIZE + thread_idx
34
+ mask = offsets < n_elements
35
+
36
+ A = tl.load(A_ptr + offsets, mask=mask, other=0.0)
37
+
38
+ # To be able process several blocks -> (PAIRED_SPLIT_NUM_BLOCKS, BLOCK_SIZE)
39
+ A_reshaped = tl.reshape(A, (PAIRED_SPLIT_NUM_BLOCKS, BLOCK_SIZE))
40
+
41
+ # Calculating absamax for each block
42
+ absmax = tl.max(tl.abs(A_reshaped), axis=1)
43
+ absmax_offsets = block_start_idx + tl.arange(0, PAIRED_SPLIT_NUM_BLOCKS)
44
+ tl.store(absmax_ptr + absmax_offsets, absmax, mask=absmax_offsets < absmax_elements)
45
+
46
+ A_normalized = A_reshaped / absmax[:, None]
47
+ A_normalized = tl.clamp(A_normalized, -1.0, 1.0)
48
+
49
+ sign = tl.where(A_normalized < 0, 0b1000, 0b0000)
50
+ A_absf = tl.abs(A_normalized)
51
+
52
+ result = tl.where(
53
+ A_absf > 0.29166667,
54
+ tl.where(
55
+ A_absf > 0.583333, tl.where(A_absf > 0.8333333, 0b011, 0b010), tl.where(A_absf > 0.4166667, 0b101, 0b100)
56
+ ),
57
+ tl.where(
58
+ A_absf > 0.0859375,
59
+ tl.where(A_absf > 0.20833333, 0b0111, 0b0110),
60
+ tl.where(A_absf > 0.00260417, 0b0001, 0b0000),
61
+ ),
62
+ )
63
+ quantized = (result ^ sign).to(tl.uint8)
64
+
65
+ quantized = quantized.reshape((PAIRED_SPLIT_NUM_BLOCKS, BLOCK_SIZE // 2, 2))
66
+ left, right = quantized.split()
67
+ packed = left << 4 | (right & 0xF)
68
+
69
+ packed_flat = tl.reshape(packed, (BLOCK_SIZE * SPLIT_NUM_BLOCKS,))
70
+ out_offsets = block_start_idx * BLOCK_SIZE // 2 + tl.arange(0, SPLIT_NUM_BLOCKS * BLOCK_SIZE)
71
+ # Use n - n//2 instead of (n+1)//2 to avoid integer overflow for large n
72
+ out_mask = out_offsets < (n_elements - n_elements // 2)
73
+ tl.store(out_ptr + out_offsets, packed_flat, mask=out_mask)
74
+
75
+
76
+ # Triton implementation of similar CUDA kernel to avoid loading code from csrc/kernels.cu::dQuantizeNF4
77
+ # @triton.autotune(
78
+ # configs=[
79
+ # triton.Config({"SPLIT_NUM_BLOCKS": 1, "grf_mode": "auto"}, num_stages=4, num_warps=32),
80
+ # triton.Config({"SPLIT_NUM_BLOCKS": 2, "grf_mode": "auto"}, num_stages=4, num_warps=32),
81
+ # triton.Config({"SPLIT_NUM_BLOCKS": 1}),
82
+ # triton.Config({"SPLIT_NUM_BLOCKS": 2}),
83
+ # triton.Config({"SPLIT_NUM_BLOCKS": 4}),
84
+ # triton.Config({"SPLIT_NUM_BLOCKS": 8}),
85
+ # ],
86
+ # key=["n_elements"],
87
+ # )
88
+ @triton.jit
89
+ def quantize_nf4_blockwise_kernel(
90
+ A_ptr,
91
+ absmax_ptr,
92
+ out_ptr,
93
+ n_elements,
94
+ absmax_elements,
95
+ BLOCK_SIZE: tl.constexpr,
96
+ SPLIT_NUM_BLOCKS: tl.constexpr,
97
+ ):
98
+ PAIRED_SPLIT_NUM_BLOCKS: tl.constexpr = SPLIT_NUM_BLOCKS * 2
99
+ block_start_idx = tl.program_id(0) * PAIRED_SPLIT_NUM_BLOCKS
100
+ thread_idx = tl.arange(0, PAIRED_SPLIT_NUM_BLOCKS * BLOCK_SIZE)
101
+
102
+ offsets = block_start_idx * BLOCK_SIZE + thread_idx
103
+ mask = offsets < n_elements
104
+
105
+ A = tl.load(A_ptr + offsets, mask=mask, other=0.0)
106
+
107
+ # To be able process several blocks -> (PAIRED_SPLIT_NUM_BLOCKS, BLOCK_SIZE)
108
+ A_reshaped = tl.reshape(A, (PAIRED_SPLIT_NUM_BLOCKS, BLOCK_SIZE))
109
+
110
+ # Calculating absamax for each block
111
+ absmax = tl.max(tl.abs(A_reshaped), axis=1)
112
+ absmax_offsets = block_start_idx + tl.arange(0, PAIRED_SPLIT_NUM_BLOCKS)
113
+ tl.store(absmax_ptr + absmax_offsets, absmax, mask=absmax_offsets < absmax_elements)
114
+
115
+ A_normalized = A_reshaped / absmax[:, None]
116
+ A_normalized = tl.clamp(A_normalized, -1.0, 1.0)
117
+
118
+ result = tl.where(
119
+ A_normalized > 0.03979014977812767,
120
+ tl.where(
121
+ A_normalized > 0.3893125355243683,
122
+ tl.where(
123
+ A_normalized > 0.6427869200706482,
124
+ tl.where(A_normalized > 0.8614784181118011, 0b1111, 0b1110),
125
+ tl.where(A_normalized > 0.5016634166240692, 0b1101, 0b1100),
126
+ ),
127
+ tl.where(
128
+ A_normalized > 0.2035212516784668,
129
+ tl.where(A_normalized > 0.2920137718319893, 0b1011, 0b1010),
130
+ tl.where(A_normalized > 0.1202552504837513, 0b1001, 0b1000),
131
+ ),
132
+ ),
133
+ tl.where(
134
+ A_normalized > -0.33967943489551544,
135
+ tl.where(
136
+ A_normalized > -0.13791173323988914,
137
+ tl.where(A_normalized > -0.045525018125772476, 0b0111, 0b0110),
138
+ tl.where(A_normalized > -0.23460740596055984, 0b0101, 0b0100),
139
+ ),
140
+ tl.where(
141
+ A_normalized > -0.6106329262256622,
142
+ tl.where(A_normalized > -0.4599952697753906, 0b0011, 0b0010),
143
+ tl.where(A_normalized > -0.8480964004993439, 0b0001, 0b0000),
144
+ ),
145
+ ),
146
+ )
147
+ quantized = result.to(tl.uint8)
148
+
149
+ quantized = quantized.reshape((PAIRED_SPLIT_NUM_BLOCKS, BLOCK_SIZE // 2, 2))
150
+
151
+ left, right = quantized.split()
152
+ packed = left << 4 | (right & 0xF)
153
+
154
+ packed_flat = tl.reshape(packed, (BLOCK_SIZE * SPLIT_NUM_BLOCKS,))
155
+ out_offsets = block_start_idx * BLOCK_SIZE // 2 + tl.arange(0, SPLIT_NUM_BLOCKS * BLOCK_SIZE)
156
+ # Use n - n//2 instead of (n+1)//2 to avoid integer overflow for large n
157
+ out_mask = out_offsets < (n_elements - n_elements // 2)
158
+ tl.store(out_ptr + out_offsets, packed_flat, mask=out_mask)
159
+
160
+
161
+ def quantize_4bit_blockwise_triton(A, blocksize, quant_type, blocks, absmax, num_elements, quantized_out):
162
+ # grid = lambda META: (triton.cdiv(blocks, META["SPLIT_NUM_BLOCKS"]),)
163
+ split_num_blocks = 4
164
+ grid = (triton.cdiv(blocks, split_num_blocks),)
165
+ if quant_type == "fp4":
166
+ quantize_fp4_blockwise_kernel[grid](
167
+ A_ptr=A,
168
+ absmax_ptr=absmax,
169
+ out_ptr=quantized_out,
170
+ n_elements=num_elements,
171
+ absmax_elements=absmax.numel(),
172
+ BLOCK_SIZE=blocksize,
173
+ SPLIT_NUM_BLOCKS=split_num_blocks,
174
+ )
175
+ else:
176
+ quantize_nf4_blockwise_kernel[grid](
177
+ A_ptr=A,
178
+ absmax_ptr=absmax,
179
+ out_ptr=quantized_out,
180
+ n_elements=num_elements,
181
+ absmax_elements=absmax.numel(),
182
+ BLOCK_SIZE=blocksize,
183
+ SPLIT_NUM_BLOCKS=split_num_blocks,
184
+ )
185
+ return quantized_out, absmax
186
+
187
+
188
+ @triton.jit
189
+ def dequant_4bit_body_util(a, offsets, quant_ptr, absmax_ptr, n_elems, QUANT_BLOCK: tl.constexpr):
190
+ PAIRED_QUANT_BLOCK: tl.constexpr = QUANT_BLOCK // 2
191
+ mask = offsets < n_elems
192
+ higher = a & 0xF
193
+ # lower 4bits
194
+ lower = a >> 4
195
+
196
+ abs_offsets = offsets // PAIRED_QUANT_BLOCK
197
+ absmax = tl.load(absmax_ptr + abs_offsets, mask=mask, other=1.0, eviction_policy="evict_last")
198
+
199
+ # apply conversion
200
+ lower_4 = tl.load(quant_ptr + lower, eviction_policy="evict_last")
201
+ higher_4 = tl.load(quant_ptr + higher, eviction_policy="evict_last")
202
+
203
+ mul_high = higher_4 * absmax
204
+ mul_low = lower_4 * absmax
205
+ out_dq = tl.interleave(mul_low, mul_high)
206
+ return out_dq
207
+
208
+
209
+ # Triton implementation of similar CUDA kernel to avoid loading code from csrc/kernels.cu::dDequantizeFP4Tree
210
+ @triton.jit
211
+ def dequantize_fp4_tree(val, absmax):
212
+ # val: tl.tensor (uint8)
213
+ # absmax: tl.tensor (float32/float16)
214
+ # 00001100 00001011 00001001 00001111
215
+ sign = tl.where((val & 0b1000) == 0b1000, -1.0, 1.0) # -1
216
+ third_bit = (val & 0b0100) == 0b0100 # True
217
+ second_bit = (val & 0b0010) == 0b0010 # False
218
+ first_bit = (val & 0b0001) == 0b0001 # False
219
+
220
+ branch1 = tl.where(
221
+ second_bit,
222
+ tl.where(first_bit, 0.25, 0.16666667), # 1111, 1110
223
+ tl.where(first_bit, 0.5, 0.33333333), # 1101, 1100
224
+ )
225
+ branch2 = tl.where(
226
+ second_bit,
227
+ tl.where(first_bit, 1.0, 0.66666667), # 1011, 1010
228
+ tl.where(first_bit, 0.005208333333, 0.0), # 1001, 1000
229
+ )
230
+ out = tl.where(third_bit, branch1, branch2)
231
+ return out * sign * absmax
232
+
233
+
234
+ @triton.jit
235
+ def dequant_fp4_body_util(a, offsets, absmax_ptr, n_elems, QUANT_BLOCK: tl.constexpr):
236
+ PAIRED_QUANT_BLOCK: tl.constexpr = QUANT_BLOCK // 2
237
+ mask = offsets < n_elems
238
+ higher = a & 0xF
239
+ lower = a >> 4
240
+
241
+ abs_offsets = offsets // PAIRED_QUANT_BLOCK
242
+ absmax = tl.load(absmax_ptr + abs_offsets, mask=mask, other=1.0, eviction_policy="evict_last")
243
+ mul_high = dequantize_fp4_tree(higher, absmax)
244
+ mul_low = dequantize_fp4_tree(lower, absmax)
245
+ out_dq = tl.interleave(mul_low, mul_high)
246
+ return out_dq
247
+
248
+
249
+ # Triton implementation of similar CUDA kernel to avoid loading code from csrc/kernels.cu::dDequantizeNF4
250
+ @triton.jit
251
+ def dequantize_nf4_tree(val):
252
+ # val: tl.tensor (uint8)
253
+ cond0 = (val & 0b1000) == 0b1000
254
+ cond1 = (val & 0b0100) == 0b0100
255
+ cond2 = (val & 0b0010) == 0b0010
256
+ cond3 = (val & 0b0001) == 0b0001
257
+
258
+ # Positive branch (val & 0b1000) == 8
259
+ branch_pos = tl.where(
260
+ cond1,
261
+ tl.where(
262
+ cond2,
263
+ tl.where(cond3, 1.0, 0.7229568362236023), # 1111, 1110
264
+ tl.where(cond3, 0.5626170039176941, 0.44070982933044434), # 1101, 1100
265
+ ),
266
+ tl.where(
267
+ cond2,
268
+ tl.where(cond3, 0.33791524171829224, 0.24611230194568634), # 1011, 1010
269
+ tl.where(cond3, 0.16093020141124725, 0.07958029955625534), # 1001, 1000
270
+ ),
271
+ )
272
+
273
+ # Negative branch (val & 0b1000) == 0
274
+ branch_neg = tl.where(
275
+ cond1,
276
+ tl.where(
277
+ cond2,
278
+ tl.where(cond3, 0.0, -0.09105003625154495), # 0111, 0110
279
+ tl.where(cond3, -0.18477343022823334, -0.28444138169288635), # 0101, 0100
280
+ ),
281
+ tl.where(
282
+ cond2,
283
+ tl.where(cond3, -0.39491748809814453, -0.5250730514526367), # 0011, 0010
284
+ tl.where(cond3, -0.6961928009986877, -1.0), # 0001, 0000
285
+ ),
286
+ )
287
+ return tl.where(cond0, branch_pos, branch_neg)
288
+
289
+
290
+ @triton.jit
291
+ def dequant_nf4_body_util(a, offsets, absmax_ptr, n_elems, QUANT_BLOCK: tl.constexpr):
292
+ PAIRED_QUANT_BLOCK: tl.constexpr = QUANT_BLOCK // 2
293
+ mask = offsets < n_elems
294
+ higher = a & 0xF
295
+ # lower 4bits
296
+ lower = a >> 4
297
+
298
+ abs_offsets = offsets // PAIRED_QUANT_BLOCK
299
+ absmax = tl.load(absmax_ptr + abs_offsets, mask=mask, other=1.0, eviction_policy="evict_last")
300
+ mul_high = dequantize_nf4_tree(higher) * absmax
301
+ mul_low = dequantize_nf4_tree(lower) * absmax
302
+ out_dq = tl.interleave(mul_low, mul_high)
303
+ return out_dq
304
+
305
+
306
+ # All such kernels are similar, so maybe code can be generalised.
307
+ # @triton.autotune(
308
+ # configs=[
309
+ # # # triton.Config({'SPLIT_SIZE': 64}),
310
+ # # # # triton.Config({'SPLIT_SIZE': 64, 'grf_mode': 'large'}, num_stages=2, num_warps=32),
311
+ # # # # triton.Config({'SPLIT_SIZE': 64, 'grf_mode': 'auto'}, num_stages=2, num_warps=32),
312
+ # # # # triton.Config({'SPLIT_SIZE': 64, 'grf_mode': 'large'}, num_stages=4, num_warps=32),
313
+ # # # # triton.Config({'SPLIT_SIZE': 64, 'grf_mode': 'auto'}, num_stages=4, num_warps=32),
314
+ # triton.Config({'SPLIT_SIZE': 128}),
315
+ # triton.Config({'SPLIT_SIZE': 128}, num_warps = 32, num_stages = 2),
316
+ # # # triton.Config({'SPLIT_SIZE': 128}, num_warps = 4, num_stages = 4),
317
+ # # # # triton.Config({'SPLIT_SIZE': 128, 'grf_mode': 'large'}, num_stages=2, num_warps=32),
318
+ # # # # triton.Config({'SPLIT_SIZE': 128, 'grf_mode': 'auto'}, num_stages=2, num_warps=32),
319
+ # # # # triton.Config({'SPLIT_SIZE': 128, 'grf_mode': 'large'}, num_stages=4, num_warps=32),
320
+ # # # # triton.Config({'SPLIT_SIZE': 128, 'grf_mode': 'auto'}, num_stages=4, num_warps=32),
321
+ # triton.Config({'SPLIT_SIZE': 256}),
322
+ # triton.Config({'SPLIT_SIZE': 256}, num_warps = 32, num_stages = 2),
323
+ # # triton.Config({'SPLIT_SIZE': 256}, num_warps = 4, num_stages = 4),
324
+ # triton.Config({'SPLIT_SIZE': 512}),
325
+ # triton.Config({'SPLIT_SIZE': 512}, num_warps = 32, num_stages = 2),
326
+ # # triton.Config({'SPLIT_SIZE': 512}, num_warps = 4, num_stages = 4),
327
+ # # # # triton.Config({'SPLIT_SIZE': 512, 'grf_mode': 'large'}, num_stages=2, num_warps=32),
328
+ # # # # triton.Config({'SPLIT_SIZE': 512, 'grf_mode': 'auto'}, num_stages=2, num_warps=32),
329
+ # # # # triton.Config({'SPLIT_SIZE': 512, 'grf_mode': 'large'}, num_stages=4, num_warps=32),
330
+ # # # # triton.Config({'SPLIT_SIZE': 512, 'grf_mode': 'auto'}, num_stages=4, num_warps=32),
331
+ # # # triton.Config({'SPLIT_SIZE': 1024}),
332
+ # # # # triton.Config({'SPLIT_SIZE': 2048}),
333
+ # # # # triton.Config({'SPLIT_SIZE': 4096}),
334
+ # # # # triton.Config({'SPLIT_SIZE': 8192}),
335
+ # # # # triton.Config({'SPLIT_SIZE': 16384}),
336
+ # ],
337
+ # key=['num_paired_elements'],
338
+ # )
339
+ @triton.jit
340
+ def dequant_4bit_kernel(
341
+ a_ptr,
342
+ c_ptr,
343
+ quant_ptr,
344
+ absmax_ptr,
345
+ num_paired_elements,
346
+ num_output_elements,
347
+ QUANT_BLOCK: tl.constexpr,
348
+ SPLIT_SIZE: tl.constexpr,
349
+ ):
350
+ pid = tl.program_id(axis=0) # We use a 1D launch grid so axis is 0.
351
+ block_start = pid * SPLIT_SIZE
352
+ offsets = block_start + tl.arange(0, SPLIT_SIZE)
353
+ mask = offsets < num_paired_elements
354
+
355
+ a = tl.load(a_ptr + offsets, mask, eviction_policy="evict_first")
356
+
357
+ out_dq = dequant_4bit_body_util(
358
+ a=a,
359
+ offsets=offsets,
360
+ quant_ptr=quant_ptr,
361
+ absmax_ptr=absmax_ptr,
362
+ n_elems=num_paired_elements,
363
+ QUANT_BLOCK=QUANT_BLOCK,
364
+ )
365
+
366
+ out_block_start = pid * SPLIT_SIZE * 2
367
+ offs = out_block_start + tl.arange(0, SPLIT_SIZE * 2)
368
+ mask = offs < num_output_elements
369
+ tl.store(c_ptr + offs, out_dq, mask)
370
+
371
+
372
+ # @triton.autotune(
373
+ # configs=[
374
+ # triton.Config({'SPLIT_SIZE': 128}, num_warps = 32, num_stages = 2),
375
+ # triton.Config({'SPLIT_SIZE': 256}),
376
+ # triton.Config({'SPLIT_SIZE': 256}, num_warps = 32, num_stages = 2),
377
+ # triton.Config({'SPLIT_SIZE': 512}),
378
+ # triton.Config({'SPLIT_SIZE': 512}, num_warps = 32, num_stages = 2),
379
+ # triton.Config({'SPLIT_SIZE': 1024}, num_warps = 32, num_stages = 2),
380
+ # ],
381
+ # key=['num_paired_elements'],
382
+ # )
383
+ @triton.jit
384
+ def dequant_fp4_kernel(
385
+ a_ptr,
386
+ c_ptr,
387
+ absmax_ptr,
388
+ num_paired_elements,
389
+ num_output_elements,
390
+ QUANT_BLOCK: tl.constexpr,
391
+ SPLIT_SIZE: tl.constexpr,
392
+ ):
393
+ pid = tl.program_id(axis=0) # We use a 1D launch grid so axis is 0.
394
+ block_start = pid * SPLIT_SIZE
395
+ offsets = block_start + tl.arange(0, SPLIT_SIZE)
396
+ mask = offsets < num_paired_elements
397
+
398
+ a = tl.load(a_ptr + offsets, mask, eviction_policy="evict_first")
399
+
400
+ out_dq = dequant_fp4_body_util(
401
+ a=a,
402
+ offsets=offsets,
403
+ absmax_ptr=absmax_ptr,
404
+ n_elems=num_paired_elements,
405
+ QUANT_BLOCK=QUANT_BLOCK,
406
+ )
407
+
408
+ out_block_start = pid * SPLIT_SIZE * 2
409
+ offs = out_block_start + tl.arange(0, SPLIT_SIZE * 2)
410
+ mask = offs < num_output_elements
411
+ tl.store(c_ptr + offs, out_dq, mask)
412
+
413
+
414
+ # @triton.autotune(
415
+ # configs=[
416
+ # triton.Config({'SPLIT_SIZE': 128}, num_warps = 32, num_stages = 2),
417
+ # triton.Config({'SPLIT_SIZE': 256}),
418
+ # triton.Config({'SPLIT_SIZE': 256}, num_warps = 32, num_stages = 2),
419
+ # triton.Config({'SPLIT_SIZE': 512}),
420
+ # triton.Config({'SPLIT_SIZE': 512}, num_warps = 32, num_stages = 2),
421
+ # triton.Config({'SPLIT_SIZE': 1024}, num_warps = 32, num_stages = 2),
422
+ # ],
423
+ # key=['num_paired_elements'],
424
+ # )
425
+ @triton.jit
426
+ def dequant_nf4_kernel(
427
+ a_ptr,
428
+ c_ptr,
429
+ absmax_ptr,
430
+ num_paired_elements,
431
+ num_output_elements,
432
+ QUANT_BLOCK: tl.constexpr,
433
+ SPLIT_SIZE: tl.constexpr,
434
+ ):
435
+ pid = tl.program_id(axis=0) # We use a 1D launch grid so axis is 0.
436
+ block_start = pid * SPLIT_SIZE
437
+ offsets = block_start + tl.arange(0, SPLIT_SIZE)
438
+ mask = offsets < num_paired_elements
439
+
440
+ a = tl.load(a_ptr + offsets, mask, eviction_policy="evict_first")
441
+
442
+ out_dq = dequant_nf4_body_util(
443
+ a=a,
444
+ offsets=offsets,
445
+ absmax_ptr=absmax_ptr,
446
+ n_elems=num_paired_elements,
447
+ QUANT_BLOCK=QUANT_BLOCK,
448
+ )
449
+
450
+ out_block_start = pid * SPLIT_SIZE * 2
451
+ offs = out_block_start + tl.arange(0, SPLIT_SIZE * 2)
452
+ mask = offs < num_output_elements
453
+ tl.store(c_ptr + offs, out_dq, mask)
454
+
455
+
456
+ def dequantize_4bit_impl(
457
+ A: torch.Tensor,
458
+ absmax: torch.Tensor,
459
+ blocksize: int,
460
+ quant_type: str,
461
+ dtype: torch.dtype,
462
+ out: torch.Tensor,
463
+ ) -> None:
464
+ # It's will be processed as an array, so
465
+ # actual length is row * col
466
+ # Elements are in uint8 format, so interleaved
467
+ # so total amount of data is 2 * elem_count
468
+ number_of_paired_elements = A.numel()
469
+ num_output_elements = out.numel()
470
+ # we assume that split_size > quant_blocksize
471
+
472
+ SPLIT_SIZE = 256
473
+ # grid = lambda META: (triton.cdiv(number_of_paired_elements, META['SPLIT_SIZE']), )
474
+ grid = (triton.cdiv(number_of_paired_elements, SPLIT_SIZE),)
475
+ if quant_type == "fp4":
476
+ dequant_fp4_kernel[grid](A, out, absmax, number_of_paired_elements, num_output_elements, blocksize, SPLIT_SIZE)
477
+ else:
478
+ dequant_nf4_kernel[grid](A, out, absmax, number_of_paired_elements, num_output_elements, blocksize, SPLIT_SIZE)
479
+
480
+
481
+ def dequantize_4bit_impl_passing_code(
482
+ A: torch.Tensor,
483
+ absmax: torch.Tensor,
484
+ blocksize: int,
485
+ code: torch.Tensor,
486
+ dtype: torch.dtype,
487
+ out: torch.Tensor,
488
+ ) -> None:
489
+ number_of_paired_elements = A.numel()
490
+ num_output_elements = out.numel()
491
+ # we assume that split_size > quant_blocksize
492
+
493
+ SPLIT_SIZE = 256
494
+ # grid = lambda META: (triton.cdiv(number_of_paired_elements, META['SPLIT_SIZE']), )
495
+ grid = (triton.cdiv(number_of_paired_elements, SPLIT_SIZE),)
496
+ dequant_4bit_kernel[grid](
497
+ A, out, code, absmax, number_of_paired_elements, num_output_elements, blocksize, SPLIT_SIZE
498
+ )
499
+
500
+
501
+ ######################### Fallback dequantization functions #########################
502
+ ## for debug ##
503
+
504
+
505
+ # @triton.autotune(
506
+ # configs=[
507
+ # # triton.Config({'SPLIT_NUM_BLOCKS': 1, 'grf_mode': 'large'}, num_stages=2, num_warps=32),
508
+ # # triton.Config({'SPLIT_NUM_BLOCKS': 1, 'grf_mode': 'auto'}, num_stages=2, num_warps=32),
509
+ # # triton.Config({'SPLIT_NUM_BLOCKS': 1, 'grf_mode': 'large'}, num_stages=4, num_warps=32),
510
+ # # #
511
+ # # triton.Config({"SPLIT_NUM_BLOCKS": 1, "grf_mode": "auto"}, num_stages=4, num_warps=32),
512
+ # #
513
+ # triton.Config({"SPLIT_NUM_BLOCKS": 2}),
514
+ # # triton.Config({"SPLIT_NUM_BLOCKS": 2, "grf_mode": "large"}, num_stages=2, num_warps=32),
515
+ # # # triton.Config({'SPLIT_NUM_BLOCKS': 2, 'grf_mode': 'large'}, num_stages=4, num_warps=32),
516
+ # # triton.Config({"SPLIT_NUM_BLOCKS": 2, "grf_mode": "auto"}, num_stages=2, num_warps=32),
517
+ # # triton.Config({"SPLIT_NUM_BLOCKS": 2, "grf_mode": "auto"}, num_stages=4, num_warps=32),
518
+ # # triton.Config({"SPLIT_NUM_BLOCKS": 4, "grf_mode": "large"}, num_stages=2, num_warps=32),
519
+ # # triton.Config({"SPLIT_NUM_BLOCKS": 4, "grf_mode": "large"}, num_stages=4, num_warps=32),
520
+ # # triton.Config({'SPLIT_NUM_BLOCKS': 8, 'grf_mode': 'large'}, num_stages=2, num_warps=32),
521
+ # ],
522
+ # key=["n_elements", "BLOCK_SIZE"],
523
+ # )
524
+ @triton.jit
525
+ def quantize_4bit_blockwise_kernel(
526
+ A_ptr,
527
+ code_ptr,
528
+ absmax_ptr,
529
+ out_ptr,
530
+ n_elements,
531
+ BLOCK_SIZE: tl.constexpr,
532
+ CODE_SIZE: tl.constexpr,
533
+ SPLIT_NUM_BLOCKS: tl.constexpr,
534
+ ):
535
+ PAIRED_SPLIT_NUM_BLOCKS: tl.constexpr = SPLIT_NUM_BLOCKS * 2
536
+ block_start_idx = tl.program_id(0) * PAIRED_SPLIT_NUM_BLOCKS
537
+ thread_idx = tl.arange(0, PAIRED_SPLIT_NUM_BLOCKS * BLOCK_SIZE)
538
+
539
+ offsets = block_start_idx * BLOCK_SIZE + thread_idx
540
+ mask = offsets < n_elements
541
+
542
+ A = tl.load(A_ptr + offsets, mask=mask, other=0.0)
543
+
544
+ # To be able process several blocks -> (PAIRED_SPLIT_NUM_BLOCKS, BLOCK_SIZE)
545
+ A_reshaped = tl.reshape(A, (PAIRED_SPLIT_NUM_BLOCKS, BLOCK_SIZE))
546
+
547
+ # Calculating absamax for each block
548
+ absmax = tl.max(tl.abs(A_reshaped), axis=1)
549
+ tl.store(absmax_ptr + block_start_idx + tl.arange(0, PAIRED_SPLIT_NUM_BLOCKS), absmax)
550
+
551
+ A_normalized = A_reshaped / absmax[:, None]
552
+ A_normalized = tl.clamp(A_normalized, -1.0, 1.0)
553
+
554
+ lower_pivot = tl.zeros((PAIRED_SPLIT_NUM_BLOCKS, BLOCK_SIZE), dtype=tl.int32)
555
+ upper_pivot = tl.full((PAIRED_SPLIT_NUM_BLOCKS, BLOCK_SIZE), CODE_SIZE - 1, dtype=tl.int32)
556
+
557
+ for _ in range(4): # ceil(log2(code_size)) = 4, actually, in general case should be input parameter
558
+ pivot = (lower_pivot + upper_pivot) // 2
559
+ val = tl.load(code_ptr + pivot)
560
+ is_higher = A_normalized > val # code[pivot]
561
+ lower_pivot = tl.where(is_higher, pivot, lower_pivot)
562
+ upper_pivot = tl.where(is_higher, upper_pivot, pivot)
563
+
564
+ # Choose closest level
565
+ lower_val = tl.load(code_ptr + lower_pivot)
566
+ upper_val = tl.load(code_ptr + upper_pivot)
567
+ lower_dist = tl.abs(A_normalized - lower_val)
568
+ upper_dist = tl.abs(A_normalized - upper_val)
569
+ quantized = tl.where(lower_dist <= upper_dist, lower_pivot, upper_pivot).to(tl.uint8)
570
+
571
+ quantized = quantized.reshape((PAIRED_SPLIT_NUM_BLOCKS, BLOCK_SIZE // 2, 2))
572
+ quantized = quantized.to(tl.uint8, bitcast=True)
573
+ left, right = quantized.split()
574
+ packed = left << 4 | (right & 0xF)
575
+
576
+ # Reduce don't guarantee the order of the elements passed to unite_2_int4
577
+ # packed = tl.reduce(quantized, axis=2, combine_fn=unite_2_int4)
578
+ # packed = packed.to(tl.uint8, bitcast=True)
579
+
580
+ packed_flat = tl.reshape(packed, (BLOCK_SIZE * SPLIT_NUM_BLOCKS,))
581
+ out_offsets = block_start_idx * BLOCK_SIZE // 2 + tl.arange(0, SPLIT_NUM_BLOCKS * BLOCK_SIZE)
582
+ out_mask = out_offsets < n_elements // 2
583
+ tl.store(out_ptr + out_offsets, packed_flat, mask=out_mask)