Skip to content

refactor rotary embedding 3: so it is not on cpu - #9307

Merged
sayakpaul merged 2 commits into
mainfrom
fix-torch-rope
Aug 29, 2024
Merged

refactor rotary embedding 3: so it is not on cpu#9307
sayakpaul merged 2 commits into
mainfrom
fix-torch-rope

Conversation

@yiyixuxu

@yiyixuxuyiyixuxu commented Aug 28, 2024

Copy link
Copy Markdown
Collaborator

@HuggingFaceDocBuilderDev

Copy link
Copy Markdown

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

@yiyixuxuyiyixuxu changed the title refactor rotary embedding so it is not on cpurefactor rotary embedding 3: so it is not on cpuAug 29, 2024

@sayakpaulsayakpaul left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@yiyixuxu possible to trigger a torch.compile() with PyTorch nightly to verify if this helps with the CUDAGraph issue? Code is in #9299 (comment).

Ccing @cpuhrsch maybe you would like to review it?

@yiyixuxu

Copy link
Copy Markdown
CollaboratorAuthor

@sayakpaul yeah tested it is fine

@sayakpaul
sayakpaul merged commit 61d96c3 into mainAug 29, 2024
@sayakpaul
sayakpaul deleted the fix-torch-rope branch August 29, 2024 19:37
@yiyixuxu

Copy link
Copy Markdown
CollaboratorAuthor

@sayakpaul
Is this a reasonable script? I want to compare the performance against 0.30.1-patch before we introduce the rotary embedding refractor

importtorchimporttorch.utils.benchmarkasbenchmarkimportgcimporttimetorch.set_float32_matmul_precision("high")
torch._inductor.conv_1x1_as_mm=Truetorch._inductor.coordinate_descent_tuning=Truetorch._inductor.epilogue_fusion=Falsetorch._inductor.coordinate_descent_check_all_directions=Trueimportdiffusersfromplatformimportpython_versionfromdiffusersimportDiffusionPipelineprint(diffusers.__version__)
print(torch.__version__)
print(python_version())
defbenchmark_fn(f, *args, **kwargs):
t0=benchmark.Timer(
stmt="f(*args, **kwargs)",
globals={"args": args, "kwargs": kwargs, "f": f},
num_threads=torch.get_num_threads(),
)
returnf"{(t0.blocked_autorange().mean):.3f}"defbytes_to_giga_bytes(bytes):
returnf"{(bytes/1024/1024/1024):.3f}"defflush():
"""Wipes off memory."""gc.collect()
torch.cuda.empty_cache()
torch.cuda.reset_max_memory_allocated()
torch.cuda.reset_peak_memory_stats()
pipe=DiffusionPipeline.from_pretrained("black-forest-labs/FLUX.1-dev", text_encoder=None, text_encoder_2=None, torch_dtype=torch.bfloat16).to("cuda")
pipe.transformer.to(memory_format=torch.channels_last)
pipe.vae.to(memory_format=torch.channels_last)
pipe.transformer=torch.compile(pipe.transformer, mode="max-autotune", fullgraph=True)
pipe.vae.decode=torch.compile(pipe.vae.decode, mode="max-autotune", fullgraph=True)
prompt_embeds=torch.load("flux_prompt_embeds.pt")
pooled_prompt_embeds=torch.load("flux_pooled_prompt_embeds.pt")
defrun_inference(pipe):
_=pipe(
prompt_embeds=prompt_embeds,
pooled_prompt_embeds=pooled_prompt_embeds,
num_inference_steps=5,
guidance_scale=3.5,
max_sequence_length=512,
generator=torch.manual_seed(42),
height=1024,
width=1024,
)
flush()
time=benchmark_fn(run_inference)
memory=bytes_to_giga_bytes(torch.cuda.max_memory_allocated()) # in GBs.print(f" Execution time: {time} sec")
print(f" Memory: {memory} gib")

freqs = 1.0 / (theta ** (torch.arange(0, dim, 2, dtype=freqs_dtype)[: (dim // 2)] / dim)) / linear_factor # [D/2]
t = torch.from_numpy(pos).to(freqs.device) # type: ignore # [S]
freqs = torch.outer(t, freqs) # type: ignore # [S, D/2]
freqs = freqs.to(pos.device)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd expect this to cause a sync as well since by default arange allocates on the CPU. One way to mitigate could be to
a) use pin_memory() on freqs ahead of time and set non_blocking=True
b) do arange on the GPU right away (i.e. torch.arange([...], device=pos.device)).

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ohhh let's do torch.arange([...], device=pos.device)

@sayakpaul

Copy link
Copy Markdown
Member

@yiyixuxu that looks reasonable but I'd call run_inference() maybe 2/3 times for warmups.


if isinstance(pos, int):
pos = np.arange(pos)
pos = torch.arange(pos)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should also be passed a device argument to allocate it on the GPU. If this isn't on the GPU, then neither will the following Tensors.

sayakpaul pushed a commit that referenced this pull request Dec 23, 2024
change get_1d_rotary to accept pos as torch tensors
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CUDAGRAPHs for Flux position embeddings

4 participants

@yiyixuxu@HuggingFaceDocBuilderDev@sayakpaul@cpuhrsch