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,491 @@
1
+ from dataclasses import dataclass
2
+ import logging
3
+ from math import prod
4
+ from typing import Optional
5
+ import warnings
6
+ from warnings import warn
7
+
8
+ import torch
9
+
10
+ import bitsandbytes.functional as F
11
+
12
+ logger = logging.getLogger(__name__)
13
+
14
+ # The inverse transformation for the colTuring and colAmpere format were contributed by Alex Borzunov:
15
+ # https://github.com/bigscience-workshop/petals/blob/main/src/petals/utils/linear8bitlt_patch.py
16
+
17
+
18
+ """
19
+ This class pools outlier dimensions across layers.
20
+ This is particularly important for small models where outlier features
21
+ are less systematic and occur with low frequency.
22
+ """
23
+
24
+
25
+ class GlobalOutlierPooler:
26
+ _instance = None
27
+
28
+ def __init__(self):
29
+ raise RuntimeError("Call get_instance() instead")
30
+
31
+ def initialize(self):
32
+ self.outliers = set()
33
+ self.model_dim = None
34
+
35
+ @classmethod
36
+ def get_instance(cls):
37
+ if cls._instance is None:
38
+ cls._instance = cls.__new__(cls)
39
+ cls._instance.initialize()
40
+ return cls._instance
41
+
42
+ def add_outliers(self, outlier_idx, feature_dim):
43
+ if self.model_dim is None:
44
+ self.model_dim = feature_dim
45
+ if feature_dim != self.model_dim:
46
+ return # we do not encode outliers for the 2nd FFN layer
47
+
48
+ self.outliers.update(outlier_idx.tolist())
49
+
50
+ def get_current_outlier_idx(self):
51
+ return torch.Tensor(list(self.outliers)).to(torch.int64)
52
+
53
+
54
+ _is_compiling = torch.compiler.is_compiling
55
+
56
+
57
+ @dataclass
58
+ class MatmulLtState:
59
+ force_no_igemmlt: bool = False
60
+
61
+ CB: Optional[torch.Tensor] = None
62
+ SB: Optional[torch.Tensor] = None
63
+ SCB: Optional[torch.Tensor] = None
64
+
65
+ SBt: Optional[torch.Tensor] = None
66
+ CBt: Optional[torch.Tensor] = None
67
+
68
+ subB: Optional[torch.Tensor] = None
69
+
70
+ outlier_pool: Optional[GlobalOutlierPooler] = None
71
+ has_accumulated_gradients = False
72
+ threshold = 0.0
73
+ idx: Optional[torch.Tensor] = None
74
+ is_training = True
75
+ has_fp16_weights = True
76
+ use_pool = False
77
+
78
+ # Deprecated attributes kept for downstream compatibility (TGI, vLLM).
79
+ # These are always None and will be fully removed in the next release.
80
+ _deprecated_fields = frozenset({"CxB", "CxBt", "formatB", "_tile_indices"})
81
+
82
+ def __getattr__(self, name):
83
+ if name in MatmulLtState._deprecated_fields:
84
+ warnings.warn(
85
+ f"MatmulLtState.{name} is deprecated and will be removed in the next bitsandbytes release.",
86
+ FutureWarning,
87
+ stacklevel=2,
88
+ )
89
+ return None
90
+ raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'")
91
+
92
+ def reset_grads(self):
93
+ self.CB = None
94
+ self.SB = None
95
+ self.SCB = None
96
+
97
+ self.SBt = None
98
+ self.CBt = None
99
+
100
+
101
+ class MatMul8bitLt(torch.autograd.Function):
102
+ @staticmethod
103
+ def forward(
104
+ ctx: torch.autograd.function.FunctionCtx,
105
+ A: torch.Tensor,
106
+ B: torch.Tensor,
107
+ out: Optional[torch.Tensor] = None,
108
+ bias: Optional[torch.Tensor] = None,
109
+ state: Optional[MatmulLtState] = None,
110
+ ):
111
+ state = state or MatmulLtState()
112
+
113
+ # default of pytorch behavior if inputs are empty
114
+ ctx.is_empty = False
115
+ if prod(A.shape) == 0:
116
+ ctx.is_empty = True
117
+ ctx.A = A
118
+ ctx.B = B
119
+ ctx.bias = bias
120
+ if A.shape[-1] == B.shape[0]:
121
+ return torch.empty(A.shape[:-1] + B.shape[1:], dtype=A.dtype, device=A.device)
122
+ else:
123
+ return torch.empty(A.shape[:-1] + B.shape[:1], dtype=A.dtype, device=A.device)
124
+
125
+ input_shape = A.shape
126
+
127
+ # Cast A to fp16
128
+ if A.dtype != torch.float16 and not _is_compiling():
129
+ logger.warning("MatMul8bitLt: inputs will be cast from %s to float16 during quantization", A.dtype)
130
+
131
+ if len(A.shape) == 3:
132
+ A = A.reshape(-1, A.shape[-1])
133
+
134
+ # 1. Quantize A. Note that as a side-effect, outliers are suppressed in CA/CAt.
135
+ if ctx.needs_input_grad[1]:
136
+ # Slower path
137
+ CA, CAt, SCA, SCAt, outlier_cols = F.int8_double_quant(A.to(torch.float16), threshold=state.threshold)
138
+ else:
139
+ # Fast path
140
+ CA, SCA, outlier_cols = F.int8_vectorwise_quant(A.to(torch.float16), threshold=state.threshold)
141
+ CAt = SCAt = None
142
+
143
+ has_grad = False
144
+
145
+ if state.has_fp16_weights or state.CB is None:
146
+ has_grad = getattr(B, "grad", None) is not None
147
+ is_transposed = not B.is_contiguous() and B.shape[0] == B.stride(1)
148
+ if is_transposed:
149
+ B = B.contiguous()
150
+
151
+ if (state.is_training and not has_grad) or state.CB is None or state.SCB is None:
152
+ state.reset_grads()
153
+
154
+ # 2. Quantize B
155
+ state.CB, state.SCB, _ = F.int8_vectorwise_quant(B.to(torch.float16))
156
+
157
+ # Handle sparse decomposition
158
+ if state.threshold > 0.0:
159
+ state.idx = outlier_cols
160
+
161
+ # Mixed Int8 Matmul + Dequant + Bias
162
+ output, subA = torch.ops.bitsandbytes.int8_mixed_scaled_mm(
163
+ A,
164
+ CA,
165
+ state.CB,
166
+ SCA,
167
+ state.SCB,
168
+ outlier_cols,
169
+ bias,
170
+ )
171
+
172
+ else:
173
+ # Int8 Matmul + Dequant + Bias
174
+ output = torch.ops.bitsandbytes.int8_scaled_mm.default(
175
+ CA, state.CB, SCA, state.SCB, bias=bias, dtype=A.dtype
176
+ )
177
+ subA = None
178
+
179
+ # 5. Save state
180
+ ctx.state = state
181
+
182
+ ctx.grad_shape = input_shape
183
+ ctx.dtype_A = A.dtype
184
+ ctx.dtype_bias = None if bias is None else bias.dtype
185
+
186
+ if any(ctx.needs_input_grad[:2]):
187
+ ctx.tensors = (CAt, subA, A)
188
+ ctx.tensor_states = (SCAt, state.idx)
189
+ else:
190
+ ctx.tensors = [None, None, None]
191
+ ctx.tensor_states = (None, None)
192
+ ctx.save_for_backward(None, None)
193
+
194
+ output_shape = (*input_shape[:-1], state.CB.shape[0])
195
+
196
+ if len(input_shape) == 3:
197
+ return output.reshape(output_shape)
198
+
199
+ return output
200
+
201
+ @staticmethod
202
+ def backward(ctx: torch.autograd.function.FunctionCtx, grad_output: torch.Tensor):
203
+ if ctx.is_empty:
204
+ bias_grad = None if ctx.bias is None else torch.zeros_like(ctx.bias)
205
+ return torch.zeros_like(ctx.A), torch.zeros_like(ctx.B), None, bias_grad, None
206
+
207
+ req_gradA, req_gradB, _, req_gradBias, _ = ctx.needs_input_grad
208
+ CAt, subA, _A = ctx.tensors
209
+ SCAt, idx = ctx.tensor_states
210
+ state: MatmulLtState = ctx.state
211
+ grad_A = grad_B = grad_bias = None
212
+
213
+ if req_gradBias:
214
+ # compute grad_bias first before changing grad_output dtype
215
+ grad_bias = grad_output.sum(0, dtype=ctx.dtype_bias)
216
+
217
+ # Cast grad_output to fp16
218
+ if len(grad_output.shape) == 3:
219
+ grad_output = grad_output.reshape(-1, grad_output.shape[-1]).contiguous()
220
+
221
+ if req_gradB:
222
+ Cgrad, _, _, SCgradt, _ = F.int8_double_quant(grad_output.to(torch.float16))
223
+
224
+ grad_B = torch.ops.bitsandbytes.int8_scaled_mm.default(
225
+ Cgrad.t().contiguous(),
226
+ CAt.t(),
227
+ SCgradt,
228
+ SCAt,
229
+ dtype=torch.float16,
230
+ )
231
+
232
+ if state.threshold > 0.0 and subA is not None and subA.numel() > 0:
233
+ grad_B[:, idx] += torch.matmul(grad_output.t(), subA)
234
+
235
+ if req_gradA:
236
+ if state.CB is not None:
237
+ CB = state.CB.to(ctx.dtype_A, copy=True).mul_(state.SCB.unsqueeze(1).mul(1.0 / 127.0))
238
+ grad_A = torch.matmul(grad_output.to(ctx.dtype_A), CB).view(ctx.grad_shape)
239
+ else:
240
+ raise Exception("State must contain CB matrix for backward")
241
+
242
+ return grad_A, grad_B, None, grad_bias, None
243
+
244
+
245
+ class MatMul8bitFp(torch.autograd.Function):
246
+ # For Intel CPU and XPU MatMul8bitFp is much faster (~3x) than MatMul8bitLt in finetune.
247
+ # Because the MatMul8bitLt has more mechanisms in computing grad.
248
+ # We don't have fast kernel for quant/dequant 8bit in CPU/XPU, so it's very slow.
249
+ # We'd like to use dequant + matmul to run finetune with good performance.
250
+
251
+ @staticmethod
252
+ def forward(ctx, A, B, out=None, bias=None, state=MatmulLtState):
253
+ if state.has_fp16_weights or state.CB is None:
254
+ has_grad = getattr(B, "grad", None) is not None
255
+ is_transposed = not B.is_contiguous() and B.shape[0] == B.stride(1)
256
+ if is_transposed:
257
+ B = B.contiguous()
258
+
259
+ if (state.is_training and not has_grad) or state.CB is None or state.SCB is None:
260
+ state.reset_grads()
261
+ state.CB, state.SCB, _ = F.int8_vectorwise_quant(B.to(torch.float16))
262
+ B = state.CB
263
+
264
+ CB = state.CB.data.to(A.dtype).mul_(state.SCB.unsqueeze(1).mul(1.0 / 127.0))
265
+ output = torch.nn.functional.linear(A, CB, bias)
266
+ ctx.state = state
267
+ ctx.dtype_A = A.dtype
268
+ ctx.grad_shape = A.shape
269
+ ctx.A = A
270
+ ctx.dtype_bias = None if bias is None else bias.dtype
271
+ return output
272
+
273
+ @staticmethod
274
+ def backward(ctx, grad_output):
275
+ req_gradA, req_gradB, _, req_gradBias, _ = ctx.needs_input_grad
276
+ A = ctx.A
277
+ state = ctx.state
278
+ grad_A = grad_B = grad_bias = None
279
+ if req_gradBias:
280
+ # compute grad_bias first before changing grad_output dtype
281
+ grad_bias = grad_output.sum(0, dtype=ctx.dtype_bias)
282
+
283
+ # Cast grad_output to fp16
284
+ if len(grad_output.shape) == 3:
285
+ grad_output = grad_output.reshape(-1, grad_output.shape[-1]).contiguous()
286
+
287
+ if req_gradB:
288
+ grad_B = torch.matmul(A.t(), grad_output).t()
289
+
290
+ if req_gradA:
291
+ if state.CB is not None:
292
+ CB = state.CB.to(ctx.dtype_A, copy=True).mul_(state.SCB.unsqueeze(1).mul(1.0 / 127.0))
293
+ grad_A = torch.matmul(grad_output.to(ctx.dtype_A), CB).view(ctx.grad_shape)
294
+ else:
295
+ raise Exception("State must contain CB matrix for backward")
296
+
297
+ return grad_A, grad_B, None, grad_bias, None
298
+
299
+
300
+ class MatMul4Bit(torch.autograd.Function):
301
+ # forward is the same, but we added the fallback for pre-turing GPUs
302
+
303
+ @staticmethod
304
+ def forward(ctx, A, B, out=None, bias=None, quant_state: Optional[F.QuantState] = None):
305
+ # default of pytorch behavior if inputs are empty
306
+ ctx.is_empty = False
307
+ if A.numel() == 0:
308
+ ctx.is_empty = True
309
+ ctx.A = A
310
+ ctx.B = B
311
+ ctx.bias = bias
312
+ B_shape = quant_state.shape
313
+ if A.shape[-1] == B_shape[0]:
314
+ return torch.empty(A.shape[:-1] + B_shape[1:], dtype=A.dtype, device=A.device)
315
+ else:
316
+ return torch.empty(A.shape[:-1] + B_shape[:1], dtype=A.dtype, device=A.device)
317
+
318
+ # Normalize to canonical [(N*K+1)//2, 1]. Packed weights are always contiguous
319
+ # in this orientation (B.t() callers get strides [1,1], still compatible).
320
+ # quant_state.shape is the source of truth for N and K.
321
+ B = B.view(-1, 1)
322
+
323
+ if not quant_state.nested:
324
+ output = torch.ops.bitsandbytes.gemm_4bit.default(
325
+ A,
326
+ B,
327
+ quant_state.shape,
328
+ quant_state.absmax,
329
+ quant_state.blocksize,
330
+ quant_state.quant_type,
331
+ bias=bias,
332
+ )
333
+ elif quant_state.state2.blocksize == 256:
334
+ output = torch.ops.bitsandbytes.gemm_4bit.default(
335
+ A,
336
+ B,
337
+ quant_state.shape,
338
+ quant_state.state2.absmax,
339
+ quant_state.blocksize,
340
+ quant_state.quant_type,
341
+ bias=bias,
342
+ absmax_8bit=quant_state.absmax,
343
+ absmax_code=quant_state.state2.code,
344
+ absmax_offset=quant_state.offset,
345
+ )
346
+ else:
347
+ raise NotImplementedError("nested quantization with state2.blocksize != 256 is not supported")
348
+
349
+ if out is not None:
350
+ out.copy_(output)
351
+ output = out
352
+
353
+ # 3. Save state
354
+ ctx.state = quant_state
355
+ ctx.dtype_A, ctx.dtype_B, ctx.dtype_bias = A.dtype, B.dtype, None if bias is None else bias.dtype
356
+
357
+ if any(ctx.needs_input_grad[:2]):
358
+ ctx.tensors = (None, B)
359
+ else:
360
+ ctx.tensors = (None, None)
361
+
362
+ return output
363
+
364
+ @staticmethod
365
+ def backward(ctx, grad_output):
366
+ if ctx.is_empty:
367
+ bias_grad = None if ctx.bias is None else torch.zeros_like(ctx.bias)
368
+ return torch.zeros_like(ctx.A), torch.zeros_like(ctx.B), None, bias_grad, None
369
+
370
+ req_gradA, _, _, req_gradBias, _ = ctx.needs_input_grad
371
+ _, B = ctx.tensors
372
+
373
+ grad_A, grad_B, grad_bias = None, None, None
374
+
375
+ if req_gradBias:
376
+ # compute grad_bias first before changing grad_output dtype
377
+ grad_bias = grad_output.sum(0, dtype=ctx.dtype_bias)
378
+
379
+ # not supported by PyTorch. TODO: create work-around
380
+ # if req_gradB: grad_B = torch.matmul(grad_output.t(), A)
381
+ if req_gradA:
382
+ # B in ctx.tensors is already in canonical [(N*K+1)//2, 1] form (normalized in forward).
383
+ # dequantize returns [N, K]; matmul(grad_output[M,N], [N,K]) = grad_A[M,K].
384
+ grad_A = torch.matmul(grad_output, F.dequantize_4bit(B, ctx.state).to(grad_output.dtype))
385
+
386
+ return grad_A, grad_B, None, grad_bias, None
387
+
388
+
389
+ def matmul(
390
+ A: torch.Tensor,
391
+ B: torch.Tensor,
392
+ out: Optional[torch.Tensor] = None,
393
+ state: Optional[MatmulLtState] = None,
394
+ threshold=0.0,
395
+ bias: Optional[torch.Tensor] = None,
396
+ ):
397
+ state = state or MatmulLtState()
398
+ if threshold > 0.0:
399
+ state.threshold = threshold
400
+ # MatMul8bitLt is slower because no fast kernel for quant/dequant 8bit in CPU/XPU
401
+ if state.is_training:
402
+ if A.device.type in ("cpu", "xpu"):
403
+ return MatMul8bitFp.apply(A, B, out, bias, state)
404
+ return MatMul8bitLt.apply(A, B, out, bias, state)
405
+
406
+
407
+ def matmul_4bit(
408
+ A: torch.Tensor,
409
+ B: torch.Tensor,
410
+ quant_state: F.QuantState,
411
+ out: Optional[torch.Tensor] = None,
412
+ bias: Optional[torch.Tensor] = None,
413
+ ):
414
+ if quant_state is None:
415
+ raise ValueError("quant_state is required")
416
+ if len(quant_state.shape) != 2:
417
+ raise ValueError("matmul_4bit: quant_state.shape must be 2D [N, K]")
418
+
419
+ # packing_format_for_cpu uses a different memory layout optimized for AVX512BF16.
420
+ # This flag is only set for inference (weight conversion happens at eval time).
421
+ # The underlying kernel supports any M via tiled GEMM despite the gemv name.
422
+ if A.device.type == "cpu" and getattr(quant_state, "packing_format_for_cpu", False):
423
+ result = F.gemv_4bit(A, B, out=out, state=quant_state)
424
+ if bias is not None:
425
+ result += bias
426
+ return result
427
+
428
+ # Normalize B to canonical [(N*K+1)//2, 1]. Packed weights are always contiguous
429
+ # in this orientation (B.t() callers get strides [1,1], still compatible).
430
+ # quant_state.shape is the source of truth for N and K.
431
+ B = B.view(-1, 1)
432
+
433
+ K = A.shape[-1]
434
+
435
+ # Weight is in [K, N] orientation when A's inner dim matches shape[0] not shape[1].
436
+ # Square weights (K==N) are ambiguous and treated as [N, K].
437
+ if K == quant_state.shape[0] and K != quant_state.shape[1]:
438
+ if not _is_compiling():
439
+ warn(
440
+ f"matmul_4bit: weight was quantized from a [K, N] tensor (quant_state.shape={list(quant_state.shape)}). "
441
+ "Re-quantize from the weight in [N, K] (out_features, in_features) orientation. "
442
+ "This will be an error in a future version.",
443
+ DeprecationWarning,
444
+ stacklevel=2,
445
+ )
446
+ B_dq = F.dequantize_4bit(B, quant_state).to(A.dtype)
447
+ result = torch.nn.functional.linear(A, B_dq.t(), bias)
448
+ if out is not None:
449
+ out.copy_(result)
450
+ return out
451
+ return result
452
+
453
+ needs_grad = torch.is_grad_enabled() and (A.requires_grad or (bias is not None and bias.requires_grad))
454
+ if not needs_grad:
455
+ A_numel = A.numel()
456
+ if A_numel == 0:
457
+ if out is not None:
458
+ return out
459
+ return torch.empty((*A.shape[:-1], quant_state.shape[0]), dtype=A.dtype, device=A.device)
460
+
461
+ if not quant_state.nested:
462
+ result = torch.ops.bitsandbytes.gemm_4bit.default(
463
+ A,
464
+ B,
465
+ quant_state.shape,
466
+ quant_state.absmax,
467
+ quant_state.blocksize,
468
+ quant_state.quant_type,
469
+ bias=bias,
470
+ )
471
+ elif quant_state.state2.blocksize == 256:
472
+ result = torch.ops.bitsandbytes.gemm_4bit.default(
473
+ A,
474
+ B,
475
+ quant_state.shape,
476
+ quant_state.state2.absmax,
477
+ quant_state.blocksize,
478
+ quant_state.quant_type,
479
+ bias=bias,
480
+ absmax_8bit=quant_state.absmax,
481
+ absmax_code=quant_state.state2.code,
482
+ absmax_offset=quant_state.offset,
483
+ )
484
+ else:
485
+ raise NotImplementedError("nested quantization with state2.blocksize != 256 is not supported")
486
+ if out is not None:
487
+ out.copy_(result)
488
+ return out
489
+ return result
490
+
491
+ return MatMul4Bit.apply(A, B, out, bias, quant_state)
File without changes
File without changes