Skip to content

Commit 350468f

Browse files
committed
use per batch attention with sliced KV
Signed-off-by: Shreyas Misra <shreyasm@nvidia.com>
1 parent cd41092 commit 350468f

4 files changed

Lines changed: 96 additions & 25 deletions

File tree

examples/visual_gen/configs/cosmos3-nano-1gpu.yaml

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,14 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515

16-
# 1-GPU Cosmos3 (Nano / Super) with FP8 dynamic quantization.
16+
# 1-GPU Cosmos3 (Nano / Super).
1717
# Model: nvidia/Cosmos3-Nano or nvidia/Cosmos3-Super
1818
# Shared by offline examples (--visual_gen_args) and trtllm-serve.
1919
#
2020
# Cosmos3 constraints: VANILLA attention only;
21-
# no Attention2D / Ring. Use CFG + Ulysses for multi-GPU (see cosmos3-super-4gpu.yaml).
22-
quant_config:
23-
quant_algo: FP8
24-
dynamic: true
25-
ignore: ["language_model.*", "vae2llm", "llm2vae", "time_embedder.*"]
21+
# Use CFG + Ulysses for multi-GPU (see cosmos3-super-4gpu.yaml).
2622
attention_config:
2723
backend: VANILLA
2824
parallel_config:
2925
cfg_size: 1
3026
ulysses_size: 1
31-
cuda_graph_config:
32-
enable: false

examples/visual_gen/configs/cosmos3-super-4gpu.yaml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,12 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515

16-
# 4-GPU Cosmos3-Super with FP8 dynamic quantization (CFG + Ulysses + parallel VAE).
16+
# 4-GPU Cosmos3-Super with (CFG + Ulysses + parallel VAE).
1717
# Launch with 4 processes, e.g. torchrun --nproc_per_node=4 ...
1818
# Model: nvidia/Cosmos3-Super
1919
# Shared by offline examples (--visual_gen_args) and trtllm-serve.
2020
#
2121
# GPU layout: cfg_size=2 (positive | negative) x ulysses_size=2 (sequence split).
22-
quant_config:
23-
quant_algo: FP8
24-
dynamic: true
25-
ignore: ["language_model.*", "vae2llm", "llm2vae", "time_embedder.*"]
2622
attention_config:
2723
backend: VANILLA
2824
parallel_config:

