tests: fix cuda model tests. (#14464) · alexanderar/diffusers@d5baa4f · GitHub
Skip to content

Commit d5baa4f

Browse files
sayakpauldg845
andauthored
tests: fix cuda model tests. (huggingface#14464)
* tests: fix cuda model tests. * up * up * up * add to docstrings. * restore previous beehaviour. --------- Co-authored-by: dg845 <58458699+dg845@users.noreply.github.com>
1 parent c401daa commit d5baa4f

13 files changed

Lines changed: 130 additions & 49 deletions

‎docker/diffusers-pytorch-cuda/Dockerfile‎

Lines changed: 3 additions & 0 deletions

‎src/diffusers/models/autoencoders/autoencoder_kl_minimax_h3.py‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
from ..attention import AttentionMixin, AttentionModuleMixin, FeedForward
2525
from ..attention_dispatch import dispatch_attention_fn
2626
from ..modeling_outputs import AutoencoderKLOutput
27-
from ..modeling_utils import ModelMixin
27+
from ..modeling_utils import ModelMixin, get_parameter_dtype
2828
from .vae import AutoencoderMixin, DecoderOutput, DiagonalGaussianDistribution
2929

3030

@@ -857,6 +857,9 @@ def encode(self, x: torch.Tensor, return_dict: bool = True) -> AutoencoderKLOutp
857857
The latent distribution of the encoded videos. Note that MiniMax-H3 normalizes the sampled latents with
858858
`latents_mean` / `latents_std` afterwards.
859859
"""
860+
# Every module is pinned to float32 by `_keep_in_fp32_modules`, so a pipeline running in a lower `torch_dtype`
861+
# hands over lower-precision pixels; align them with the weights, like the audio autoencoder does.
862+
x = x.to(get_parameter_dtype(self.encoder))
860863
if self.use_slicing and x.shape[0] > 1:
861864
moments = torch.cat([self._encode(x_slice) for x_slice in x.split(1)])
862865
else:
@@ -881,6 +884,7 @@ def decode(self, z: torch.Tensor, return_dict: bool = True) -> DecoderOutput | t
881884
[`~models.autoencoders.vae.DecoderOutput`] or `tuple`:
882885
The decoded videos, shape `(batch_size, out_channels, num_frames, height, width)`.
883886
"""
887+
z = z.to(get_parameter_dtype(self.decoder))
884888
if self.use_slicing and z.shape[0] > 1:
885889
decoded = torch.cat([self._decode(z_slice) for z_slice in z.split(1)])
886890
else:

‎src/diffusers/models/autoencoders/autoencoder_kl_minimax_h3_audio.py‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,10 @@ class AutoencoderKLMiniMaxH3Audio(ModelMixin, ConfigMixin, AttentionMixin):
524524
"""
525525

526526
_supports_gradient_checkpointing = False
527+
# `weight_norm` recomputes `weight` from `weight_g` / `weight_v` in a forward pre-hook, which runs before the
528+
# leaf-level group offloading hook has onloaded them, so the convolution would see a CPU weight. Same reason the
529+
# other weight-normalized audio autoencoders (`AutoencoderOobleck`, `Cosmos3AVAEAudioTokenizer`) opt out.
530+
_supports_group_offloading = False
527531
# The released checkpoint is float32 and the DAC/BigVGAN stack (weight-normalized convolutions, Snake
528532
# activations) degrades audibly under bfloat16 (roughly 20 dB quieter decodes), so a pipeline-level
529533
# `torch_dtype=torch.bfloat16` must not downcast the weights.

‎src/diffusers/models/transformers/transformer_minimax_h3.py‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,14 @@ class MiniMaxH3TransformerOutput(BaseOutput):
4646
sample (`torch.Tensor` of shape `(batch_size, num_video_tokens, in_channels * prod(patch_size))`):
4747
The video velocity prediction for the rows addressed by `video_indices`, in the same order. Conditioning
4848
rows are returned unmasked — masking them out before the scheduler step is the caller's job.
49-
audio_sample (`torch.Tensor` of shape `(batch_size, num_audio_tokens, audio_in_channels)`):
50-
The audio velocity prediction for the rows addressed by `audio_indices`, in the same order.
49+
audio_sample (`torch.Tensor` of shape `(batch_size, num_audio_tokens, audio_in_channels)`, defaults to `None`):
50+
The audio velocity prediction for the rows addressed by `audio_indices`, in the same order. `forward`
51+
always populates it; it only defaults to `None` so that the output can be rebuilt from a plain dict of its
52+
fields, which is how the accelerate offload hooks move a `BaseOutput` back to the input device.
5153
"""
5254

5355
sample: torch.Tensor
54-
audio_sample: torch.Tensor
56+
audio_sample: torch.Tensor | None = None
5557

5658

5759
def _apply_rotary_emb(hidden_states: torch.Tensor, cos: torch.Tensor, sin: torch.Tensor) -> torch.Tensor:

‎tests/models/autoencoders/test_models_autoencoder_kl_kvae_video.py‎

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,19 @@
2020
from diffusers.utils.torch_utils import randn_tensor
2121

2222
from ...testing_utils import enable_full_determinism, torch_device
23-
from ..testing_utils import BaseModelTesterConfig, MemoryTesterMixin, ModelTesterMixin, TrainingTesterMixin
23+
from ..testing_utils import (
24+
BaseModelTesterConfig,
25+
MemoryTesterMixin,
26+
ModelTesterMixin,
27+
TrainingTesterMixin,
28+
run_nondeterministic,
29+
)
2430
from .testing_utils import NewAutoencoderTesterMixin
2531

2632

2733
enable_full_determinism()
2834

2935

30-
def _run_nondeterministic(fn):
31-
# reflection_pad3d_backward_out_cuda has no deterministic CUDA implementation;
32-
# temporarily relax the requirement for tests that do backward passes.
33-
torch.use_deterministic_algorithms(False)
34-
try:
35-
fn()
36-
finally:
37-
torch.use_deterministic_algorithms(True)
38-
39-
4036
class AutoencoderKLKVAEVideoTesterConfig(BaseModelTesterConfig):
4137
@property
4238
def model_class(self):
@@ -91,14 +87,16 @@ def test_gradient_checkpointing_is_applied(self):
9187
expected_set = {"KVAECachedEncoder3D", "KVAECachedDecoder3D"}
9288
super().test_gradient_checkpointing_is_applied(expected_set=expected_set)
9389

90+
# reflection_pad3d_backward_out_cuda has no deterministic CUDA implementation, so every test with a backward
91+
# pass runs with determinism relaxed.
9492
def test_training(self):
95-
_run_nondeterministic(super().test_training)
93+
run_nondeterministic(super().test_training)
9694

9795
def test_training_with_ema(self):
98-
_run_nondeterministic(super().test_training_with_ema)
96+
run_nondeterministic(super().test_training_with_ema)
9997

10098
def test_mixed_precision_training(self):
101-
_run_nondeterministic(super().test_mixed_precision_training)
99+
run_nondeterministic(super().test_mixed_precision_training)
102100

103101
@pytest.mark.skip(
104102
"Gradient checkpointing recomputes the forward pass, but the model uses a stateful cache_dict "
@@ -112,8 +110,10 @@ def test_gradient_checkpointing_equivalence(self):
112110
class TestAutoencoderKLKVAEVideoMemory(AutoencoderKLKVAEVideoTesterConfig, MemoryTesterMixin):
113111
"""Memory optimization tests for AutoencoderKLKVAEVideo."""
114112

113+
# reflection_pad3d_backward_out_cuda has no deterministic CUDA implementation, so every test with a backward
114+
# pass runs with determinism relaxed.
115115
def test_layerwise_casting_training(self):
116-
_run_nondeterministic(super().test_layerwise_casting_training)
116+
run_nondeterministic(super().test_layerwise_casting_training)
117117

118118

119119
class TestAutoencoderKLKVAEVideoSlicingTiling(AutoencoderKLKVAEVideoTesterConfig, NewAutoencoderTesterMixin):

‎tests/models/autoencoders/test_models_autoencoder_kl_minimax_h3.py‎

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
BaseModelTesterConfig,
2626
MemoryTesterMixin,
2727
ModelTesterMixin,
28-
TorchCompileTesterMixin,
2928
TrainingTesterMixin,
29+
run_nondeterministic,
3030
)
3131
from .testing_utils import NewAutoencoderTesterMixin
3232

@@ -134,6 +134,18 @@ def test_encode_decode_temporal_geometry(self):
134134
class TestAutoencoderKLMiniMaxH3Memory(AutoencoderKLMiniMaxH3TesterConfig, MemoryTesterMixin):
135135
"""Memory optimization tests for the MiniMax-H3 video autoencoder."""
136136

137+
@pytest.mark.skip(
138+
"`_keep_in_fp32_modules` pins every module of this autoencoder, so layerwise casting has nothing to cast and "
139+
"the memory footprint does not change."
140+
)
141+
def test_layerwise_casting_memory(self):
142+
pass
143+
144+
# The encoder's reflect spatial padding has no deterministic CUDA backward
145+
# (reflection_pad3d_backward_out_cuda), so every test with a backward pass runs with determinism relaxed.
146+
def test_layerwise_casting_training(self):
147+
run_nondeterministic(super().test_layerwise_casting_training)
148+
137149

138150
class TestAutoencoderKLMiniMaxH3Training(AutoencoderKLMiniMaxH3TesterConfig, TrainingTesterMixin):
139151
"""Training tests for the MiniMax-H3 video autoencoder."""
@@ -143,13 +155,23 @@ def test_gradient_checkpointing_is_applied(self):
143155
expected_set={"MiniMaxH3VideoDownBlock3d", "MiniMaxH3VideoViTDecoder3d"}
144156
)
145157

158+
# The encoder's reflect spatial padding has no deterministic CUDA backward
159+
# (reflection_pad3d_backward_out_cuda), so every test with a backward pass runs with determinism relaxed.
160+
def test_training(self):
161+
run_nondeterministic(super().test_training)
146162

147-
class TestAutoencoderKLMiniMaxH3Attention(AutoencoderKLMiniMaxH3TesterConfig, AttentionTesterMixin):
148-
"""Attention processor tests for the MiniMax-H3 video autoencoder."""
163+
def test_training_with_ema(self):
164+
run_nondeterministic(super().test_training_with_ema)
149165

166+
def test_mixed_precision_training(self):
167+
run_nondeterministic(super().test_mixed_precision_training)
150168

151-
class TestAutoencoderKLMiniMaxH3TorchCompile(AutoencoderKLMiniMaxH3TesterConfig, TorchCompileTesterMixin):
152-
"""Torch compile tests for the MiniMax-H3 video autoencoder."""
169+
def test_gradient_checkpointing_equivalence(self):
170+
run_nondeterministic(super().test_gradient_checkpointing_equivalence)
171+
172+
173+
class TestAutoencoderKLMiniMaxH3Attention(AutoencoderKLMiniMaxH3TesterConfig, AttentionTesterMixin):
174+
"""Attention processor tests for the MiniMax-H3 video autoencoder."""
153175

154176

155177
class TestAutoencoderKLMiniMaxH3SlicingTiling(AutoencoderKLMiniMaxH3TesterConfig, NewAutoencoderTesterMixin):

‎tests/models/autoencoders/test_models_autoencoder_kl_minimax_h3_audio.py‎

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
BaseModelTesterConfig,
2626
MemoryTesterMixin,
2727
ModelTesterMixin,
28-
TorchCompileTesterMixin,
2928
TrainingTesterMixin,
29+
run_nondeterministic,
3030
)
3131

