1 ポイント 投稿者 GN⁺ 2 시간 전 | 1件のコメント | WhatsAppで共有
  • cuda-oxideは、安全性を重視したイディオマティックなRustでSIMT GPUカーネルを記述し、標準的なRustコードをPTXへ直接コンパイルする実験的コンパイラ
  • DSLや異言語バインディングなしでRustのみを使用し、所有権・トレイト・ジェネリクスの理解が前提で、asyncの章では.awaitの知識も必要
  • v0.1.0は初期アルファリリースのため、バグ、未完成機能、APIの破壊的変更を想定する必要がある
  • 例はcargo oxide run vecaddで実行し、#[cuda_module]内の#[kernel]関数がthread::index_1d()でベクトル加算を行う
  • #[cuda_module]デバイスアーティファクトをホストバイナリに含め、型付きローダーとカーネルごとの実行メソッドを生成する

使い方と生成コード

  • クイックスタート

    • インストール前提条件を満たしたうえで、cargo oxide run vecaddでサンプルをビルドして実行する
    • インストール案内はprerequisitesにある
    • サンプルは#[cuda_module]モジュール内に#[kernel]関数vecaddを定義し、thread::index_1d()でインデックスを取得してa[i] + b[i]DisjointSlice<f32>に書き込む
    • ホスト側ではCudaContext::new(0)、デフォルトストリーム、kernels::load(&ctx)を使い、DeviceBuffer::from_hostDeviceBuffer::<f32>::zeroedLaunchConfig::for_num_elems(1024)でカーネルを実行する
    • 実行結果をc.to_host_vec(&stream)で取得し、result[0] == 3.0を確認する
  • #[cuda_module]の動作

    • #[cuda_module]は生成されたデバイスアーティファクトをホストバイナリに含める
    • 型付きのkernels::load関数とカーネルごとの実行メソッドを生成する
    • 特定のsidecarアーティファクトを読み込んだり、カスタム実行コードを作成したりする必要がある場合は、低レベルのload_kernel_modulecuda_launch! APIも引き続き利用できる

前提と方向性

  • cuda-oxideは、Rustの型システムと所有権モデルでGPUカーネルを記述することを目指し、安全性を最優先の目標にしている
  • GPUには微妙な点があるため、the safety modelを読む必要がある
  • DSLではなく、純粋なRustをPTXへコンパイルするカスタムrustcコード生成バックエンドである
  • GPU処理を遅延実行されるDeviceOperationグラフとして構成し、ストリームプールにスケジューリングして、.awaitで結果を待つ非同期実行をサポートする
  • Rustの所有権、トレイト、ジェネリクスに習熟していることを前提とし、その後のasync GPUプログラミングの章ではasync/.awaitやtokioのようなランタイムの知識も必要になる
  • 参考資料としてThe Rust Programming LanguageRust by ExampleAsync Bookが提供されている
  • v0.1.0リリースは初期アルファ段階であり、バグ、未完成機能、APIの破壊的変更を想定する必要がある

