bitsandbytes 0.50.0__py3-none-win_arm64.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 +78 -0
  2. bitsandbytes/__main__.py +4 -0
  3. bitsandbytes/_ops.py +510 -0
  4. bitsandbytes/autograd/__init__.py +0 -0
  5. bitsandbytes/autograd/_functions.py +491 -0
  6. bitsandbytes/backends/__init__.py +0 -0
  7. bitsandbytes/backends/cpu/__init__.py +0 -0
  8. bitsandbytes/backends/cpu/ops.py +580 -0
  9. bitsandbytes/backends/cuda/__init__.py +0 -0
  10. bitsandbytes/backends/cuda/ops.py +1199 -0
  11. bitsandbytes/backends/default/__init__.py +0 -0
  12. bitsandbytes/backends/default/ops.py +632 -0
  13. bitsandbytes/backends/hpu/__init__.py +0 -0
  14. bitsandbytes/backends/hpu/ops.py +53 -0
  15. bitsandbytes/backends/mps/__init__.py +0 -0
  16. bitsandbytes/backends/mps/ops.py +277 -0
  17. bitsandbytes/backends/triton/__init__.py +0 -0
  18. bitsandbytes/backends/triton/kernels_4bit.py +577 -0
  19. bitsandbytes/backends/triton/kernels_8bit_quant.py +195 -0
  20. bitsandbytes/backends/triton/kernels_optim.py +1177 -0
  21. bitsandbytes/backends/triton/ops.py +304 -0
  22. bitsandbytes/backends/utils.py +94 -0
  23. bitsandbytes/backends/xpu/__init__.py +0 -0
  24. bitsandbytes/backends/xpu/ops.py +305 -0
  25. bitsandbytes/cextension.py +405 -0
  26. bitsandbytes/consts.py +12 -0
  27. bitsandbytes/cuda_specs.py +111 -0
  28. bitsandbytes/diagnostics/__init__.py +0 -0
  29. bitsandbytes/diagnostics/cuda.py +193 -0
  30. bitsandbytes/diagnostics/main.py +134 -0
  31. bitsandbytes/diagnostics/utils.py +12 -0
  32. bitsandbytes/functional.py +1810 -0
  33. bitsandbytes/libbitsandbytes_cpu.dll +0 -0
  34. bitsandbytes/nn/__init__.py +19 -0
  35. bitsandbytes/nn/modules.py +1220 -0
  36. bitsandbytes/nn/parametrize.py +206 -0
  37. bitsandbytes/optim/__init__.py +22 -0
  38. bitsandbytes/optim/adagrad.py +187 -0
  39. bitsandbytes/optim/adam.py +346 -0
  40. bitsandbytes/optim/adamw.py +337 -0
  41. bitsandbytes/optim/ademamix.py +410 -0
  42. bitsandbytes/optim/lamb.py +190 -0
  43. bitsandbytes/optim/lars.py +259 -0
  44. bitsandbytes/optim/lion.py +266 -0
  45. bitsandbytes/optim/optimizer.py +756 -0
  46. bitsandbytes/optim/rmsprop.py +170 -0
  47. bitsandbytes/optim/sgd.py +152 -0
  48. bitsandbytes/py.typed +0 -0
  49. bitsandbytes/utils.py +208 -0
  50. bitsandbytes-0.50.0.dist-info/METADATA +288 -0
  51. bitsandbytes-0.50.0.dist-info/RECORD +54 -0
  52. bitsandbytes-0.50.0.dist-info/WHEEL +5 -0
  53. bitsandbytes-0.50.0.dist-info/licenses/LICENSE +21 -0
  54. bitsandbytes-0.50.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,577 @@
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.00520833, 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)