3232

@@ -130,10 +130,33 @@ def test_encode_pads_to_the_hop_length(self):
130130
class TestAutoencoderKLMiniMaxH3AudioMemory(AutoencoderKLMiniMaxH3AudioTesterConfig, MemoryTesterMixin):
131131
"""Memory optimization tests for the MiniMax-H3 audio autoencoder."""
132132

133+
@pytest.mark.skip(
134+
"`_keep_in_fp32_modules` pins every module of this autoencoder, so layerwise casting has nothing to cast and "
135+
"the memory footprint does not change."
136+
)
137+
def test_layerwise_casting_memory(self):
138+
pass
139+
140+
# The causal-attention projection's `F.adaptive_avg_pool1d` has no deterministic CUDA backward
141+
# (adaptive_avg_pool2d_backward_cuda), so every test with a backward pass runs with determinism relaxed.
142+
def test_layerwise_casting_training(self):
143+
run_nondeterministic(super().test_layerwise_casting_training)
144+
133145

134146
class TestAutoencoderKLMiniMaxH3AudioTraining(AutoencoderKLMiniMaxH3AudioTesterConfig, TrainingTesterMixin):
135147
"""Training tests for the MiniMax-H3 audio autoencoder."""
136148

149+
# The causal-attention projection's `F.adaptive_avg_pool1d` has no deterministic CUDA backward
150+
# (adaptive_avg_pool2d_backward_cuda), so every test with a backward pass runs with determinism relaxed.
151+
def test_training(self):
152+
run_nondeterministic(super().test_training)
153+
154+
def test_training_with_ema(self):
155+
run_nondeterministic(super().test_training_with_ema)
156+
157+
def test_mixed_precision_training(self):
158+
run_nondeterministic(super().test_mixed_precision_training)
159+
137160

