|
| 1 | +import torch |
| 2 | +import os |
| 3 | +import pytest |
| 4 | + |
| 5 | + |
| 6 | +if os.getenv("ALLOW_COVERAGE_TRACE") != "1": |
| 7 | + pytest.skip("Skipping test_coverage_hf_diffusers.py in regular CI", allow_module_level=True) |
| 8 | + |
| 9 | +hf_diffusers_unet2d_condition_model_ids = [ |
| 10 | + "runwayml/stable-diffusion-v1-5", |
| 11 | + "CompVis/stable-diffusion-v1-4", |
| 12 | + "ionet-official/bc8-alpha", |
| 13 | + "stabilityai/sd-turbo", |
| 14 | + "runwayml/stable-diffusion-inpainting", |
| 15 | + "stabilityai/stable-diffusion-xl-base-1.0", |
| 16 | + "stabilityai/stable-diffusion-xl-refiner-1.0", |
| 17 | + "diffusers/stable-diffusion-xl-1.0-inpainting-0.1", |
| 18 | +] |
| 19 | + |
| 20 | +from thunder.tests.framework import requiresCUDA |
| 21 | + |
| 22 | + |
| 23 | +@requiresCUDA |
| 24 | +@pytest.mark.parametrize("model_id", hf_diffusers_unet2d_condition_model_ids) |
| 25 | +def test_hf_diffusers(model_id): |
| 26 | + from thunder.dynamo import thunderfx |
| 27 | + from diffusers import UNet2DConditionModel |
| 28 | + |
| 29 | + unet_config = UNet2DConditionModel.load_config(model_id, subfolder="unet", torch_dtype=torch.bfloat16) |
| 30 | + unet = UNet2DConditionModel(unet_config) |
| 31 | + in_channels = unet.config.in_channels |
| 32 | + cross_attention_dim = unet.config.cross_attention_dim |
| 33 | + addition_embed_type = unet.config.addition_embed_type |
| 34 | + |
| 35 | + sample_size = 4 |
| 36 | + batch_size = 1 |
| 37 | + seq_length = 4 |
| 38 | + |
| 39 | + if "xl" in model_id: |
| 40 | + time_ids_dim = 6 |
| 41 | + text_embeds_dim = 4 |
| 42 | + if "refiner" in model_id: |
| 43 | + time_ids_dim = 2 |
| 44 | + text_embeds_dim = 4 |
| 45 | + else: |
| 46 | + time_ids_dim = None |
| 47 | + text_embeds_dim = None |
| 48 | + |
| 49 | + input_shape = (batch_size, in_channels, sample_size, sample_size) |
| 50 | + hidden_states_shape = (batch_size, seq_length, cross_attention_dim) |
| 51 | + |
| 52 | + unet = unet.to("cuda", dtype=torch.bfloat16).requires_grad_(True) |
| 53 | + compiled_model = thunderfx(unet) |
| 54 | + |
| 55 | + def make_inputs(dtype=torch.bfloat16): |
| 56 | + added_cond_kwargs = {} |
| 57 | + with torch.device("cuda"): |
| 58 | + input = torch.randn(input_shape, dtype=dtype) |
| 59 | + hidden_states = torch.randn(hidden_states_shape, dtype=dtype) |
| 60 | + timestep = torch.ones(batch_size, dtype=torch.long) |
| 61 | + if addition_embed_type is not None: |
| 62 | + assert text_embeds_dim is not None and time_ids_dim is not None |
| 63 | + time_ids_shape = (batch_size, time_ids_dim) |
| 64 | + text_embeds_shape = (batch_size, text_embeds_dim) |
| 65 | + added_cond_kwargs["time_ids"] = torch.randn(time_ids_shape, device="cuda", dtype=dtype) |
| 66 | + added_cond_kwargs["text_embeds"] = torch.randn(text_embeds_shape, device="cuda", dtype=dtype) |
| 67 | + return (input, timestep, hidden_states), {"added_cond_kwargs": added_cond_kwargs} |
| 68 | + |
| 69 | + compiled_args, compiled_kwargs = make_inputs(torch.bfloat16) |
| 70 | + compiled_output = compiled_model(*compiled_args, **compiled_kwargs) |
| 71 | + |
| 72 | + ref_output = unet(*compiled_args, **compiled_kwargs) |
| 73 | + |
| 74 | + ref_output = ref_output.sample |
| 75 | + compiled_output = compiled_output.sample |
| 76 | + |
| 77 | + torch.testing.assert_close(compiled_output, ref_output, rtol=1e-2, atol=2e-1) |
| 78 | + |
| 79 | + # TODO: Currently fails, needs investigation https://github.com/Lightning-AI/lightning-thunder/issues/2153 |
| 80 | + # loss_grad = torch.randn_like(compiled_output) |
| 81 | + # grads_ref = torch.autograd.grad(ref_output, unet.parameters(), grad_outputs=loss_grad) |
| 82 | + # grads_compiled = torch.autograd.grad(compiled_output, unet.parameters(), grad_outputs=loss_grad) |
| 83 | + # torch.testing.assert_close(grads_ref, grads_compiled, rtol=1e-1, atol=1e-1) |
0 commit comments