[Performance] FusedAdam capturable kernel is ~1.9x slower than regular Adam on GB300
メンテナーはふだん 2 日以内に返信
評価
この issue はまだ評価されていません。
説明
Transformer Engine's FusedAdam optimizer exhibits approximately 1.9x higher kernel latency with capturable=True compared to capturable=False on GB300.
This was observed in Nemotron 3.5 30B training when enabling optimizer.optimizer_cuda_graph=true in Megatron. The optimizer kernel changes from AdamFunctor to AdamCapturableFunctor, increasing average kernel execution time from approximately 104 µs to 196 µs.
GPU: NVIDIA GB300
Container: nvidia+nemo+26.08.01
Training workload: Nemotron 3.5 30B (BF16, 2 nodes)
To reproduce the issue, run the standalone benchmark: python3 adam_bench.py --graph
"""
Benchmark Transformer Engine FusedAdam: regular vs capturable.
Compares optimizer kernel latency with capturable=False and
capturable=True using large FP32 tensors.
Usage:
python3 adam_bench.py
python3 adam_bench.py --n-tensors 10 --steps 5
python3 adam_bench.py --graph
"""
import argparse
import statistics
import torch
from torch.profiler import profile, ProfilerActivity
from transformer_engine.pytorch.optimizers import FusedAdam
parser = argparse.ArgumentParser()
parser.add_argument("--n-tensors", type=int, default=201)
parser.add_argument("--numel", type=int, default=320 * 65536)
parser.add_argument("--steps", type=int, default=6)
parser.add_argument("--graph", action="store_true")
args = parser.parse_args()
print(f"GPU: {torch.cuda.get_device_name(0)}")
print(f"Tensors: {args.n_tensors}, Elements/tensor: {args.numel:,}")
def benchmark(capturable):
# Create parameters and gradients
params = [
torch.randn(args.numel, device="cuda", requires_grad=True)
for _ in range(args.n_tensors)
]
for p in params:
p.grad = torch.randn_like(p) * 1e-3
optimizer = FusedAdam(
params,
lr=1.6e-3,
betas=(0.9, 0.95),
eps=1e-8,
weight_decay=0.1,
adam_w_mode=True,
capturable=capturable,
exp_avg_dtype=torch.float32,
exp_avg_sq_dtype=torch.float32,
)
# Warmup and initialize optimizer states
for _ in range(2):
optimizer.step()
torch.cuda.synchronize()
# Measure individual Adam CUDA kernels
with profile(activities=[ProfilerActivity.CPU, ProfilerActivity.CUDA]) as prof:
for _ in range(args.steps):
optimizer.step()
torch.cuda.synchronize()
kernel_times = [
e.device_time
for e in prof.events()
if e.device_type == torch.autograd.DeviceType.CUDA
and "multi_tensor_apply_kernel" in e.name
]
# Measure total optimizer step time
start = torch.cuda.Event(enable_timing=True)
end = torch.cuda.Event(enable_timing=True)
start.record()
for _ in range(args.steps):
optimizer.step()
end.record()
torch.cuda.synchronize()
step_ms = start.elapsed_time(end) / args.steps
kernel_us = statistics.mean(kernel_times)
print(f"\nCapturable: {capturable}")
print(f" Kernels/step: {len(kernel_times) / args.steps:.0f}")
print(f" Mean kernel: {kernel_us:.1f} us")
print(f" Step time: {step_ms:.2f} ms")
# Optional CUDA graph benchmark
if capturable and args.graph:
graph = torch.cuda.CUDAGraph()
stream = torch.cuda.Stream()
stream.wait_stream(torch.cuda.current_stream())
with torch.cuda.stream(stream):
optimizer.step()
torch.cuda.current_stream().wait_stream(stream)
with torch.cuda.graph(graph):
optimizer.step()
start.record()
for _ in range(args.steps):
graph.replay()
end.record()
torch.cuda.synchronize()
print(f" Graph replay: {start.elapsed_time(end) / args.steps:.2f} ms")
del optimizer, params
torch.cuda.empty_cache()
return kernel_us, step_ms
regular_us, regular_ms = benchmark(capturable=False)
capturable_us, capturable_ms = benchmark(capturable=True)
print("\n=== Comparison ===")
print(f"Kernel slowdown: {capturable_us / regular_us:.2f}x")
print(f"Step slowdown: {capturable_ms / regular_ms:.2f}x")
- 主要言語
- Python
- スター
- 3.6k
- フォーク
- 883
- 平均マージ
- 4日 17時間
- マージ済み PR(30日)
- 70
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
NVIDIA/TransformerEngine のほかの issue
-
[PyTorch] fp8_cs_quantize fake implementation returns a vector inverse scale instead of a scalar再び着手できるかも @sanjana658 が 22 日前に担当しましたが、オープン中のプルリクエストはありません。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
NVIDIA/TransformerEngine#3636 · コメント 2 件 ·
メンテナーはふだん 2 日以内に返信
-
[Bug] Backend selection picks FA3 for training with head_dim_qk=192 / v_head_dim=128, but FA3 backward cannot run it再び着手できるかも @modelpath-dev が 56 日前に担当しましたが、オープン中のプルリクエストはありません。 オープンattention
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
NVIDIA/TransformerEngine#3481 · コメント 4 件 ·
メンテナーはふだん 2 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
NVIDIA/TransformerEngine#2189 · コメント 7 件 · リアクション 5 件 ·
メンテナーはふだん 2 日以内に返信
-
`DotProductAttention` with `fp8_dpa=True` does not update its backward scales when no Linear-family module is in the autocast region, and dQ/dK lose most of their norm対応中かも @sha7doww が 1 日前に担当しました。 オープン
難易度 4/5 3〜5日 初心者へのやさしさ 48/100
NVIDIA/TransformerEngine#3778 ·
メンテナーはふだん 2 日以内に返信
-
難易度 4/5 3〜5日 初心者へのやさしさ 55/100
NVIDIA/TransformerEngine#3765 ·
メンテナーはふだん 2 日以内に返信
NVIDIA/TransformerEngine の issue をすべて見る
似ている issue
-
getchaintips leaves out the active tip once a header is staged on it, where Core always lists itオープン
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
btclib-org/btclib-node#2158 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
dbt-msft/dbt-sqlserver#897 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
Gathin23/cleanyourtv#2770 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
vllm-project/vllm#64845 ·
メンテナーはふだん 1 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
dekobon/big-code-analysis#1729 ·
メンテナーはふだん 1 日以内に返信