138161
class TestAutoencoderKLMiniMaxH3AudioAttention(AutoencoderKLMiniMaxH3AudioTesterConfig, AttentionTesterMixin):
139162
"""Attention processor tests for the MiniMax-H3 audio autoencoder."""
@@ -144,7 +167,3 @@ class TestAutoencoderKLMiniMaxH3AudioAttention(AutoencoderKLMiniMaxH3AudioTester
144167
)
145168
def test_attention_processor_count_mismatch_raises_error(self):
146169
pass
147-
148-
149-
class TestAutoencoderKLMiniMaxH3AudioTorchCompile(AutoencoderKLMiniMaxH3AudioTesterConfig, TorchCompileTesterMixin):
150-
"""Torch compile tests for the MiniMax-H3 audio autoencoder."""

‎tests/models/autoencoders/test_models_autoencoder_vidtok.py‎

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,19 @@
1919
from diffusers.utils.torch_utils import randn_tensor
2020

2121
from ...testing_utils import enable_full_determinism, torch_device
22-
from ..testing_utils import BaseModelTesterConfig, MemoryTesterMixin, ModelTesterMixin, TrainingTesterMixin
22+
from ..testing_utils import (
23+
BaseModelTesterConfig,
24+
MemoryTesterMixin,
25+
ModelTesterMixin,
26+
TrainingTesterMixin,
27+
run_nondeterministic,
28+
)
2329
from .testing_utils import NewAutoencoderTesterMixin
2430

