ホームへ戻る

GitHub Repo

PyTorch開発版でCUDA Graphのコピー不具合が報告、遅延コピーされたテンソルがリプレイ時に古いデータを読む可能性

10月7日のPyTorchとTorchTitanの報告によると、copy-on-writeテンソルがCUDA Graphのキャプチャ中に実体化されると、コピー操作が記録されず、リプレイ時に誤った結果が生じる可能性がある。最小再現例とMoE推論の比較結果が示されているが、正式版への影響範囲と上流での修正は未確認だ。

Pytorch Deepdream (https://github.com/gordicaleksa/pytorch-deepdream) by gordicaleksa (https://github.com/gordicaleksa/pytorch-deepdream/commits?author=gordicaleksa) · MIT · Image source
zh-Hant

PyTorchリポジトリで10月7日、正確性に関する問題が新たに報告された。torch._lazy_clone()で作成したcopy-on-writeテンソルについて、CUDA Graphのキャプチャ中に実際のコピーが発生すると、リプレイ時もキャプチャ時点の古いデータを読み続ける可能性があり、キャプチャ中にはエラーも発生しないという。報告された環境はPyTorch 2.16.0a0開発版、CUDA 13.0、GB300で、torch.compile(mode="reduce-overhead")でも再現できるとされる。PyTorchの報告

最小ケースでは、まず入力をNaNで初期化し、キャプチャ領域内で遅延コピーされたテンソルを作成してから、data_ptr()を呼び出して実体化させる。各リプレイの前に新しい乱数値を入力に書き込んでも、出力にはNaNが含まれる。報告では、原因として、アロケーターがストリームを指定しない同期cudaMemcpyを使用していることが挙げられている。コピーはキャプチャ時に一度だけ実行され、グラフのノードとして記録されない。再現例と原因分析

この問題は、CUDA Graphのデータ更新の仕組みに直接関係する。公式ドキュメントによると、リプレイでは同じメモリアドレスが再利用されるため、ユーザーはリプレイ前に入力バッファーを更新する必要がある。性能向上の主な理由は、CPU側のカーネル起動オーバーヘッドを省けることだ。中間のコピーがグラフに含まれていなければ、元の入力を更新しても、後続カーネルが読み取るコピーは更新されない。CUDA Graph公式ドキュメント

関連するTorchTitanの事例では、Qwen3.5-35B-A3Bのテンソル並列MoE推論でこの問題が発生した。シャーディング処理によって遅延コピーされたテンソルが生成され、Dist-MoEが元のポインターを介してTritonまたはCuTeのカーネルに渡していた。報告者はH100単一GPUでのテストも提示しており、デフォルト以外のストリームではデータ生成前にコピーが完了する可能性を示している。一方、通常のclone()を使った比較テストでは正しい結果が得られた。TorchTitanの事例

今後は、遅延コピー、元のポインター、ストリームが交わる箇所について正確性を比較し、コピー操作が現在のストリームに沿って順序付けられ、安全にキャプチャされるかを確認する必要がある。確認時点で両方のissueはオープンのままで、ページには修正PRへのリンクがない。現時点の証拠は開発版に限られており、すべての安定版やすべてのvLLMデプロイに影響すると推定することはできない。通常のコピーを使う暫定回避策についても、性能コストの全容はまだ測定されていない。TorchTitanの報告と提案

出典

  1. Materializing a lazy clone (COW tensor) during CUDA graph capture gives wrong results on replay
  2. CUDAGraph + Copy-on-write tensor lazy copy produce NaN output
  3. CUDA semantics — PyTorch 2.14 documentation