11from collections .abc import Sequence
2- from math import prod
32from typing import Optional
43
54import torch
@@ -96,7 +95,7 @@ def _(A: torch.Tensor, B: torch.Tensor, out: torch.Tensor):
9695@register_fake ("bitsandbytes::int8_vectorwise_quant" )
9796def _ (A : torch .Tensor , threshold = 0.0 ):
9897 out_row = torch .empty (A .shape , device = A .device , dtype = torch .int8 )
99- row_stats = torch .empty (prod ( A .shape [: - 1 ]) , device = A .device , dtype = torch .float32 )
98+ row_stats = torch .empty (A . numel () // A .shape [- 1 ], device = A .device , dtype = torch .float32 )
10099
101100 if threshold == 0.0 :
102101 return out_row , row_stats , None
@@ -153,7 +152,7 @@ def _(
153152) -> tuple [torch .Tensor , torch .Tensor , torch .Tensor , torch .Tensor , Optional [torch .Tensor ]]:
154153 out_row = torch .empty_like (A , dtype = torch .int8 )
155154 out_col = torch .empty_like (A , dtype = torch .int8 )
156- row_stats = torch .empty (prod ( A .shape [: - 1 ]) , device = A .device , dtype = torch .float32 )
155+ row_stats = torch .empty (A . numel () // A .shape [- 1 ], device = A .device , dtype = torch .float32 )
157156 col_stats = torch .empty (A .shape [- 1 ], device = A .device , dtype = torch .float32 )
158157 outlier_n = torch .library .get_ctx ().new_dynamic_size ()
159158 outlier_cols = A .new_empty (outlier_n , dtype = torch .int64 )
@@ -175,7 +174,13 @@ def _(
175174 shape : Sequence [int ],
176175 dtype : torch .dtype ,
177176) -> torch .Tensor :
178- torch ._check (blocksize >= 0 , lambda : f"Blocksize must be non-negative, got { blocksize } " )
177+ torch ._check (blocksize in (32 , 64 , 128 , 256 , 512 , 1024 , 2048 , 4096 ), lambda : f"invalid blocksize { blocksize } " )
178+ torch ._check (quant_type in ("nf4" , "fp4" ), lambda : f"quant_type must be 'nf4' or 'fp4', got { quant_type !r} " )
179+ torch ._check (absmax .dtype == torch .float32 , lambda : f"absmax must be float32, got { absmax .dtype } " )
180+ torch ._check (
181+ dtype in (torch .float16 , torch .bfloat16 , torch .float32 ),
182+ lambda : f"Blockwise 4bit dequantization only supports 16/32-bit floats, but got { dtype } " ,
183+ )
179184 return torch .empty (shape , dtype = dtype , device = A .device )
180185
181186
@@ -195,7 +200,13 @@ def _(
195200 dtype : torch .dtype ,
196201 out : torch .Tensor ,
197202) -> None :
198- torch ._check (blocksize >= 0 , lambda : f"Blocksize must be non-negative, got { blocksize } " )
203+ torch ._check (blocksize in (32 , 64 , 128 , 256 , 512 , 1024 , 2048 , 4096 ), lambda : f"invalid blocksize { blocksize } " )
204+ torch ._check (quant_type in ("nf4" , "fp4" ), lambda : f"quant_type must be 'nf4' or 'fp4', got { quant_type !r} " )
205+ torch ._check (absmax .dtype == torch .float32 , lambda : f"absmax must be float32, got { absmax .dtype } " )
206+ torch ._check (
207+ dtype in (torch .float16 , torch .bfloat16 , torch .float32 ),
208+ lambda : f"Blockwise 4bit dequantization only supports 16/32-bit floats, but got { dtype } " ,
209+ )
199210 torch ._check (out .shape == shape , lambda : f"Expected out.shape == { shape } , got { out .shape } " )
200211 torch ._check (out .device == A .device , lambda : f"Expected out.device == { A .device } , got { out .device } " )
201212 torch ._check (out .dtype == dtype , lambda : f"Expected out.dtype == { dtype } , got { out .dtype } " )
@@ -211,7 +222,12 @@ def _(
211222def _ (
212223 A : torch .Tensor , blocksize : int , quant_type : str , quant_storage : torch .dtype
213224) -> tuple [torch .Tensor , torch .Tensor ]:
214- torch ._check (blocksize >= 0 , lambda : f"Blocksize must be non-negative, got { blocksize } " )
225+ torch ._check (blocksize in (32 , 64 , 128 , 256 , 512 , 1024 , 2048 , 4096 ), lambda : f"invalid blocksize { blocksize } " )
226+ torch ._check (quant_type in ("nf4" , "fp4" ), lambda : f"quant_type must be 'nf4' or 'fp4', got { quant_type !r} " )
227+ torch ._check (
228+ A .dtype in (torch .float16 , torch .bfloat16 , torch .float32 ),
229+ lambda : f"Blockwise 4bit quantization only supports 16/32-bit floats, but got { A .dtype } " ,
230+ )
215231
216232 n = A .numel ()
217233 blocks = - (n // - blocksize )
@@ -250,7 +266,7 @@ def _(
250266 B .dtype in (torch .uint8 , torch .bfloat16 , torch .float16 , torch .float32 ),
251267 lambda : f"B must be backed by storage of type uint8, bfloat16, float16, or float32, got { B .dtype } " ,
252268 )
253- torch ._check (blocksize in [ 32 , 64 , 128 , 256 , 512 , 1024 , 2048 , 4096 ] , lambda : f"invalid blocksize { blocksize } " )
269+ torch ._check (blocksize in ( 32 , 64 , 128 , 256 , 512 , 1024 , 2048 , 4096 ) , lambda : f"invalid blocksize { blocksize } " )
254270 torch ._check (quant_type in ("nf4" , "fp4" ), lambda : f"quant_type must be 'nf4' or 'fp4', got { quant_type !r} " )
255271 torch ._check (absmax .dtype == torch .float32 , lambda : f"absmax must be float32, got { absmax .dtype } " )
256272 if absmax_8bit is not None :
@@ -287,8 +303,12 @@ def _(
287303
288304@register_fake ("bitsandbytes::dequantize_blockwise" )
289305def _ (A : torch .Tensor , absmax : torch .Tensor , code : torch .Tensor , blocksize : int , dtype : torch .dtype ) -> torch .Tensor :
290- torch ._check (blocksize >= 0 , lambda : f"Blocksize must be non-negative , got { blocksize } " )
306+ torch ._check (blocksize > 0 , lambda : f"blocksize must be positive , got { blocksize } " )
291307 torch ._check (A .dtype == torch .uint8 , lambda : f"A must be uint8, got { A .dtype } " )
308+ torch ._check (
309+ dtype in (torch .float16 , torch .bfloat16 , torch .float32 ),
310+ lambda : f"Blockwise dequantization only supports 16/32-bit floats, but got { dtype } " ,
311+ )
292312 return torch .empty_like (A , dtype = dtype )
293313
294314
@@ -302,8 +322,12 @@ def _(A: torch.Tensor, absmax: torch.Tensor, code: torch.Tensor, blocksize: int,
302322def _ (
303323 A : torch .Tensor , absmax : torch .Tensor , code : torch .Tensor , blocksize : int , dtype : torch .dtype , out : torch .Tensor
304324):
305- torch ._check (blocksize >= 0 , lambda : f"Blocksize must be non-negative , got { blocksize } " )
325+ torch ._check (blocksize > 0 , lambda : f"blocksize must be positive , got { blocksize } " )
306326 torch ._check (A .dtype == torch .uint8 , lambda : f"A must be uint8, got { A .dtype } " )
327+ torch ._check (
328+ dtype in (torch .float16 , torch .bfloat16 , torch .float32 ),
329+ lambda : f"Blockwise dequantization only supports 16/32-bit floats, but got { dtype } " ,
330+ )
307331 torch ._check (out .shape == A .shape , lambda : f"Expected out.shape == { A .shape } , got { out .shape } " )
308332 torch ._check (out .device == A .device , lambda : f"Expected out.device == { A .device } , got { out .device } " )
309333 torch ._check (out .dtype == dtype , lambda : f"Expected out.dtype == { dtype } , got { out .dtype } " )
@@ -314,7 +338,11 @@ def _(
314338
315339@register_fake ("bitsandbytes::quantize_blockwise" )
316340def _ (A : torch .Tensor , code : torch .Tensor , blocksize : int ) -> tuple [torch .Tensor , torch .Tensor ]:
317- torch ._check (blocksize >= 0 , lambda : f"Blocksize must be non-negative, got { blocksize } " )
341+ torch ._check (blocksize > 0 , lambda : f"blocksize must be positive, got { blocksize } " )
342+ torch ._check (
343+ A .dtype in (torch .float16 , torch .bfloat16 , torch .float32 ),
344+ lambda : f"Blockwise quantization only supports 16/32-bit floats, but got { A .dtype } " ,
345+ )
318346 n = A .numel ()
319347 blocks = - (n // - blocksize )
320348 absmax = torch .empty ((blocks ,), device = A .device , dtype = torch .float32 )
@@ -332,14 +360,13 @@ def _(A: torch.Tensor, code: torch.Tensor, blocksize: int) -> tuple[torch.Tensor
332360def _ (
333361 A : torch .Tensor , B : torch .Tensor , shapeB : Sequence [int ], absmax : torch .Tensor , code : torch .Tensor , blocksize : int
334362) -> torch .Tensor :
335- torch ._check (blocksize >= 0 , lambda : f"Blocksize must be non-negative, got { blocksize } " )
336- torch ._check (A .numel () == A .size (- 1 ), lambda : f"A must be a vector with leading dimensions of 1, got { A .shape } " )
363+ torch ._check (blocksize in (32 , 64 , 128 , 256 , 512 , 1024 , 2048 , 4096 ), lambda : f"invalid blocksize { blocksize } " )
337364 torch ._check (
338- A .dtype in [ torch .float16 , torch .bfloat16 , torch .float32 ] ,
365+ A .dtype in ( torch .float16 , torch .bfloat16 , torch .float32 ) ,
339366 lambda : f"A must be float16, bfloat16, or float32, got { A .dtype } " ,
340367 )
341368 torch ._check (
342- B .dtype in [ torch .uint8 , torch .bfloat16 , torch .float16 , torch .float32 ] ,
369+ B .dtype in ( torch .uint8 , torch .bfloat16 , torch .float16 , torch .float32 ) ,
343370 lambda : f"B must be backed by storage of type uint8, bfloat16, float16, or float32, got { B .dtype } " ,
344371 )
345372 shape = (* A .shape [:- 1 ], shapeB [0 ])
@@ -362,14 +389,13 @@ def _(
362389 blocksize : int ,
363390 out : torch .Tensor ,
364391) -> None :
365- torch ._check (blocksize >= 0 , lambda : f"Blocksize must be non-negative, got { blocksize } " )
366- torch ._check (A .numel () == A .size (- 1 ), lambda : f"A must be a vector with leading dimensions of 1, got { A .shape } " )
392+ torch ._check (blocksize in (32 , 64 , 128 , 256 , 512 , 1024 , 2048 , 4096 ), lambda : f"invalid blocksize { blocksize } " )
367393 torch ._check (
368- A .dtype in [ torch .float16 , torch .bfloat16 , torch .float32 ] ,
394+ A .dtype in ( torch .float16 , torch .bfloat16 , torch .float32 ) ,
369395 lambda : f"A must be float16, bfloat16, or float32, got { A .dtype } " ,
370396 )
371397 torch ._check (
372- B .dtype in [ torch .uint8 , torch .bfloat16 , torch .float16 , torch .float32 ] ,
398+ B .dtype in ( torch .uint8 , torch .bfloat16 , torch .float16 , torch .float32 ) ,
373399 lambda : f"B must be backed by storage of type uint8, bfloat16, float16, or float32, got { B .dtype } " ,
374400 )
375401 torch ._check (
0 commit comments