cbensimon HF Staff commited on
Commit
d0dbaba
·
verified ·
1 Parent(s): 325c731

Upload folder using huggingface_hub

Browse files
.gitattributes CHANGED
@@ -33,3 +33,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ package/single_transformer_blocks/package.pt2 filter=lfs diff=lfs merge=lfs -text
37
+ package/transformer_blocks/package.pt2 filter=lfs diff=lfs merge=lfs -text
38
+ samples/after/edited.png filter=lfs diff=lfs merge=lfs -text
39
+ samples/before/edited.png filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ ---
3
+ tags:
4
+ - ahead-of-time
5
+ - pytorch
6
+ library_name: diffusers
7
+ ---
8
+
9
+ > [!NOTE]
10
+ > This **README** has been auto-generated by the **HF Job** run linked below
11
+ > and the whole repository is a reproducible artifact of this Job
12
+
13
+ # Ahead-of-time repository
14
+
15
+ AoT repos contain **pre-compiled binaries** of PyTorch models, enabling:
16
+ - fast startup times (no `torch.compile` needed)
17
+ - significant **speedup**
18
+ - **ZeroGPU** compatibility
19
+
20
+ ## How to use
21
+ ``` python
22
+
23
+ import spaces
24
+ import torch
25
+ from diffusers.pipelines.flux2.pipeline_flux2_klein import Flux2KleinPipeline
26
+
27
+ pipeline = Flux2KleinPipeline.from_pretrained(
28
+ 'black-forest-labs/FLUX.2-klein-4B',
29
+ torch_dtype=torch.bfloat16
30
+ ).to('cuda')
31
+
32
+ spaces.aoti_load(
33
+ module=pipeline.transformer,
34
+ repo_id='cbensimon/FLUX.2-klein-4B-sm90-cu128-glibc235-r02',
35
+ )
36
+ ```
37
+
38
+ ## How to reproduce or customize
39
+ ``` bash
40
+ # Install hf CLI
41
+ curl -LsSf https://hf.co/cli/install.sh | bash
42
+
43
+ # Login
44
+ hf auth login
45
+
46
+ # Get the job file and edit (user section) if needed
47
+ hf download cbensimon/FLUX.2-klein-4B-sm90-cu128-glibc235-r02 job.py
48
+
49
+ # Run the job and change flavor or image if needed
50
+ hf jobs uv run job.py \
51
+ --flavor h200 \
52
+ --image pytorch/pytorch:2.9.1-cuda12.8-cudnn9-devel \
53
+ --secrets HF_TOKEN
54
+ ```
55
+
56
+ The following job [environment variables](https://hf.co/docs/hub/en/jobs-configuration#user-defined-environment-variables)
57
+ can be used to customize the repo name generation:
58
+ - `OUTPUT_REPO_NAMESPACE`: taken from `HF_TOKEN` otherwise
59
+ - `OUTPUT_REPO_BASE_NAME`: defaults to `module` class name
60
+ - `OUTPUT_REPO_ID`: fully overtakes name generation
61
+
62
+ ## Samples
63
+
64
+ Generated as part of the compilation job: before and after compilation
65
+
66
+ | Before compilation (10.19s) | After compilation (7.62s) |
67
+ |------------------------------------------------|----------------------------------------------|
68
+ | ![edited.png](https://huggingface.co/cbensimon/FLUX.2-klein-4B-sm90-cu128-glibc235-r02/resolve/main/samples/before/edited.png) | ![edited.png](https://huggingface.co/cbensimon/FLUX.2-klein-4B-sm90-cu128-glibc235-r02/resolve/main/samples/after/edited.png) |
69
+
70
+ Speedup: **1.34x**
71
+ (note that this might not always reflect actual performance gain)
72
+
73
+ ## Environment
74
+ <details>
75
+ <summary>Click to expand</summary>
76
+
77
+ ```
78
+ PyTorch version: 2.9.1+cu128
79
+ Is debug build: False
80
+ CUDA used to build PyTorch: 12.8
81
+ ROCM used to build PyTorch: N/A
82
+
83
+ OS: Ubuntu 22.04.5 LTS (x86_64)
84
+ GCC version: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
85
+ Clang version: Could not collect
86
+ CMake version: version 4.1.2
87
+ Libc version: glibc-2.35
88
+
89
+ Python version: 3.10.0 (default, Oct 18 2021, 02:11:22) [Clang 13.0.0 ] (64-bit runtime)
90
+ Python platform: Linux-6.12.64-87.122.amzn2023.x86_64-x86_64-with-glibc2.35
91
+ Is CUDA available: True
92
+ CUDA runtime version: 12.8.93
93
+ CUDA_MODULE_LOADING set to:
94
+ GPU models and configuration: GPU 0: NVIDIA H200
95
+ Nvidia driver version: 580.126.09
96
+ cuDNN version: Could not collect
97
+ Is XPU available: False
98
+ HIP runtime version: N/A
99
+ MIOpen runtime version: N/A
100
+ Is XNNPACK available: True
101
+
102
+ CPU:
103
+ Architecture: x86_64
104
+ CPU op-mode(s): 32-bit, 64-bit
105
+ Address sizes: 46 bits physical, 48 bits virtual
106
+ Byte Order: Little Endian
107
+ CPU(s): 192
108
+ On-line CPU(s) list: 0-191
109
+ Vendor ID: GenuineIntel
110
+ Model name: Intel(R) Xeon(R) Platinum 8488C
111
+ CPU family: 6
112
+ Model: 143
113
+ Thread(s) per core: 2
114
+ Core(s) per socket: 48
115
+ Socket(s): 2
116
+ Stepping: 8
117
+ BogoMIPS: 4800.00
118
+ Flags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq monitor ssse3 fma cx16 pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch ssbd ibrs ibpb stibp ibrs_enhanced fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves avx_vnni avx512_bf16 wbnoinvd ida arat avx512vbmi umip pku ospke waitpkg avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg tme avx512_vpopcntdq rdpid cldemote movdiri movdir64b md_clear serialize amx_bf16 avx512_fp16 amx_tile amx_int8 flush_l1d arch_capabilities
119
+ Hypervisor vendor: KVM
120
+ Virtualization type: full
121
+ L1d cache: 4.5 MiB (96 instances)
122
+ L1i cache: 3 MiB (96 instances)
123
+ L2 cache: 192 MiB (96 instances)
124
+ L3 cache: 210 MiB (2 instances)
125
+ NUMA node(s): 2
126
+ NUMA node0 CPU(s): 0-47,96-143
127
+ NUMA node1 CPU(s): 48-95,144-191
128
+ Vulnerability Gather data sampling: Not affected
129
+ Vulnerability Indirect target selection: Not affected
130
+ Vulnerability Itlb multihit: Not affected
131
+ Vulnerability L1tf: Not affected
132
+ Vulnerability Mds: Not affected
133
+ Vulnerability Meltdown: Not affected
134
+ Vulnerability Mmio stale data: Not affected
135
+ Vulnerability Reg file data sampling: Not affected
136
+ Vulnerability Retbleed: Not affected
137
+ Vulnerability Spec rstack overflow: Not affected
138
+ Vulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl
139
+ Vulnerability Spectre v1: Mitigation; usercopy/swapgs barriers and __user pointer sanitization
140
+ Vulnerability Spectre v2: Mitigation; Enhanced / Automatic IBRS; IBPB conditional; PBRSB-eIBRS SW sequence; BHI BHI_DIS_S
141
+ Vulnerability Srbds: Not affected
142
+ Vulnerability Tsa: Not affected
143
+ Vulnerability Tsx async abort: Not affected
144
+ Vulnerability Vmscape: Not affected
145
+
146
+ Versions of relevant libraries:
147
+ [pip3] Could not collect
148
+ [conda] numpy 2.3.4 py311h2e04523_0 conda-forge
149
+ [conda] nvidia-cublas-cu12 12.8.4.1 pypi_0 pypi
150
+ [conda] nvidia-cuda-cupti-cu12 12.8.90 pypi_0 pypi
151
+ [conda] nvidia-cuda-nvrtc-cu12 12.8.93 pypi_0 pypi
152
+ [conda] nvidia-cuda-runtime-cu12 12.8.90 pypi_0 pypi
153
+ [conda] nvidia-cudnn-cu12 9.10.2.21 pypi_0 pypi
154
+ [conda] nvidia-cufft-cu12 11.3.3.83 pypi_0 pypi
155
+ [conda] nvidia-curand-cu12 10.3.9.90 pypi_0 pypi
156
+ [conda] nvidia-cusolver-cu12 11.7.3.90 pypi_0 pypi
157
+ [conda] nvidia-cusparse-cu12 12.5.8.93 pypi_0 pypi
158
+ [conda] nvidia-cusparselt-cu12 0.7.1 pypi_0 pypi
159
+ [conda] nvidia-nccl-cu12 2.27.5 pypi_0 pypi
160
+ [conda] nvidia-nvjitlink-cu12 12.8.93 pypi_0 pypi
161
+ [conda] nvidia-nvtx-cu12 12.8.90 pypi_0 pypi
162
+ [conda] optree 0.17.0 pypi_0 pypi
163
+ [conda] torch 2.9.1+cu128 pypi_0 pypi
164
+ [conda] torchaudio 2.9.1+cu128 pypi_0 pypi
165
+ [conda] torchelastic 0.2.2 pypi_0 pypi
166
+ [conda] torchvision 0.24.1+cu128 pypi_0 pypi
167
+ [conda] triton 3.5.1 pypi_0 pypi
168
+ ```
169
+ </details>
170
+
171
+ ## Job run
172
+ - [cbensimon/69cfe0474adb81dd2de74621](https://huggingface.co/jobs/cbensimon/69cfe0474adb81dd2de74621)
environment.json ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "torch_version": "2.9.1+cu128",
3
+ "is_debug_build": "False",
4
+ "cuda_compiled_version": "12.8",
5
+ "gcc_version": "(Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0",
6
+ "clang_version": null,
7
+ "cmake_version": "version 4.1.2",
8
+ "os": "Ubuntu 22.04.5 LTS (x86_64)",
9
+ "libc_version": "glibc-2.35",
10
+ "python_version": "3.10.0 (default, Oct 18 2021, 02:11:22) [Clang 13.0.0 ] (64-bit runtime)",
11
+ "python_platform": "Linux-6.12.64-87.122.amzn2023.x86_64-x86_64-with-glibc2.35",
12
+ "is_cuda_available": "True",
13
+ "cuda_runtime_version": "12.8.93",
14
+ "cuda_module_loading": "",
15
+ "nvidia_driver_version": "580.126.09",
16
+ "nvidia_gpu_models": "GPU 0: NVIDIA H200",
17
+ "cudnn_version": null,
18
+ "is_xpu_available": "False",
19
+ "pip_version": "pip3",
20
+ "pip_packages": null,
21
+ "conda_packages": "numpy 2.3.4 py311h2e04523_0 conda-forge\nnvidia-cublas-cu12 12.8.4.1 pypi_0 pypi\nnvidia-cuda-cupti-cu12 12.8.90 pypi_0 pypi\nnvidia-cuda-nvrtc-cu12 12.8.93 pypi_0 pypi\nnvidia-cuda-runtime-cu12 12.8.90 pypi_0 pypi\nnvidia-cudnn-cu12 9.10.2.21 pypi_0 pypi\nnvidia-cufft-cu12 11.3.3.83 pypi_0 pypi\nnvidia-curand-cu12 10.3.9.90 pypi_0 pypi\nnvidia-cusolver-cu12 11.7.3.90 pypi_0 pypi\nnvidia-cusparse-cu12 12.5.8.93 pypi_0 pypi\nnvidia-cusparselt-cu12 0.7.1 pypi_0 pypi\nnvidia-nccl-cu12 2.27.5 pypi_0 pypi\nnvidia-nvjitlink-cu12 12.8.93 pypi_0 pypi\nnvidia-nvtx-cu12 12.8.90 pypi_0 pypi\noptree 0.17.0 pypi_0 pypi\ntorch 2.9.1+cu128 pypi_0 pypi\ntorchaudio 2.9.1+cu128 pypi_0 pypi\ntorchelastic 0.2.2 pypi_0 pypi\ntorchvision 0.24.1+cu128 pypi_0 pypi\ntriton 3.5.1 pypi_0 pypi",
22
+ "hip_compiled_version": "N/A",
23
+ "hip_runtime_version": "N/A",
24
+ "miopen_runtime_version": "N/A",
25
+ "caching_allocator_config": "",
26
+ "is_xnnpack_available": "True",
27
+ "cpu_info": "Architecture: x86_64\nCPU op-mode(s): 32-bit, 64-bit\nAddress sizes: 46 bits physical, 48 bits virtual\nByte Order: Little Endian\nCPU(s): 192\nOn-line CPU(s) list: 0-191\nVendor ID: GenuineIntel\nModel name: Intel(R) Xeon(R) Platinum 8488C\nCPU family: 6\nModel: 143\nThread(s) per core: 2\nCore(s) per socket: 48\nSocket(s): 2\nStepping: 8\nBogoMIPS: 4800.00\nFlags: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq monitor ssse3 fma cx16 pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch ssbd ibrs ibpb stibp ibrs_enhanced fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves avx_vnni avx512_bf16 wbnoinvd ida arat avx512vbmi umip pku ospke waitpkg avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg tme avx512_vpopcntdq rdpid cldemote movdiri movdir64b md_clear serialize amx_bf16 avx512_fp16 amx_tile amx_int8 flush_l1d arch_capabilities\nHypervisor vendor: KVM\nVirtualization type: full\nL1d cache: 4.5 MiB (96 instances)\nL1i cache: 3 MiB (96 instances)\nL2 cache: 192 MiB (96 instances)\nL3 cache: 210 MiB (2 instances)\nNUMA node(s): 2\nNUMA node0 CPU(s): 0-47,96-143\nNUMA node1 CPU(s): 48-95,144-191\nVulnerability Gather data sampling: Not affected\nVulnerability Indirect target selection: Not affected\nVulnerability Itlb multihit: Not affected\nVulnerability L1tf: Not affected\nVulnerability Mds: Not affected\nVulnerability Meltdown: Not affected\nVulnerability Mmio stale data: Not affected\nVulnerability Reg file data sampling: Not affected\nVulnerability Retbleed: Not affected\nVulnerability Spec rstack overflow: Not affected\nVulnerability Spec store bypass: Mitigation; Speculative Store Bypass disabled via prctl\nVulnerability Spectre v1: Mitigation; usercopy/swapgs barriers and __user pointer sanitization\nVulnerability Spectre v2: Mitigation; Enhanced / Automatic IBRS; IBPB conditional; PBRSB-eIBRS SW sequence; BHI BHI_DIS_S\nVulnerability Srbds: Not affected\nVulnerability Tsa: Not affected\nVulnerability Tsx async abort: Not affected\nVulnerability Vmscape: Not affected"
28
+ }
job.py ADDED
@@ -0,0 +1,419 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # /// script
2
+ # requires-python = "==3.10"
3
+ # dependencies = [
4
+ # "spaces==0.49b5",
5
+ # "torch==2.9.1",
6
+ # "torchvision",
7
+ # "diffusers==0.37.1",
8
+ # "huggingface_hub==1.8.0",
9
+ # "transformers",
10
+ # "accelerate",
11
+ # "setuptools",
12
+ # ]
13
+ # ///
14
+ # fmt: off
15
+
16
+
17
+ # =========================
18
+ # User section
19
+ # =========================
20
+
21
+ # README::MODEL_INIT::START
22
+ import spaces
23
+ import torch
24
+ from diffusers.pipelines.flux2.pipeline_flux2_klein import Flux2KleinPipeline
25
+
26
+ pipeline = Flux2KleinPipeline.from_pretrained(
27
+ 'black-forest-labs/FLUX.2-klein-4B',
28
+ torch_dtype=torch.bfloat16
29
+ ).to('cuda')
30
+ # README::MODEL_INIT::END
31
+
32
+
33
+ TRANSFORMER_IMAGE_DIM = torch.export.Dim('image_seq_length', min=4096, max=16384) # min: 0 images, max: 3 (1024x1024) images
34
+
35
+ TRANSFORMER_DYNAMIC_SHAPES = {
36
+ 'transformer_blocks': {
37
+ 'hidden_states': {
38
+ 1: TRANSFORMER_IMAGE_DIM,
39
+ },
40
+ 'image_rotary_emb': (
41
+ {0: TRANSFORMER_IMAGE_DIM + 512},
42
+ {0: TRANSFORMER_IMAGE_DIM + 512},
43
+ ),
44
+ },
45
+ 'single_transformer_blocks': {
46
+ 'hidden_states': {
47
+ 1: TRANSFORMER_IMAGE_DIM + 512,
48
+ },
49
+ 'image_rotary_emb': (
50
+ {0: TRANSFORMER_IMAGE_DIM + 512},
51
+ {0: TRANSFORMER_IMAGE_DIM + 512},
52
+ ),
53
+ },
54
+ }
55
+
56
+ INDUCTOR_CONFIGS = {
57
+ 'conv_1x1_as_mm': True,
58
+ 'epilogue_fusion': False,
59
+ 'coordinate_descent_tuning': True,
60
+ 'coordinate_descent_check_all_directions': True,
61
+ 'max_autotune': True,
62
+ 'triton.cudagraphs': True,
63
+ }
64
+
65
+
66
+ def compile_and_save(module: torch.nn.Module, package_dir: str):
67
+ from PIL import Image
68
+ from torch.utils._pytree import tree_map
69
+
70
+ for submodule in (
71
+ 'transformer_blocks',
72
+ 'single_transformer_blocks',
73
+ ):
74
+ block = module.get_submodule(submodule)[0]
75
+ with spaces.aoti_capture(block) as call:
76
+ pipeline(
77
+ prompt="prompt",
78
+ image=[Image.new("RGB", (1024, 1024))],
79
+ )
80
+ dynamic_shapes = tree_map(lambda t: None, call.kwargs)
81
+ dynamic_shapes |= TRANSFORMER_DYNAMIC_SHAPES[submodule]
82
+ with torch.no_grad():
83
+ exported = torch.export.export(
84
+ mod=block,
85
+ args=call.args,
86
+ kwargs=call.kwargs,
87
+ dynamic_shapes=dynamic_shapes,
88
+ )
89
+ spaces.aoti_compile_and_save(
90
+ package_dir=package_dir,
91
+ exported_program=exported,
92
+ inductor_configs=INDUCTOR_CONFIGS,
93
+ submodule=submodule,
94
+ )
95
+
96
+
97
+ def generate_samples(samples_dir: str):
98
+ from diffusers.utils.loading_utils import load_image
99
+ output = pipeline(
100
+ prompt="Remove the sunglasses",
101
+ image=load_image('https://hf.co/datasets/huggingface/documentation-images/resolve/main/diffusers/wan-cat.jpg'),
102
+ guidance_scale=2.5,
103
+ generator=torch.Generator(device='cuda').manual_seed(42),
104
+ )
105
+ output.images[0].save(f'{samples_dir}/edited.png')
106
+
107
+
108
+ def main():
109
+ create_aoti_repo(
110
+ module=pipeline.transformer,
111
+ module_expr='pipeline.transformer',
112
+ compile_and_save=compile_and_save,
113
+ generate_samples=generate_samples,
114
+ )
115
+
116
+
117
+ # =========================
118
+ # Internal (avoid editing)
119
+ # =========================
120
+
121
+
122
+ import inspect
123
+ import json
124
+ import os
125
+ import platform
126
+ import random
127
+ import shutil
128
+ import sys
129
+ import time
130
+ from pathlib import Path
131
+ from tempfile import TemporaryDirectory
132
+ from typing import Callable
133
+
134
+ import huggingface_hub as hf
135
+ from requests.exceptions import HTTPError
136
+
137
+
138
+ def create_aoti_repo(
139
+ module: torch.nn.Module,
140
+ module_expr: str,
141
+ compile_and_save: Callable[[torch.nn.Module, str], None],
142
+ generate_samples: Callable[[str], None],
143
+ aoti_loader: Callable[[torch.nn.Module, str], None] | None = None,
144
+ ):
145
+ """
146
+ Compile a PyTorch module Ahead-of-Time and publish it to a Hugging Face Hub repository.
147
+
148
+ This function orchestrates the following process by using the passed handlers:
149
+ - generates output samples
150
+ - compile the module and save it
151
+ - load the compiled version (mutates the module)
152
+ - generates output samples again (meaning after compilation)
153
+ - creates a README + other context files
154
+ - uploads everything to the Hub
155
+
156
+ Parameters
157
+ ----------
158
+ module:
159
+ Module to compile (e.g. `pipeline.transformer`).
160
+
161
+ module_expr:
162
+ String representation used in generated README code.
163
+
164
+ compile_and_save:
165
+ Callable with signature `(module: torch.nn.Module, package_dir: str) -> None`.
166
+ Must AoT compile `module` (without mutating) to `package_dir` using `spaces.aoti_compile_and_save`
167
+
168
+ generate_samples:
169
+ Callable with signature `(samples_dir: str) -> None`.
170
+ Must generate samples from the model (e.g. `pipeline`) and save them inside `samples_dir`
171
+
172
+ aoti_loader:
173
+ Callable with signature `(module: torch.nn.Module, package_dir: str) -> None`.
174
+ Optional custom loader passed to `spaces.aoti_load`.
175
+ Defaults to `spaces.aoti_load_from_package_dir`
176
+ """
177
+
178
+ HUB_URL = 'https://huggingface.co'
179
+
180
+ user = hf.whoami()['name']
181
+ job_id = os.environ['JOB_ID']
182
+ job_info = hf.inspect_job(job_id=job_id)
183
+ env_info = torch.utils.collect_env.get_env_info()
184
+ library_name, config = _get_library_config(module)
185
+ output_repo_id = _create_empty_repo(user, module, env_info.cuda_runtime_version)
186
+
187
+ print(f"Created empty repo: {HUB_URL}/{output_repo_id}")
188
+
189
+ # README: how-to-use
190
+ model_init_region = (inspect.getsource(sys.modules['__main__'])
191
+ .split('\n# README::MODEL_INIT::START')[1]
192
+ .split('\n# README::MODEL_INIT::END')[0]
193
+ )
194
+ aoti_load_readme = spaces.aoti_load_call_source(
195
+ module_expr=module_expr,
196
+ repo_id=output_repo_id,
197
+ aoti_loader=aoti_loader,
198
+ )
199
+
200
+ with TemporaryDirectory() as tempdir:
201
+ tempdir = Path(tempdir)
202
+
203
+ # Structure
204
+ readme_path = tempdir / 'README.md'
205
+ package_dir = tempdir / 'package'
206
+ samples_before_dir = tempdir / 'samples' / 'before'
207
+ samples_after_dir = tempdir / 'samples' / 'after'
208
+ environment_path = tempdir / 'environment.json'
209
+ config_path = tempdir / 'module_config.json'
210
+
211
+ # Samples before compile
212
+ samples_before_dir.mkdir(parents=True)
213
+ t0 = time.perf_counter()
214
+ generate_samples(str(samples_before_dir))
215
+ generate_before_dt = time.perf_counter() - t0
216
+
217
+ # Compile and load
218
+ package_dir.mkdir(parents=True)
219
+ compile_and_save(module, str(package_dir))
220
+ if aoti_loader is not None:
221
+ aoti_loader(module, str(package_dir))
222
+ else:
223
+ spaces.aoti_load_from_package_dir(module, package_dir)
224
+
225
+ # Samples after compile
226
+ samples_after_dir.mkdir(parents=True)
227
+ t0 = time.perf_counter()
228
+ generate_samples(str(samples_after_dir))
229
+ generate_after_dt = time.perf_counter() - t0
230
+
231
+ # Environment and config dump
232
+ environment_path.write_text(json.dumps(env_info._asdict(), indent=4))
233
+ if config is not None:
234
+ config_path.write_text(json.dumps(config, indent=4))
235
+
236
+ # README.md
237
+ def get_link(path: Path):
238
+ kind = 'tree' if path.is_dir() else 'resolve'
239
+ return f'{HUB_URL}/{output_repo_id}/{kind}/main/{path.relative_to(tempdir)}'
240
+ readme_path.write_text(_readme_template(
241
+ model_init=model_init_region,
242
+ aoti_load=aoti_load_readme,
243
+ repo_id=output_repo_id,
244
+ job_id=f'{user}/{job_id}',
245
+ job_image=job_info.docker_image,
246
+ job_flavor=job_info.flavor,
247
+ environment=torch.utils.collect_env.pretty_str(env_info),
248
+ library_name=library_name,
249
+ generate_before_dt=generate_before_dt,
250
+ generate_after_dt=generate_after_dt,
251
+ samples_before_urls=[get_link(path) for path in samples_before_dir.iterdir()],
252
+ samples_after_urls=[get_link(path) for path in samples_after_dir.iterdir()],
253
+ ))
254
+
255
+ # Self include
256
+ shutil.copyfile(__file__, tempdir / 'job.py')
257
+
258
+ # Push to hub
259
+ hf.upload_folder(repo_id=output_repo_id, folder_path=tempdir)
260
+ print(f"AoT repository successfully created at: {HUB_URL}/{output_repo_id}")
261
+
262
+
263
+ def _create_empty_repo(
264
+ user: str,
265
+ module: torch.nn.Module,
266
+ cuda_runtime_version: str,
267
+ max_attempts: int = 10
268
+ ):
269
+ for _ in range(max_attempts):
270
+ output_repo_id = _get_repo_id(user, module, cuda_runtime_version)
271
+ try:
272
+ hf.create_repo(output_repo_id)
273
+ except HTTPError as err:
274
+ if err.response.status_code != 409:
275
+ raise
276
+ else:
277
+ return output_repo_id
278
+ raise AssertionError
279
+
280
+
281
+ def _get_repo_id(
282
+ user: str,
283
+ module: torch.nn.Module,
284
+ cuda_runtime_version: str,
285
+ ):
286
+ if (repo_id := os.getenv('OUTPUT_REPO_ID')) is not None:
287
+ return repo_id
288
+ namespace = os.getenv('OUTPUT_REPO_NAMESPACE', user)
289
+ base_name = os.getenv('OUTPUT_REPO_BASE_NAME', module.__class__.__name__)
290
+ sm = ''.join(map(str, torch.cuda.get_device_capability()))
291
+ cu = ''.join(cuda_runtime_version.split('.')[:2])
292
+ glibc = platform.libc_ver()[1].replace('.', '')
293
+ rnd = random.randbytes(1).hex()
294
+ return f'{namespace}/{base_name}-sm{sm}-cu{cu}-glibc{glibc}-r{rnd}'
295
+
296
+
297
+ def _get_library_config(module: torch.nn.Module):
298
+ if (config := getattr(module, 'config', None)) is None:
299
+ return None, None
300
+ if callable(getattr(config, 'to_dict', None)):
301
+ config_dict = config.to_dict()
302
+ elif isinstance(getattr(config, '__dict__', None), dict):
303
+ config_dict = config.__dict__
304
+ else:
305
+ return None, None
306
+ if 'transformers_version' in config_dict:
307
+ library_name = 'transformers'
308
+ elif '_diffusers_version' in config_dict:
309
+ library_name = 'diffusers'
310
+ else:
311
+ library_name = 'unknown'
312
+ return library_name, config_dict
313
+
314
+
315
+ def _readme_template(
316
+ model_init: str,
317
+ aoti_load: str,
318
+ repo_id: str,
319
+ job_id: str,
320
+ job_image: str | None,
321
+ job_flavor: str | None,
322
+ environment: str,
323
+ library_name: str | None,
324
+ generate_before_dt: float,
325
+ generate_after_dt: float,
326
+ samples_before_urls: list[str],
327
+ samples_after_urls: list[str],
328
+ ):
329
+ NEWLINE = '\n'
330
+ IMAGE_EXTS = ('.png', '.webp', '.jpg', '.jpeg', '.gif')
331
+ VIDEO_EXTS = ('.mp4', '.webm', '.mov')
332
+
333
+ def media_cell(url: str):
334
+ name = url.split('/')[-1]
335
+ if name.endswith(IMAGE_EXTS):
336
+ return f'![{name}]({url})'
337
+ if name.endswith(VIDEO_EXTS):
338
+ return f'<video src="{url}" controls></video>'
339
+ return f'[{name}]({url})'
340
+
341
+ return f"""
342
+ ---
343
+ tags:
344
+ - ahead-of-time
345
+ - pytorch
346
+ library_name: {library_name or 'pytorch'}
347
+ ---
348
+
349
+ > [!NOTE]
350
+ > This **README** has been auto-generated by the **HF Job** run linked below
351
+ > and the whole repository is a reproducible artifact of this Job
352
+
353
+ # Ahead-of-time repository
354
+
355
+ AoT repos contain **pre-compiled binaries** of PyTorch models, enabling:
356
+ - fast startup times (no `torch.compile` needed)
357
+ - significant **speedup**
358
+ - **ZeroGPU** compatibility
359
+
360
+ ## How to use
361
+ ``` python
362
+ {model_init}\n
363
+ {aoti_load}
364
+ ```
365
+
366
+ ## How to reproduce or customize
367
+ ``` bash
368
+ # Install hf CLI
369
+ curl -LsSf https://hf.co/cli/install.sh | bash
370
+
371
+ # Login
372
+ hf auth login
373
+
374
+ # Get the job file and edit (user section) if needed
375
+ hf download {repo_id} job.py
376
+
377
+ # Run the job and change flavor or image if needed
378
+ hf jobs uv run job.py \\
379
+ --flavor {job_flavor or '<unknown>'} \\
380
+ --image {job_image or '<unknown>'} \\
381
+ --secrets HF_TOKEN
382
+ ```
383
+
384
+ The following job [environment variables](https://hf.co/docs/hub/en/jobs-configuration#user-defined-environment-variables)
385
+ can be used to customize the repo name generation:
386
+ - `OUTPUT_REPO_NAMESPACE`: taken from `HF_TOKEN` otherwise
387
+ - `OUTPUT_REPO_BASE_NAME`: defaults to `module` class name
388
+ - `OUTPUT_REPO_ID`: fully overtakes name generation
389
+
390
+ ## Samples
391
+
392
+ Generated as part of the compilation job: before and after compilation
393
+
394
+ | Before compilation ({generate_before_dt:.2f}s) | After compilation ({generate_after_dt:.2f}s) |
395
+ |------------------------------------------------|----------------------------------------------|
396
+ {NEWLINE.join(
397
+ f"| {media_cell(before_url)} | {media_cell(after_url)} |"
398
+ for before_url, after_url in zip(samples_before_urls, samples_after_urls)
399
+ )}
400
+
401
+ Speedup: **{generate_before_dt/generate_after_dt:.2f}x**
402
+ (note that this might not always reflect actual performance gain)
403
+
404
+ ## Environment
405
+ <details>
406
+ <summary>Click to expand</summary>
407
+
408
+ ```
409
+ {environment}
410
+ ```
411
+ </details>
412
+
413
+ ## Job run
414
+ - [{job_id}](https://huggingface.co/jobs/{job_id})
415
+ """
416
+
417
+
418
+ if __name__ == '__main__':
419
+ main()
module_config.json ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "patch_size": 1,
3
+ "in_channels": 128,
4
+ "out_channels": null,
5
+ "num_layers": 5,
6
+ "num_single_layers": 20,
7
+ "attention_head_dim": 128,
8
+ "num_attention_heads": 24,
9
+ "joint_attention_dim": 7680,
10
+ "timestep_guidance_channels": 256,
11
+ "mlp_ratio": 3.0,
12
+ "axes_dims_rope": [
13
+ 32,
14
+ 32,
15
+ 32,
16
+ 32
17
+ ],
18
+ "rope_theta": 2000,
19
+ "eps": 1e-06,
20
+ "guidance_embeds": false,
21
+ "_class_name": "Flux2Transformer2DModel",
22
+ "_diffusers_version": "0.37.0.dev0",
23
+ "_name_or_path": "/root/.cache/huggingface/hub/models--black-forest-labs--FLUX.2-klein-4B/snapshots/e7b7dc27f91deacad38e78976d1f2b499d76a294/transformer",
24
+ "_FrozenDict__frozen": true
25
+ }
package/single_transformer_blocks/package.pt2 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:67ad15e4c7523016e5ed4569141f171f57e9778f57a7ee1c42312b9e9384c70d
3
+ size 583455
package/transformer_blocks/package.pt2 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7506e85384600a93a0879a2d77f366c976be3621c13fe8349b452cf231327a89
3
+ size 1062565
samples/after/edited.png ADDED

Git LFS Details

  • SHA256: 635f5effb6c0c6cf3492ae01f00f12b1fab17550d27748386245745d49caeb0a
  • Pointer size: 132 Bytes
  • Size of remote file: 1.41 MB
samples/before/edited.png ADDED

Git LFS Details

  • SHA256: d8fac34fef8f311334e92274225dee20fc82bbf188ff02ed718fc48cc2a4fc93
  • Pointer size: 132 Bytes
  • Size of remote file: 1.41 MB