examples/visual_gen/models/cosmos3_ti2v.py

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
- ``cosmos3-super-4gpu.yaml`` — 4 GPU, CFG + Ulysses + parallel VAE
4646
4747
Usage:
48-
python cosmos3_ti2v.py --model nvidia/Cosmos3-Nano \\
48+
python cosmos3_ti2v.py --model nvidia/Cosmos3-Nano \
4949
--prompt "The video opens with a view of a well-lit indoor space featuring a " \\
5050
"wooden display case with compartments filled with various fruits, " \\
5151
"including bananas, apples, pears, oranges, and carambolas. " \\
@@ -66,11 +66,38 @@
6666
"position, leaving the display case and surrounding area unchanged. " \\
6767
"The video showcases a seamless and efficient automated fruit-picking " \\
6868
"process, highlighting the precision and efficiency of modern robotics " \\
69-
"in a retail setting." \\
69+
"in a retail setting." \
7070
--visual_gen_args ../configs/cosmos3-nano-1gpu.yaml
71+
72+
python cosmos3_ti2v.py --model nvidia/Cosmos3-Nano \
73+
--prompt "A low-angle tracking shot follows a man riding a vintage black motorcycle " \\
74+
"across a lush green grassy yard. Sunlight filters through overhead trees, casting " \\
75+
"dappled shadows across the vibrating chrome exhaust and the rider's leather jacket. " \\
76+
"He kicks up small blades of grass as he maneuvers the bike. He gradually decelerates, " \\
77+
"the front fork compressing slightly as he brakes to a smooth halt beside another " \\
78+
"individual standing in the shade. The camera settles into a medium two-shot, capturing " \\
79+
"the rider lifting his visor to speak, his face framed by a matte helmet. The video is " \\
80+
"8 seconds long and is of 24 FPS. This video is of 1280x720 resolution. Audio description: " \\
81+
"The rhythmic, mechanical chugging of a four-stroke motorcycle engine dominates the " \\
82+
"foreground, characterized by a throaty, guttural timbre. Periodic high-pitched revs " \\
83+
"punctuate the steady idle as the throttle is twisted. The sound of tires crunching " \\
84+
"softly over dry grass and twigs provides a textured background layer. As the vehicle " \\
85+
"slows, the engine note drops to a low-frequency rumble before clicking into neutral. " \\
86+
"A muffled, mid-range male voice begins speaking, accompanied by the metallic clink of " \\
87+
"a helmet visor snapping upward and the faint chirping of distant birds in an open-air " \\
88+
"environment." \
89+
--visual_gen_args ../configs/cosmos3-nano-1gpu.yaml \
90+
--enable_audio
91+
92+
python cosmos3_ti2v.py --model nvidia/Cosmos3-Nano \
93+
--prompt "A cute puppy playing with a ball in a park" \
94+
--visual_gen_args ../configs/cosmos3-nano-1gpu.yaml \
95+
--output_type image \
96+
--output_path output.png
7197
"""
7298

7399
import argparse
100+
import json
74101

75102
from tensorrt_llm import VisualGen, VisualGenArgs
76103

@@ -109,6 +136,26 @@ def main():
109136
default="cosmos3_ti2v_output.mp4",
110137
help="Path to save the output video",
111138
)
139+
parser.add_argument(
140+
"--enable_duration_template", action="store_true", help="Enable duration template in prompt"
141+
)
142+
parser.add_argument(
143+
"--enable_resolution_template",
144+
action="store_true",
145+
help="Enable resolution template in prompt",
146+
)
147+
parser.add_argument(
148+
"--use_system_prompt", action="store_true", help="Use system prompt in prompt"
149+
)
150+
parser.add_argument("--enable_audio", action="store_true", help="Enable audio generation")
151+
parser.add_argument(
152+
"--output_type", type=str, default="video", help="Output type (video, image)"
153+
)
154+
155+
# Guardrails
156+
parser.add_argument(
157+
"--disable_guardrails", action="store_true", help="NOT RECOMMENDED: Disable guardrails"
158+
)
112159
args = parser.parse_args()
113160

114161
# Engine config from shared YAML (optional); model-specific defaults apply otherwise.
@@ -121,13 +168,25 @@ def main():
121168
if args.image_path is not None:
122169
params.image = args.image_path
123170

171+
negative_prompt = json.load(open("neg_prompt.json"))
172+
173+
params.extra_params["use_duration_template"] = args.enable_duration_template
174+
params.extra_params["use_resolution_template"] = args.enable_resolution_template
175+
params.extra_params["use_system_prompt"] = args.use_system_prompt
176+
params.extra_params["enable_audio"] = args.enable_audio
177+
params.extra_params["use_guardrails"] = not args.disable_guardrails
178+
params.extra_params["output_type"] = args.output_type
179+
180+
params.negative_prompt = json.dumps(negative_prompt)
181+
124182
output = visual_gen.generate(
125183
inputs=args.prompt,
126184
params=params,
127185
)
128186

129187
output.save(args.output_path)
130188
print(f"Saved: {args.output_path}")
189+
print(output.metrics)
131190

132191

133192
if __name__ == "__main__":

tensorrt_llm/_torch/visual_gen/models/cosmos3/transformer_cosmos3.py

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,7 @@ def forward(
343343
v_und: torch.Tensor,
344344
freqs_cos: torch.Tensor,
345345
freqs_sin: torch.Tensor,
346+
real_text_lens: Optional[list[int]],
346347
) -> torch.Tensor:
347348
"""
348349
Args:
@@ -366,15 +367,31 @@ def forward(
366367
q, k = self.apply_qk_norm(q, k)
367368
q, k = qwen3_apply_rotary_pos_emb(q, k, freqs_cos, freqs_sin)
368369

369-
k_all = torch.cat([k_und, k], dim=1).contiguous()
370-
v_all = torch.cat([v_und, v], dim=1).contiguous()
371-
372-
out = self._attn_impl(
373-
q,
374-
k_all,
375-
v_all,
376-
attention_mask=PredefinedAttentionMask.FULL,
377-
)
370+
if real_text_lens is not None and batch_size > 1:
371+
outs = []
372+
for b in range(batch_size):
373+
Lb = int(real_text_lens[b])
374+
k_all_b = torch.cat([k_und[b : b + 1, :Lb], k[b : b + 1]], dim=1)
375+
v_all_b = torch.cat([v_und[b : b + 1, :Lb], v[b : b + 1]], dim=1)
376+
outs.append(
377+
self._attn_impl(
378+
q[b : b + 1],
379+
k_all_b,
380+
v_all_b,
381+
attention_mask=PredefinedAttentionMask.FULL,
382+
)
383+
)
384+
out = torch.cat(outs, dim=0)
385+
else:
386+
k_all = torch.cat([k_und, k], dim=1).contiguous()
387+
v_all = torch.cat([v_und, v], dim=1).contiguous()
388+
389+
out = self._attn_impl(
390+
q,
391+
k_all,
392+
v_all,
393+
attention_mask=PredefinedAttentionMask.FULL,
394+
)
378395

379396
return self.to_out[0](out)
380397

@@ -485,6 +502,7 @@ def forward(
485502
k_und: torch.Tensor,
486503
v_und: torch.Tensor,
487504
freqs: Tuple[torch.Tensor, torch.Tensor],
505+
real_text_lens: Optional[list[int]] = None,
488506
) -> torch.Tensor:
489507
residual = hidden_states
490508
hidden_states = self.input_layernorm(hidden_states)
@@ -496,6 +514,7 @@ def forward(
496514
v_und=v_und,
497515
freqs_cos=cos,
498516
freqs_sin=sin,
517+
real_text_lens=real_text_lens,
499518
)
500519
hidden_states = residual + hidden_states
501520

@@ -968,6 +987,7 @@ def forward(
968987
T, H, W = video_shape
969988
Hp, Wp, _, _ = self._pad_to_patch_size(H, W)
970989
max_real_len = text_mask.sum(dim=1).max().item()
990+
real_text_lens = text_mask.sum(dim=1).tolist()
971991

972992
hidden_gen = self.vae2llm(self.patchify(hidden_states, T, H, W))
973993

@@ -1059,7 +1079,9 @@ def forward(
10591079
if not self.sharder.is_active:
10601080
k_und = k_und[:, :max_real_len]
10611081
v_und = v_und[:, :max_real_len]
1062-
hidden_gen = layer(hidden_gen, k_und, v_und, freqs_gen)
1082+
hidden_gen = layer(hidden_gen, k_und, v_und, freqs_gen, real_text_lens)
1083+
else:
1084+
hidden_gen = layer(hidden_gen, k_und, v_und, freqs_gen)
10631085

10641086
hidden_gen = self.sharder.gather(hidden_gen, dim=1, unpad_to=S_gen)
10651087

0 commit comments

Comments
 (0)