@@ -83,13 +83,24 @@ def is_device_quack_compat() -> bool:
8383 return torch .cuda .get_device_capability () in ((9 , 0 ), (10 , 0 ))
8484
8585
86+ # NOTE: This constraint comes from https://github.com/Dao-AILab/quack/blob/59631e98/quack/reduction_base.py#L35-L38
87+ def is_last_dim_divisible (dtype : dtypes .dtype , last_dim_size : int ) -> bool :
88+ return last_dim_size % (128 // 8 // dtype .bytes ) == 0
89+
90+
8691# Register [`quack`](https://github.com/Dao-AILab/quack) ops
8792if find_spec ("quack" ) is not None :
8893 # softmax
8994 from quack .softmax import _softmax_fwd , _softmax_backward
9095
9196 def quack_softmax_impl (a : torch .Tensor ) -> torch .Tensor :
92- return _softmax_fwd (a )
97+ original_shape = a .shape
98+ if requires_reshpae := a .ndim > 2 :
99+ a = a .view (- 1 , original_shape [- 1 ])
100+ ret = _softmax_fwd (a )
101+ if requires_reshpae :
102+ ret = ret .view (original_shape )
103+ return ret
93104
94105 def quack_softmax_meta (a : TensorProxy ) -> TensorProxy :
95106 return TensorProxy (like = a )
@@ -101,7 +112,14 @@ def quack_softmax_meta(a: TensorProxy) -> TensorProxy:
101112 )
102113
103114 def quack_softmax_backward (g : torch .Tensor , a : torch .Tensor ) -> torch .Tensor :
104- return _softmax_backward (g , a )
115+ original_shape = g .shape
116+ if requires_reshape := g .ndim > 2 :
117+ g = g .view (- 1 , original_shape [- 1 ])
118+ a = a .view (- 1 , original_shape [- 1 ])
119+ ret = _softmax_backward (g , a )
120+ if requires_reshape :
121+ ret = ret .view (original_shape )
122+ return ret
105123
106124 def quack_softmax_backward_meta (g : TensorProxy , a : TensorProxy ) -> TensorProxy :
107125 return TensorProxy (like = g )
@@ -123,11 +141,11 @@ def quack_softmax_checker(
123141 last_dims = {- 1 , a .ndim - 1 }
124142 allowed_dtypes = {None , a .dtype }
125143 return (
126- a .ndim == 2
127- and dim in last_dims
144+ dim in last_dims
128145 and dtype in allowed_dtypes
129146 and a .dtype in {dtypes .float16 , dtypes .bfloat16 , dtypes .float32 }
130147 and is_device_quack_compat ()
148+ and is_last_dim_divisible (a .dtype , a .shape [- 1 ])
131149 )
132150
133151 def quack_softmax_transform (
@@ -139,26 +157,42 @@ def quack_softmax_transform(
139157 ) -> TensorProxy :
140158 return quack_softmax (a )
141159
142- def quack_softmax_grad (
143- a : TensorProxy ,
144- / ,
145- dim : int ,
146- * ,
147- dtype : thunder_dtype | None = None ,
148- ) -> TensorProxy :
149- fwd = quack_softmax (a )
150- g = get_grad (fwd )
151- a_grad = quack_softmax_backward (g , fwd )
152- put_grad (a , a_grad )
153-
154- return fwd
160+ # NOTE: Softmax backward doesn't look functioning as follows:
161+ # def _engine_run_backward(
162+ # t_outputs: Sequence[Union[torch.Tensor, GradientEdge]],
163+ # *args: Any,
164+ # **kwargs: Any,
165+ # ) -> tuple[torch.Tensor, ...]:
166+ # attach_logging_hooks = log.getEffectiveLevel() <= logging.DEBUG
167+ # if attach_logging_hooks:
168+ # unregister_hooks = _register_logging_hooks_on_whole_graph(t_outputs)
169+ # try:
170+ # > return Variable._execution_engine.run_backward( # Calls into the C++ engine to run the backward pass
171+ # t_outputs, *args, **kwargs
172+ # ) # Calls into the C++ engine to run the backward pass
173+ # E RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn
174+ #
175+ # /pytorch/torch/autograd/graph.py:829: RuntimeError
176+ # def quack_softmax_grad(
177+ # a: TensorProxy,
178+ # /,
179+ # dim: int,
180+ # *,
181+ # dtype: thunder_dtype | None = None,
182+ # ) -> TensorProxy:
183+ # fwd = quack_softmax(a)
184+ # g = get_grad(fwd)
185+ # a_grad = quack_softmax_backward(g, fwd)
186+ # put_grad(a, a_grad)
187+
188+ # return fwd
155189
156190 for ltorch_softmax in (ltorch ._softmax , ltorch .softmax ):
157191 cutlass_dsl_ex .register_implementation (
158192 ltorch_softmax ,
159193 checker = quack_softmax_checker ,
160194 execution_transform = quack_softmax_transform ,
161- grad_transform = quack_softmax_grad ,
195+ # grad_transform=quack_softmax_grad,
162196 )
163197
164198 # crossentropy
@@ -305,7 +339,13 @@ def quack_layer_norm_forward_impl(
305339 return_rstd : bool ,
306340 return_mean : bool ,
307341 ) -> torch .Tensor :
308- return layernorm (x , weight , eps , return_rstd = return_rstd , return_mean = return_mean )
342+ original_shape = x .shape
343+ if requires_reshape := x .ndim > 2 :
344+ x = x .view (- 1 , original_shape [- 1 ])
345+ ret = layernorm (x , weight , eps , return_rstd = return_rstd , return_mean = return_mean )
346+ if requires_reshape :
347+ ret = ret .view (original_shape )
348+ return ret
309349
310350 def quack_layer_norm_forward_meta (
311351 x : TensorProxy ,
@@ -332,8 +372,7 @@ def quack_layer_norm_checker(
332372 eps : Number = 1e-5 ,
333373 ) -> bool :
334374 if (
335- a .ndim != 2
336- or a .dtype not in {dtypes .float16 , dtypes .bfloat16 , dtypes .float32 }
375+ a .dtype not in {dtypes .float16 , dtypes .bfloat16 , dtypes .float32 }
337376 or weight .ndim != 1
338377 or a .shape [- 1 ] != weight .shape [0 ]
339378 or weight .dtype not in {dtypes .float32 }
@@ -365,7 +404,13 @@ def quack_rms_norm_forward_impl(
365404 weight : torch .Tensor ,
366405 eps : float = 1e-6 ,
367406 ) -> torch .Tensor :
368- return _rmsnorm_fwd (x , weight , eps , return_rstd = False )
407+ original_shape = x .shape
408+ if requires_reshape := x .ndim > 2 :
409+ x = x .view (- 1 , original_shape [- 1 ])
410+ ret = _rmsnorm_fwd (x , weight , eps , return_rstd = False )
411+ if requires_reshape :
412+ ret = ret .view (original_shape )
413+ return ret
369414
370415 def quack_rms_norm_forward_meta (
371416 x : TensorProxy ,
@@ -386,7 +431,14 @@ def quack_rms_norm_backward_impl(
386431 weight : torch .Tensor ,
387432 rstd : torch .Tensor ,
388433 ) -> torch .Tensor :
389- return _rmsnorm_backward (x , weight , grad , rstd )
434+ original_shape = grad .shape
435+ if requires_reshape := grad .ndim > 2 :
436+ grad = grad .view (- 1 , original_shape [- 1 ])
437+ x = x .view (- 1 , original_shape [- 1 ])
438+ ret = _rmsnorm_backward (x , weight , grad , rstd )
439+ if requires_reshape :
440+ ret = ret .view (original_shape )
441+ return ret
390442
391443 def quack_rms_norm_backward_meta (
392444 grad : TensorProxy ,
@@ -411,21 +463,26 @@ def quack_rms_norm_checker(
411463 eps : float | None = None ,
412464 ) -> bool :
413465 if (
414- a .ndim != 2
415- or weight .ndim != 1
466+ weight .ndim != 1
416467 or a .shape [- 1 ] != weight .shape [0 ]
417468 or a .dtype not in {dtypes .float16 , dtypes .bfloat16 , dtypes .float32 }
418469 or weight .dtype not in {dtypes .float16 , dtypes .bfloat16 , dtypes .float32 }
419470 ):
420471 return False
421- return weight is not None and is_device_quack_compat ()
472+ return weight is not None and is_device_quack_compat () and is_last_dim_divisible ( a . dtype , a . shape [ - 1 ])
422473
423474 def quack_rms_norm_aug_forward_impl (
424475 x : torch .Tensor ,
425476 weight : torch .Tensor ,
426477 eps : float = 1e-6 ,
427478 ) -> tuple [torch .Tensor , torch .Tensor ]:
428- return _rmsnorm_fwd (x , weight , eps , return_rstd = True )
479+ original_shape = x .shape
480+ if requires_reshape := x .ndim > 2 :
481+ x = x .view (- 1 , original_shape [- 1 ])
482+ fwd , rstd = _rmsnorm_fwd (x , weight , eps , return_rstd = True )
483+ if requires_reshape :
484+ fwd = fwd .view (original_shape )
485+ return fwd , rstd
429486
430487 def quack_rms_norm_aug_forward_meta (
431488 x : TensorProxy ,
@@ -451,6 +508,23 @@ def quack_rms_norm_transform(
451508 eps = 1e-6
452509 return quack_rms_norm_aug_forward (a , weight , eps )[0 ]
453510
511+ # NOTE: The backward looks not functioning:
512+ # def _engine_run_backward(
513+ # t_outputs: Sequence[Union[torch.Tensor, GradientEdge]],
514+ # *args: Any,
515+ # **kwargs: Any,
516+ # ) -> tuple[torch.Tensor, ...]:
517+ # attach_logging_hooks = log.getEffectiveLevel() <= logging.DEBUG
518+ # if attach_logging_hooks:
519+ # unregister_hooks = _register_logging_hooks_on_whole_graph(t_outputs)
520+ # try:
521+ # > return Variable._execution_engine.run_backward( # Calls into the C++ engine to run the backward pass
522+ # t_outputs, *args, **kwargs
523+ # ) # Calls into the C++ engine to run the backward pass
524+ # E RuntimeError: One of the differentiated Tensors does not require grad
525+ #
526+ # /pytorch/torch/autograd/graph.py:829: RuntimeError
527+
454528 def quack_rms_norm_grad (
455529 a : TensorProxy ,
456530 / ,
@@ -471,5 +545,5 @@ def quack_rms_norm_grad(
471545 ltorch .rms_norm ,
472546 checker = quack_rms_norm_checker ,
473547 execution_transform = quack_rms_norm_transform ,
474- grad_transform = quack_rms_norm_grad ,
548+ # grad_transform=quack_rms_norm_grad,
475549 )
0 commit comments