NVIDIA Transformer Engine で学習加速と GPU ベンチ
本文の状態
日本語全文を表示中
詳細モードで約9分の本文を読めます。
同じ出来事の情報源
この情報源を基点に整理
MarkTechPost
MarkTechPost は NVIDIA Transformer Engine の導入と BF16、FP8 計算を組み合わせた GPU ベンチマーク手法を解説し、開発者が実環境でトレーニング効率を最大化する具体的な手順を示している。
AI深層分析を開く2026年8月2日 04:06
AI深層分析
キーポイント
ハードウェア要件の自動検出とフォールバック
スクリプトは GPU の計算能力(Compute Capability)を確認し、Ampere 以降のアーキテクチャでは Transformer Engine を、それ以前や FP8 非対応環境では純粋な PyTorch パスへ自動的に切り替える仕組みを実装している。
融合カーネルと遅延スケーリングの実装
te.Linear や te.LayerNormMLP といった融合コンポーネントを使用し、テンソルスケーリングや amax 履歴を管理する遅延スケーリング FP8 レシピを設定することで、ハイブリッド E4M3/E5M2 フォーマットでの実行を可能にしている。
合成データを用いたトレーニング比較検証
GPT スタイルの因果言語モデルを構築し、決定論的な合成シーケンスで訓練しながら、高精度モードと FP8 モードの実行時間やピーク GPU メモリ使用量を測定して性能差を検証している。
GPU 要件と FP8 サポートの確認
Transformer Engine は Compute Capability 8.0 以上で動作し、FP8 演算には 8.9 以上の GPU が必要である。コードは実行環境の GPU 仕様を自動的に検出し、サポート状況に応じて適切なモードに切り替わる。
Transformer Engine の主要モジュール
te.Linear, te.LayerNorm, te.LayerNormLinear, te.LayerNormMLP といった融合済みカーネルを提供する専用モジュールが利用可能である。これらは BF16 データ型をネイティブにサポートし、従来の PyTorch モジュールよりも効率的な計算を実現する。
重要な引用
In this tutorial, we explore how NVIDIA Transformer Engine accelerates transformer workloads by combining fused GPU kernels, BF16 computation, and hardware-aware FP8 execution.
We begin by installing Transformer Engine and detecting the active GPU architecture so that we can determine whether the runtime supports TE kernels, FP8 tensor cores, or only the pure-PyTorch fallback path.
>> Mode: TE={'ON' if TE_CAPABLE else 'OFF'} | FP8={'ON' if FP8_CAPABLE else 'OFF (will use BF16)'}
FP8 recipe:
編集コメントを表示
編集コメント
本記事は、最新のハードウェア特性に合わせた最適化手法をコードレベルで具体的に示しており、実務での導入検討において非常に有用なリファレンスとなる。特に FP8 の有効性を検証するプロセスが明確であるため、環境構築の指針として活用できる。
Source Article
元記事を日本語で読む
本文に関係しない購読案内、埋め込み通知、サイト内プロモーションは除いています。
本チュートリアルでは、NVIDIA Transformer Engine が融合された GPU カーネル、BF16 計算、ハードウェアに最適化された FP8 実行を組み合わせることで、Transformer ワークロードをどのように高速化するのかを探ります。まずは Transformer Engine のインストールと、アクティブな GPU アーキテクチャの検出から始めます。これにより、ランタイムが TE カーネルや FP8 テンソルコアをサポートしているか、それとも純粋な PyTorch のフォールバックパスのみに対応しているかを判断できます。
次に、te.Linear、te.LayerNorm、te.LayerNormLinear、te.LayerNormMLP、te.TransformerLayer といった主要な融合コンポーネントを確認し、テンソルスケーリングや amax ヒストリを管理するハイブリッド E4M3/E5M2 フォーマットに対応した遅延スケーリング FP8 のレシピを設定します。
これらのコンポーネントを用いて、コンパクトな GPT 形式の因果言語モデルを構築し、決定論的な合成シーケンスで学習を行います。その後、高精度実行と FP8 実行を比較し、ランタイム時間や GPU メモリのピーク値を測定。FP8 のメタデータを調査し、自己回帰生成を通じて学習済みモデルを検証します。
Copy CodeCopiedUse a different Browser
import subprocess, sys, os
def pip_install(*pkgs):
subprocess.run([sys.executable, "-m", "pip", "install", "-q",
"--no-build-isolation", *pkgs], check=False)
print(">> Installing transformer_engine[pytorch] (this can take a few minutes)...")
pip_install("transformer_engine[pytorch]")
import time, math, gc
import torch
import torch.nn as nn
import torch.nn.functional as F
assert torch.cuda.is_available(), "Enable a GPU runtime in Colab first!"
DEVICE = "cuda"
props = torch.cuda.get_device_properties(0)
CC = (props.major, props.minor)
GPU_NAME = props.name
print(f">> GPU: {GPU_NAME} | compute capability {CC[0]}.{CC[1]} | "
f"{props.total_memory/1e9:.1f} GB")
TE_CAPABLE = CC >= (8, 0)
FP8_CAPABLE = CC >= (8, 9)
te = None
if TE_CAPABLE:
try:
import transformer_engine.pytorch as te
from transformer_engine.common import recipe
print(">> Transformer Engine imported OK:",
getattr(te, "__version__", "unknown version"))
except Exception as e:
print(f">> TE import failed ({e}); using pure-PyTorch fallback.")
TE_CAPABLE = FP8_CAPABLE = False
else:
print(">> GPU is pre-Ampere (e.g. T4): TE kernels unsupported -> fallback mode.")
if TE_CAPABLE and FP8_CAPABLE and te is not None:
try:
ok, reason = te.fp8.check_fp8_support()
FP8_CAPABLE = bool(ok)
if not ok:
print(">> TE reports FP8 unsupported:", reason)
except Exception:
pass
print(f">> Mode: TE={'ON' if TE_CAPABLE else 'OFF'} | "
f"FP8={'ON' if FP8_CAPABLE else 'OFF (will use BF16)'}")
torch.manual_seed(1234)
if TE_CAPABLE:
H = 768
x_demo = torch.randn(8, 32, H, device=DEVICE, dtype=torch.bfloat16)
lin = te.Linear(H, H, bias=True, params_dtype=torch.bfloat16).to(DEVICE)
ln = te.LayerNorm(H, params_dtype=torch.bfloat16).to(DEVICE)
ln_lin = te.LayerNormLinear(H, 3 * H, params_dtype=torch.bfloat16).to(DEVICE)
ln_mlp = te.LayerNormMLP(H, 4 * H, params_dtype=torch.bfloat16).to(DEVICE)
with torch.no_grad():
print("\n>> Module tour (shapes):")
print(" te.Linear ", tuple(lin(x_demo).shape))
print(" te.LayerNorm ", tuple(ln(x_demo).shape))
print(" te.LayerNormLinear", tuple(ln_lin(x_demo).shape))
print(" te.LayerNormMLP ", tuple(ln_mlp(x_demo).shape))
del lin, ln, ln_lin, ln_mlp, x_demo
gc.collect(); torch.cuda.empty_cache()
fp8_recipe = None
if FP8_CAPABLE:
fp8_recipe = recipe.DelayedScaling(
fp8_format=recipe.Format.HYBRID,
amax_history_len=16,
amax_compute_algo="max",
)
print("\n>> FP8 recipe:", fp8_recipe)
NVIDIA Transformer Engine をインストールし、GPU 加速実行に必要な PyTorch 環境を初期化します。アクティブな GPU、計算能力(compute capability)、メモリ容量を確認して、Fused TE カーネルや FP8 テンサーコアの利用可否を判断します。また、主要な Fused モジュールの検証を行い、遅延スケーリング方式の FP8 レシピを設定するとともに、対応していないハードウェア向けに PyTorch の自動フォールバック機能も維持します。
コードをコピーしました(Copied)。ブラウザを変更して実行することも可能です。
VOCAB, D_MODEL, N_HEADS, N_LAYERS, FFN, SEQ = 96, 768, 12, 4, 3072, 256
class MiniGPT_TE(nn.Module):
"""各ブロックが単一の融合された te.TransformerLayer で構成される因果律 LM(言語モデル)です。"""
def __init__(self):
super().__init__()
self.emb = nn.Embedding(VOCAB, D_MODEL)
self.pos = nn.Embedding(SEQ, D_MODEL)
self.blocks = nn.ModuleList([
te.TransformerLayer(
hidden_size=D_MODEL,
ffn_hidden_size=FFN,
num_attention_heads=N_HEADS,
self_attn_mask_type="causal",
layer_number=i + 1,
params_dtype=torch.bfloat16,
hidden_dropout=0.0,
attention_dropout=0.0,
)
for i in range(N_LAYERS)
])
self.ln_f = nn.LayerNorm(D_MODEL)
self.head = nn.Linear(D_MODEL, VOCAB, bias=False)
def forward(self, idx):
B, T = idx.shape
h = self.emb(idx) + self.pos(torch.arange(T, device=idx.device))
h = h.to(torch.bfloat16)
for blk in self.blocks:
h = blk(h)
h = self.ln_f(h.float())
return self.head(h)
class Block_PT(nn.Module):
"""標準的な PyTorch によるトランスフォーマーブロック。te.TransformerLayer と同等の機能を持ちます。"""
def __init__(self):
super().__init__()
self.ln1 = nn.LayerNorm(D_MODEL)
self.attn = nn.MultiheadAttention(D_MODEL, N_HEADS, batch_first=True)
self.ln2 = nn.LayerNorm(D_MODEL)
self.mlp = nn.Sequential(nn.Linear(D_MODEL, FFN), nn.GELU(),
</article>
nn.Linear(FFN, D_MODEL))
def forward(self, x, mask):
a, _ = self.attn(self.ln1(x), self.ln1(x), self.ln1(x),
attn_mask=mask, need_weights=False)
x = x + a
return x + self.mlp(self.ln2(x))
class MiniGPT_PT(nn.Module):
def __init__(self):
super().__init__()
self.emb = nn.Embedding(VOCAB, D_MODEL)
self.pos = nn.Embedding(SEQ, D_MODEL)
self.blocks = nn.ModuleList([Block_PT() for _ in range(N_LAYERS)])
self.ln_f = nn.LayerNorm(D_MODEL)
self.head = nn.Linear(D_MODEL, VOCAB, bias=False)
def forward(self, idx):
B, T = idx.shape
mask = torch.triu(torch.full((T, T), float("-inf"),
device=idx.device), diagonal=1)
h = self.emb(idx) + self.pos(torch.arange(T, device=idx.device))
for blk in self.blocks:
h = blk(h, mask)
return self.head(self.ln_f(h))
model = (MiniGPT_TE() if TE_CAPABLE else MiniGPT_PT()).to(DEVICE)
n_params = sum(p.numel() for p in model.parameters())
print(f"\n>> Model: {'TE fused' if TE_CAPABLE else 'pure PyTorch'} | "
f"{n_params/1e6:.1f}M params | {N_LAYERS} layers x {D_MODEL}d")
Transformer Engine での実行に対応するコンパクトな因果言語モデルを定義します。このモデルは、融合された te.TransformerLayer ブロックを使用しています。一方、マルチヘッドアテンション、レイヤー正規化、残差接続、フィードフォワードネットワークを備えた同等の純粋な PyTorch 版トランスフォーマーアーキテクチャも実装しました。
最終的なパラメータ数とアーキテクチャの次元については、利用可能な GPU のサポート状況に応じて適切なモデルを動的に選択して報告します。
def make_batch(bsz=16):
phase = torch.randint(0, VOCAB, (bsz, 1))
stride = torch.randint(1, 7, (bsz, 1))
steps = torch.arange(SEQ + 1).unsqueeze(0)
seq = (phase + stride * steps) % VOCAB
return seq[:, :-1].to(DEVICE), seq[:, 1:].to(DEVICE)
opt = torch.optim.AdamW(model.parameters(), lr=3e-4)
def run_step(x, y, use_fp8):
if TE_CAPABLE and use_fp8:
with te.fp8_autocast(enabled=True, fp8_recipe=fp8_recipe):
logits = model(x)
else:
logits = model(x)
loss = F.cross_entropy(logits.float().reshape(-1, VOCAB), y.reshape(-1))
opt.zero_grad(set_to_none=True)
loss.backward()
opt.step()
return loss.item()
print(f"\n>> Training 60 steps ({'FP8' if FP8_CAPABLE else 'BF16/FP32'})...")
t0 = time.time()
for step in range(1, 61):
x, y = make_batch()
loss = run_step(x, y, use_fp8=FP8_CAPABLE)
if step % 10 == 0:
print(f" step {step:3d} | loss {loss:.4f} | "
f"{(time.time()-t0)/step*1000:.0f} ms/step")
print(f">> Final loss: {loss:.4f} (random guess would be ~{math.log(VOCAB):.2f})")
モデルが語彙全体にわたって予測可能なトークン遷移を学習できるよう、決定論的な演算パターン系列を作成します。AdamW オプティマイザを設定し、FP8 実行がサポートされている場合にフォワードパスを te.fp8_autocast で条件付きラップするトレーニングステップを実装します。モデルを複数回反復して訓練し、損失とステップのレイテンシを監視しながら、最終的な損失をランダム推測ベースラインと比較します。
def bench(use_fp8, iters=30, warmup=10):
x, y = make_batch(bsz=32)
for _ in range(warmup):
run_step(x, y, use_fp8)
torch.cuda.synchronize()
torch.cuda.reset_peak_memory_stats()
t = time.time()
for _ in range(iters):
run_step(x, y, use_fp8)
torch.cuda.synchronize()
ms = (time.time() - t) / iters * 1000
mem = torch.cuda.max_memory_allocated() / 1e9
return ms, mem
print("\n>> Benchmark (batch 32, seq 256, fwd+bwd+optim):")
ms_hi, mem_hi = bench(use_fp8=False)
print(f" {'BF16' if TE_CAPABLE else 'FP32'}: {ms_hi:7.1f} ms/step | "
f"peak mem {mem_hi:.2f} GB")
if FP8_CAPABLE:
ms_f8, mem_f8 = bench(use_fp8=True)
print(f" FP8 : {ms_f8:7.1f} ms/step | peak mem {mem_f8:.2f} GB")
print(f" Speedup: {ms_hi/ms_f8:.2f}x "
f"(gains grow with model size — try D_MODEL=2048, N_LAYERS=12)")
else:
print(" FP8 benchmark skipped — needs an sm_89+ GPU (L4/H100/Ada/Blackwell).")
if FP8_CAPABLE:
blk = model.blocks[0]
for name, m in blk.named_modules():
meta = getattr(m, "fp8_meta", None)
if meta and "scaling_fwd" in meta:
s = meta["scaling_fwd"]
print(f"\n>> FP8 state of block-0 submodule '{name}':")
print(" scale :", s.scale.flatten()[:4].tolist())
print(" amax_history:", s.amax_history[0, :4].tolist())
break
NVIDIA Transformer Engine の高精度モードと FP8 実行モードを用いて、順伝播、逆伝播、オプティマイザ更新のベンチマークを実施しました。計算精度を下げたことによるパフォーマンスとメモリへの影響を定量化するため、平均トレーニングステップのレイテンシと最大割り当て GPU メモリ量を計測しています。また、Transformer Engine が維持するスケーリング係数と amax の履歴を確認し、遅延スケールが FP8 テンソルをどのように安定化させるかを検証しました。
Copy CodeCopiedUse a different Browser
@torch.no_grad()
def generate(prompt_len=8, gen_len=24):
x, _ = make_batch(bsz=1)
ctx = x[:, :prompt_len]
for _ in range(gen_len):
inp = ctx[:, -SEQ:]
if TE_CAPABLE and FP8_CAPABLE:
with te.fp8_autocast(enabled=True, fp8_recipe=fp8_recipe):
logits = model(inp)
else:
logits = model(inp)
nxt = logits[:, -1].argmax(-1, keepdim=True)
ctx = torch.cat([ctx, nxt], dim=1)
return ctx[0].tolist()
seq = generate()
print("\n>> Greedy generation (should continue the arithmetic pattern):")
print(" prompt+gen:", seq)
diffs = [(b - a) % VOCAB for a, b in zip(seq, seq[1:])]
print(" step diffs:", diffs, "<- constant stride = model learned the rule")
print("\n>> Done! Things to try next:")
print(" * Scale up: D_MODEL=2048, N_LAYERS=12 -> FP8 speedup becomes dramatic")
print(" * recipe.Format.E4M3 vs HYBRID; amax_history_len=1024")
print(" * te.LayerNormMLP / te.LayerNormLinear in your own architectures")
print(" * fp8_model_init() to store weights themselves in FP8 for inference")
学習済みの因果言語モデルに最新のコンテキストを逐次フィードバックすることで、貪欲な自己回帰生成を実現しています。生成された連続するトークンを比較し、合成トレーニングデータに含まれる一定の算術ストライドがモデルによって維持されているかを確認しました。
最後に、より大きなモデル次元や代替 FP8 フォーマット、長い amax ヒストリ、融合モジュール、FP8 重み初期化など、実用的な拡張の可能性について言及します。
結論として、NVIDIA Transformer Engine を異なる Colab GPU 環境間での互換性を保ちながらエンドツーエンドのトランスフォーマー学習ワークフローに統合する方法を示しました。カーネル起動のオーバーヘッドとメモリアクセスを削減するために融合されたトランスフォーマーモジュールを使用し、サポートされている場合は遅延スケーリング付きで FP8 オートキャストを適用、必要に応じて BF16 または FP32 実行を PyTorch の自動フォールバック機能で維持しました。
同じミニサイズの因果言語モデルで学習とベンチマークを実施した結果、ハードウェアの能力、数値フォーマット、融合実行、モデル規模がトレーニング速度とメモリ消費にどのように影響するかを確認できました。また、安定した FP8 計算を支える内部スケーリング係数や amax ヒストリも調査し、Transformer Engine が低精度演算をどう管理しているかをより明確に理解することができました。
GitHub リポジトリや Hugging Face ページ、製品リリース、ウェビナーなどのプロモーションをご希望の場合は、ぜひパートナーシップを組んでください。お問い合わせはこちらから。
本記事は、MarkTechPost にて「NVIDIA Transformer Engine、Fused Kernels、BF16、FP8 を活用した Transformer 学習の高速化と GPU ベンチマーク」として掲載されました。
原文を表示
In this tutorial, we explore how NVIDIA Transformer Engine accelerates transformer workloads by combining fused GPU kernels, BF16 computation, and hardware-aware FP8 execution. We begin by installing Transformer Engine and detecting the active GPU architecture so that we can determine whether the runtime supports TE kernels, FP8 tensor cores, or only the pure-PyTorch fallback path. We then examine core fused components such as te.Linear, te.LayerNorm, te.LayerNormLinear, te.LayerNormMLP, and te.TransformerLayer, while also configuring a delayed-scaling FP8 recipe that manages tensor scaling, amax history, and hybrid E4M3/E5M2 formats. Using these components, we construct a compact GPT-style causal language model, train it on deterministic synthetic sequences, compare higher-precision and FP8 execution, measure runtime and peak GPU memory, inspect FP8 metadata, and validate the trained model through autoregressive generation.
Copy CodeCopiedUse a different Browser
import subprocess, sys, os
def pip_install(*pkgs):
subprocess.run([sys.executable, "-m", "pip", "install", "-q",
"--no-build-isolation", *pkgs], check=False)
print(">> Installing transformer_engine[pytorch] (this can take a few minutes)...")
pip_install("transformer_engine[pytorch]")
import time, math, gc
import torch
import torch.nn as nn
import torch.nn.functional as F
assert torch.cuda.is_available(), "Enable a GPU runtime in Colab first!"
DEVICE = "cuda"
props = torch.cuda.get_device_properties(0)
CC = (props.major, props.minor)
GPU_NAME = props.name
print(f">> GPU: {GPU_NAME} | compute capability {CC[0]}.{CC[1]} | "
f"{props.total_memory/1e9:.1f} GB")
TE_CAPABLE = CC >= (8, 0)
FP8_CAPABLE = CC >= (8, 9)
te = None
if TE_CAPABLE:
try:
import transformer_engine.pytorch as te
from transformer_engine.common import recipe
print(">> Transformer Engine imported OK:",
getattr(te, "__version__", "unknown version"))
except Exception as e:
print(f">> TE import failed ({e}); using pure-PyTorch fallback.")
TE_CAPABLE = FP8_CAPABLE = False
else:
print(">> GPU is pre-Ampere (e.g. T4): TE kernels unsupported -> fallback mode.")
if TE_CAPABLE and FP8_CAPABLE and te is not None:
try:
ok, reason = te.fp8.check_fp8_support()
FP8_CAPABLE = bool(ok)
if not ok:
print(">> TE reports FP8 unsupported:", reason)
except Exception:
pass
print(f">> Mode: TE={'ON' if TE_CAPABLE else 'OFF'} | "
f"FP8={'ON' if FP8_CAPABLE else 'OFF (will use BF16)'}")
torch.manual_seed(1234)
if TE_CAPABLE:
H = 768
x_demo = torch.randn(8, 32, H, device=DEVICE, dtype=torch.bfloat16)
lin = te.Linear(H, H, bias=True, params_dtype=torch.bfloat16).to(DEVICE)
ln = te.LayerNorm(H, params_dtype=torch.bfloat16).to(DEVICE)
ln_lin = te.LayerNormLinear(H, 3 * H, params_dtype=torch.bfloat16).to(DEVICE)
ln_mlp = te.LayerNormMLP(H, 4 * H, params_dtype=torch.bfloat16).to(DEVICE)
with torch.no_grad():
print("\n>> Module tour (shapes):")
print(" te.Linear ", tuple(lin(x_demo).shape))
print(" te.LayerNorm ", tuple(ln(x_demo).shape))
print(" te.LayerNormLinear", tuple(ln_lin(x_demo).shape))
print(" te.LayerNormMLP ", tuple(ln_mlp(x_demo).shape))
del lin, ln, ln_lin, ln_mlp, x_demo
gc.collect(); torch.cuda.empty_cache()
fp8_recipe = None
if FP8_CAPABLE:
fp8_recipe = recipe.DelayedScaling(
fp8_format=recipe.Format.HYBRID,
amax_history_len=16,
amax_compute_algo="max",
)
print("\n>> FP8 recipe:", fp8_recipe)
We install NVIDIA Transformer Engine and initialize the PyTorch environment required for GPU-accelerated execution. We inspect the active GPU, compute capability, and memory capacity to determine whether fused TE kernels and FP8 tensor cores are available. We also validate the core fused modules and configure a delayed-scaling FP8 recipe while preserving an automatic PyTorch fallback for unsupported hardware.
Copy CodeCopiedUse a different Browser
VOCAB, D_MODEL, N_HEADS, N_LAYERS, FFN, SEQ = 96, 768, 12, 4, 3072, 256
class MiniGPT_TE(nn.Module):
"""Causal LM where every block is a single fused te.TransformerLayer."""
def __init__(self):
super().__init__()
self.emb = nn.Embedding(VOCAB, D_MODEL)
self.pos = nn.Embedding(SEQ, D_MODEL)
self.blocks = nn.ModuleList([
te.TransformerLayer(
hidden_size=D_MODEL,
ffn_hidden_size=FFN,
num_attention_heads=N_HEADS,
self_attn_mask_type="causal",
layer_number=i + 1,
params_dtype=torch.bfloat16,
hidden_dropout=0.0,
attention_dropout=0.0,
)
for i in range(N_LAYERS)
])
self.ln_f = nn.LayerNorm(D_MODEL)
self.head = nn.Linear(D_MODEL, VOCAB, bias=False)
def forward(self, idx):
B, T = idx.shape
h = self.emb(idx) + self.pos(torch.arange(T, device=idx.device))
h = h.to(torch.bfloat16)
for blk in self.blocks:
h = blk(h)
h = self.ln_f(h.float())
return self.head(h)
class Block_PT(nn.Module):
"""Plain-PyTorch transformer block, mirrors te.TransformerLayer."""
def __init__(self):
super().__init__()
self.ln1 = nn.LayerNorm(D_MODEL)
self.attn = nn.MultiheadAttention(D_MODEL, N_HEADS, batch_first=True)
self.ln2 = nn.LayerNorm(D_MODEL)
self.mlp = nn.Sequential(nn.Linear(D_MODEL, FFN), nn.GELU(),
nn.Linear(FFN, D_MODEL))
def forward(self, x, mask):
a, _ = self.attn(self.ln1(x), self.ln1(x), self.ln1(x),
attn_mask=mask, need_weights=False)
x = x + a
return x + self.mlp(self.ln2(x))
class MiniGPT_PT(nn.Module):
def __init__(self):
super().__init__()
self.emb = nn.Embedding(VOCAB, D_MODEL)
self.pos = nn.Embedding(SEQ, D_MODEL)
self.blocks = nn.ModuleList([Block_PT() for _ in range(N_LAYERS)])
self.ln_f = nn.LayerNorm(D_MODEL)
self.head = nn.Linear(D_MODEL, VOCAB, bias=False)
def forward(self, idx):
B, T = idx.shape
mask = torch.triu(torch.full((T, T), float("-inf"),
device=idx.device), diagonal=1)
h = self.emb(idx) + self.pos(torch.arange(T, device=idx.device))
for blk in self.blocks:
h = blk(h, mask)
return self.head(self.ln_f(h))
model = (MiniGPT_TE() if TE_CAPABLE else MiniGPT_PT()).to(DEVICE)
n_params = sum(p.numel() for p in model.parameters())
print(f"\n>> Model: {'TE fused' if TE_CAPABLE else 'pure PyTorch'} | "
f"{n_params/1e6:.1f}M params | {N_LAYERS} layers x {D_MODEL}d")
We define a compact causal language model using fused te.TransformerLayer blocks for Transformer Engine execution. We also implement an equivalent pure-PyTorch transformer architecture with multi-head attention, layer normalization, residual connections, and feed-forward networks. We select the appropriate model dynamically according to GPU support and report the final parameter count and architectural dimensions.
Copy CodeCopiedUse a different Browser
def make_batch(bsz=16):
phase = torch.randint(0, VOCAB, (bsz, 1))
stride = torch.randint(1, 7, (bsz, 1))
steps = torch.arange(SEQ + 1).unsqueeze(0)
seq = (phase + stride * steps) % VOCAB
return seq[:, :-1].to(DEVICE), seq[:, 1:].to(DEVICE)
opt = torch.optim.AdamW(model.parameters(), lr=3e-4)
def run_step(x, y, use_fp8):
if TE_CAPABLE and use_fp8:
with te.fp8_autocast(enabled=True, fp8_recipe=fp8_recipe):
logits = model(x)
else:
logits = model(x)
loss = F.cross_entropy(logits.float().reshape(-1, VOCAB), y.reshape(-1))
opt.zero_grad(set_to_none=True)
loss.backward()
opt.step()
return loss.item()
print(f"\n>> Training 60 steps ({'FP8' if FP8_CAPABLE else 'BF16/FP32'})...")
t0 = time.time()
for step in range(1, 61):
x, y = make_batch()
loss = run_step(x, y, use_fp8=FP8_CAPABLE)
if step % 10 == 0:
print(f" step {step:3d} | loss {loss:.4f} | "
f"{(time.time()-t0)/step*1000:.0f} ms/step")
print(f">> Final loss: {loss:.4f} (random guess would be ~{math.log(VOCAB):.2f})")
We create deterministic arithmetic-pattern sequences that allow the model to learn predictable token transitions across the vocabulary. We configure the AdamW optimizer and implement a training step that conditionally wraps the forward pass in te.fp8_autocast when FP8 execution is supported. We train the model for multiple iterations, monitor the loss and step latency, and compare the final loss against the random-guess baseline.
Copy CodeCopiedUse a different Browser
def bench(use_fp8, iters=30, warmup=10):
x, y = make_batch(bsz=32)
for _ in range(warmup):
run_step(x, y, use_fp8)
torch.cuda.synchronize()
torch.cuda.reset_peak_memory_stats()
t = time.time()
for _ in range(iters):
run_step(x, y, use_fp8)
torch.cuda.synchronize()
ms = (time.time() - t) / iters * 1000
mem = torch.cuda.max_memory_allocated() / 1e9
return ms, mem
print("\n>> Benchmark (batch 32, seq 256, fwd+bwd+optim):")
ms_hi, mem_hi = bench(use_fp8=False)
print(f" {'BF16' if TE_CAPABLE else 'FP32'}: {ms_hi:7.1f} ms/step | "
f"peak mem {mem_hi:.2f} GB")
if FP8_CAPABLE:
ms_f8, mem_f8 = bench(use_fp8=True)
print(f" FP8 : {ms_f8:7.1f} ms/step | peak mem {mem_f8:.2f} GB")
print(f" Speedup: {ms_hi/ms_f8:.2f}x "
f"(gains grow with model size — try D_MODEL=2048, N_LAYERS=12)")
else:
print(" FP8 benchmark skipped — needs an sm_89+ GPU (L4/H100/Ada/Blackwell).")
if FP8_CAPABLE:
blk = model.blocks[0]
for name, m in blk.named_modules():
meta = getattr(m, "fp8_meta", None)
if meta and "scaling_fwd" in meta:
s = meta["scaling_fwd"]
print(f"\n>> FP8 state of block-0 submodule '{name}':")
print(" scale :", s.scale.flatten()[:4].tolist())
print(" amax_history:", s.amax_history[0, :4].tolist())
break
We benchmark forward propagation, backpropagation, and optimizer updates using higher-precision and FP8 execution modes. We measure average training-step latency and peak allocated GPU memory to quantify the performance and memory impact of reduced-precision computation. We also inspect the scaling factors and amax history maintained by Transformer Engine to understand how delayed scaling stabilizes FP8 tensors.
Copy CodeCopiedUse a different Browser
@torch.no_grad()
def generate(prompt_len=8, gen_len=24):
x, _ = make_batch(bsz=1)
ctx = x[:, :prompt_len]
for _ in range(gen_len):
inp = ctx[:, -SEQ:]
if TE_CAPABLE and FP8_CAPABLE:
with te.fp8_autocast(enabled=True, fp8_recipe=fp8_recipe):
logits = model(inp)
else:
logits = model(inp)
nxt = logits[:, -1].argmax(-1, keepdim=True)
ctx = torch.cat([ctx, nxt], dim=1)
return ctx[0].tolist()
seq = generate()
print("\n>> Greedy generation (should continue the arithmetic pattern):")
print(" prompt+gen:", seq)
diffs = [(b - a) % VOCAB for a, b in zip(seq, seq[1:])]
print(" step diffs:", diffs, "<- constant stride = model learned the rule")
print("\n>> Done! Things to try next:")
print(" * Scale up: D_MODEL=2048, N_LAYERS=12 -> FP8 speedup becomes dramatic")
print(" * recipe.Format.E4M3 vs HYBRID; amax_history_len=1024")
print(" * te.LayerNormMLP / te.LayerNormLinear in your own architectures")
print(" * fp8_model_init() to store weights themselves in FP8 for inference")
We implement greedy autoregressive generation by repeatedly feeding the latest context into the trained causal language model. We compare consecutive generated tokens to verify whether the model preserves the constant arithmetic stride present in the synthetic training data. We conclude by identifying practical extensions, including larger model dimensions, alternative FP8 formats, longer amax histories, fused modules, and FP8 weight initialization.
In conclusion, we demonstrated how we integrate NVIDIA Transformer Engine into an end-to-end transformer training workflow while preserving compatibility across different Colab GPU environments. We used fused transformer modules to reduce kernel-launch overhead and memory traffic, applied FP8 autocasting with delayed scaling when supported, and retained BF16 or FP32 execution through an automatic PyTorch fallback. By training and benchmarking the same mini causal language model, we observed how hardware capability, numerical format, fused execution, and model scale influence training speed and memory consumption. We also inspected the internal scaling factors and amax history that support stable FP8 computation, which gives us a clearer understanding of how Transformer Engine manages reduced-precision arithmetic.
Check out the Full Codes. Also, feel free to follow us on Twitter and don’t forget to join our 150k+ML SubReddit and Subscribe to our Newsletter. Wait! are you on telegram? now you can join us on telegram as well.
Need to partner with us for promoting your GitHub Repo OR Hugging Face Page OR Product Release OR Webinar etc.? Connect with us
The post Accelerating Transformer Training with NVIDIA Transformer Engine, Fused Kernels, BF16, FP8, and GPU Benchmarking appeared first on MarkTechPost.
関連記事
News to Guide
ニュースの次に確認する
発表内容を、現在の料金や仕様と照らし合わせられる関連ガイドです。
今日のまとめ
AIデイリーブリーフで今日の重要ニュースをまとめ読み