1件のコメント

 
GN⁺ 2 시간 전
Hacker Newsのコメント
  • 本当にすごい。かなり前からカスタムCUDAカーネルと https://crates.io/crates/cudarc を使ってきたが、これはほぼドロップイン置き換えになり得そうに見える
    特にビルド時間がどう比較されるのか気になる。多くのRust CUDAクレートはCMakeやnvccの呼び出しに依存していて、コンパイルがつらいほど遅くなることがある
    ちょうど先週ビルド時間をプロファイリングしていて、sccacheのようなツールが生成物キャッシュで再ビルド時間を大きく減らせるのを見たが、それでもカスタムnvcc呼び出しのコストは残る。たとえばHugging Faceのcandleもカーネルコンパイルでカスタムnvccコマンドを呼んでいる: https://arpadvoros.com/posts/2026/05/05/speeding-up-rust-whi...
    • Cudarcは本当に良い
      Rust CUDAクレートの大半がCMakeやnvccを呼ぶせいでコンパイルが遅い、という点は個人的にはあまり経験していない。ビルドスクリプトを処理するために作った cuda_setup クレートを見ると、単なる build.rs なのでファイルが変わった時だけ再コンパイルされるし、RustのCPU側コードと比べればコンパイル時間はごく小さい
    • 他の人たちも、cuda-oxideがcudarcのほぼドロップイン置き換えのように見えると思っているのか気になる
      そうなれば本当に良いが、個人的にはおそらく補完材に近いのではないかと思う。cuda-oxideを差別化する要素が何なのか、そしてNVIDIAが完全にコントロールしているという点以上に何があるのかも気になる
  • 「直接PTXへ」というのは妙だ。最近のNVIDIA MLIRもかなり良くて速い。あるいはCuTileが使っている、より簡単で最近流行のTile IR [1] を対象にすることもできたはずだ
    Tile IRはもう少し高水準なので、ターゲットにするのはずっと簡単で、エピローグ融合のようなところでだけ不利になる
    [1] https://docs.nvidia.com/cuda/tile-ir/
    [2] https://developer.nvidia.com/cuda/tile
  • RustのメモリモデルをCUDAのセマンティクスにどう適合させたのか、かなり気になる。CUDA C++と比べて何が違うのか、Rustの型システムが実際にCUDAへより多くの安全性を与えられるのかも知りたい
    GPUカーネルを書くことは本質的に安全ではないと思う。ハードウェアの動作の仕方や、常に限界まで最適化しなければならないという点のせいで、安全な言語を作るのはあまりにも難しい
    • 大きな違いとして見えるのは4つある。第一に、cudaFree を手動で呼ぶ方式とは違って、use-after-free とdropセマンティクスを扱える
      第二に、C++の void* 引数はポインタ配列で個数しか検証しないが、ここでは cuda_launch! でカーネル引数を強制している
      第三に、可変書き込みのエイリアシング問題だ。C++では2つ以上のスレッドが同じ iout[i] に書くコードもコンパイルできるが、DisjointSliceThreadIndex には公開コンストラクタがなく、https://github.com/NVlabs/cuda-oxide/blob/2a03dfd9d5f3ecba52...index_1d, index_2d, index_2d_runtime APIだけを使うようになっている
      第四に、C++では std::string や事実上どんなPODでも cuda memcpy して状態を壊せるが、ここでは DisjointSlice、スカラー、クロージャしか受け付けない https://nvlabs.github.io/cuda-oxide/gpu-programming/memory-a...
      詳しくは https://nvlabs.github.io/cuda-oxide/gpu-safety/the-safety-mo...https://nvlabs.github.io/cuda-oxide/gpu-programming/memory-a... にある。もちろん全部を捕まえられるわけではないが、生の .cu ファイルよりは未定義動作を防ぐガードレールをずっと多く与えているように見える
    • 参考までに、Rustのメモリモデルは意図的にC++とほぼ完全に同じだ。アトミック演算も同じで、provenanceのような概念もある
      GPUプログラミングに向いた言語かどうかはまだ分からないが、GPU特有の奇妙な要素をすべて活用しつつ安全なコードを書くための、そこそこまともなDSL風APIを作れても驚かない。CUDAも結局はそういうものではないかと思う
    • ドキュメントにかなり詳しく書かれている。安全層、大部分が安全な層、安全でない層がある
      Rustの Send/Sync モデルに簡単には収めにくかった、安全ではあるが並列的な処理には、少し不格好さが必要になる
    • 目的次第だと思う。Rustでアプリケーションを書いていて、その中で時々GPU計算を使いたい立場としては、正直そこまで気にしない
      メモリモデルや所有権モデルを低い摩擦で活用できるなら良い。だが、そのせいで使い勝手が大きく悪くなるなら、そういうやり方は望まない
      基準線は今のCudarcのやり方だと思う。メモリ管理はあまり介入せず、FFIを包んだ命令型の文法と、カーネルが変わった時にnvccを呼ぶビルドスクリプトが数行ある程度だ
  • これがSlang[0] にとって何を意味するのか気になる。人々がよりモダンな言語でGPUプログラミングをしたい、というのが本質なのだろうが、今やRustを使えばよいようにも見える
    ちなみにSlangはかなり気に入っている
    [0]: https://shader-slang.org/
    • シェーダを書くことは、少なくとも現時点ではCUDAカーネルを書くこととは実質的に別物だ。シェーダは同時により高水準でもあり低水準でもあり、特定で制限されたドライバ/GPU機能セットのために設計された結果として、独特な点が多い
      たとえばディスクリプタセット、リソースレジスタ、ディスパッチ制限などだ
    • 対象が違う。Slang側はAIアルゴリズムよりグラフィックスプログラミングに関心が強い
      シェーディング言語は機能面でもよりユーザーフレンドリーだ。そのうえNVIDIAはすでにSlangを本番環境で使っており、その人たちがシェーダパイプラインをRustで書き直すことはないだろう
  • Rustと「安全な」プログラミング言語の話に関連して、NVIDIAがSpark/Adaをどう使っているのか、もっと詳しく知っている人がいるのか気になる
    見つけられるのは以下の内容だけだ
    https://www.adacore.com/case-studies/nvidia-adoption-of-spar...
  • 「DSLもなく、外国語バインディングもなく、ただのRust」という文句からして、公式CUDAポートをうたいながら導入文にもまともに気を配っていない感じがする
    それでも無視してドキュメントを読もうとしたが、カスタムIRが出てきて面白くなりかけた瞬間、「MLIRの実装はC++にTableGenを添えたもので、LLVM全体をコンパイルしなければならないビルドシステムと、キャリア選択を疑いたくなるようなデバッグセッションがある」といった調子の文を見て、もうこの業界を真面目に受け取る気がなくなった
    • コードベース全体がだいたいAIで書かれたように見える
    • WebページにAIを使っていなかったら、「なぜNVIDIAは自社サイトやドキュメントをAIで書かないのか。AI工場と何千ものエージェントを管理する社員だという自分たちの話を信じていないのか」という反応になっていただろう
      これはAI過剰宣伝企業に期待される、まさに自社製品の利用に見える
    • 名前までCUDA-oxideにしているが、Rustという言語名の由来が酸化ではなく菌類だと知らないのが透けて見える
    • 何がそんなに不満なのか正直分からない。誰かがMLIRは非常に複雑でLLVM依存だと指摘したことだろうか?
  • TileLang https://github.com/tile-ai/tilelang や Tile Kernels https://github.com/deepseek-ai/TileKernels のようなものが、いつかCUDAを時代遅れにするだろう
    • CUDAはもうほぼ20年物で、今後数年は消えないだろう
    • 根拠が少なすぎるのに、かなり大きな主張だ
  • https://nvlabs.github.io/cuda-oxide/gpu-safety/the-safety-mo... の文書を見ると、GPUカーネルは同じメモリを見る何千ものスレッド上で動き、CPU上のRustは所有権と借用でデータ競合を防ぐが、GPUではSMあたり2048スレッドが同じ関数から始まって同じ出力バッファを指すため、借用チェッカはそのために設計されていないとある
    cuda-oxideは、よくある「1スレッドが1要素を書く」というケースを構造的に安全にし、共有メモリ・ワープシャッフル・ハードウェア組み込み関数のような珍しいケースでは、文書化された契約付きの unsafe を要求し、TMA・テンソルコア・クラスタレベル通信のような最先端機能は、ハードウェアの複雑さに合わせて完全手動のままにしているという
    だがこれはあまりRustらしくない。Rustでは既存の抽象化が問題にうまく合わないなら、新しい安全な抽象化を作る。Rust for Linuxがその例だ
    安全でないのなら、Rustを使う理由は何なのか疑問だ。最後の性能を絞り出したい人にunsafe APIを提供するのは構わないが、それがデフォルトであってはならない
    io_uring やVulkanのようなAPIのユーザー空間ライブラリと比較してしまう。そうしたもの向けの安全なAPI設計はかなり難しく、実際soundではない試みもある
  • これがホストとデバイスの間で構造体を共有できるようにしてくれるのか、知っている人がいるなら気になる。既存のRust/CUDAワークフローで今まで欠けていた大きな部分がまさにそれだ
    その間のシリアライズ/バイト境界も同様だ
  • CUDAでRustを使うときに警戒していたのは、Rustが通常なら無視できる程度でも、ここでは重要になり得るわずかなオーバーヘッドを追加する点だ
    たとえば配列境界チェックが追加のレジスタ使用を招いて、カーネルの同時実行性を下げる可能性があるのか気になる