2531

2632
enable_full_determinism()
2733

2834

29-
def _run_nondeterministic(fn):
30-
# avg_pool3d_backward_cuda has no deterministic CUDA implementation;
31-
# temporarily relax the requirement for tests that do backward passes.
32-
torch.use_deterministic_algorithms(False)
33-
try:
34-
fn()
35-
finally:
36-
torch.use_deterministic_algorithms(True)
37-
38-
3935
class AutoencoderVidTokTesterConfig(BaseModelTesterConfig):
4036
@property
4137
def model_class(self):
@@ -90,24 +86,28 @@ def test_gradient_checkpointing_is_applied(self):
9086
expected_set = {"VidTokEncoder3D", "VidTokDecoder3D"}
9187
super().test_gradient_checkpointing_is_applied(expected_set=expected_set)
9288

89+
# avg_pool3d_backward_cuda has no deterministic CUDA implementation, so every test with a backward pass runs
90+
# with determinism relaxed.
9391
def test_training(self):
94-
_run_nondeterministic(super().test_training)
92+
run_nondeterministic(super().test_training)
9593

9694
def test_training_with_ema(self):
97-
_run_nondeterministic(super().test_training_with_ema)
95+
run_nondeterministic(super().test_training_with_ema)
9896

9997
def test_mixed_precision_training(self):
100-
_run_nondeterministic(super().test_mixed_precision_training)
98+
run_nondeterministic(super().test_mixed_precision_training)
10199

102100
def test_gradient_checkpointing_equivalence(self):
103-
_run_nondeterministic(super().test_gradient_checkpointing_equivalence)
101+
run_nondeterministic(super().test_gradient_checkpointing_equivalence)
104102

105103

106104
class TestAutoencoderVidTokMemory(AutoencoderVidTokTesterConfig, MemoryTesterMixin):
107105
"""Memory optimization tests for AutoencoderVidTok."""
108106

107+
# avg_pool3d_backward_cuda has no deterministic CUDA implementation, so every test with a backward pass runs
108+
# with determinism relaxed.
109109
def test_layerwise_casting_training(self):
110-
_run_nondeterministic(super().test_layerwise_casting_training)
110+
run_nondeterministic(super().test_layerwise_casting_training)
111111

112112

113113
class TestAutoencoderVidTokSlicingTiling(AutoencoderVidTokTesterConfig, NewAutoencoderTesterMixin):

‎tests/models/testing_utils/__init__.py‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
)
4949
from .single_file import SingleFileTesterMixin
5050
from .training import TrainingTesterMixin
51+
from .utils import run_nondeterministic
5152

5253

5354
__all__ = [
@@ -94,6 +95,7 @@
9495
"QuantoCompileTesterMixin",
9596
"QuantoConfigMixin",
9697
"QuantoTesterMixin",
98+
"run_nondeterministic",
9799
"SDNQCompileTesterMixin",
98100
"SDNQConfigMixin",
99101
"SDNQTesterMixin",

‎tests/models/testing_utils/compile.py‎

Lines changed: 1 addition & 1 deletion

0 commit comments

Comments
 (0)