NVIDIA GPUで高性能アルゴリズムを実装する際、CUBライブラリは必須です。しかし、従来の「2段階(two-phase)」APIは、一時ストレージのサイズ確認と割り当てを分離するため、コードが煩雑になりがちでした。この記事では、CUDA 13.1から利用可能になった新しいシングルコール(single-call) APIが開発者体験をどのように改善するかを考察します。詳細はNVIDIA開発者ブログの参考資料をご覧ください。

Server rack with NVIDIA GPU computing hardware

2段階APIの問題点

従来のパターンでは、一時ストレージのサイズを決定する呼び出しと、割り当て・実行を行う呼び出しの2回が必要でした。

// 第一呼び出し: 一時ストレージサイズの決定
cub::DeviceScan::ExclusiveSum(nullptr, temp_storage_bytes, d_input, d_output, num_items);
// 必要な一時ストレージを割り当て
cudaMalloc(&d_temp_storage, temp_storage_bytes);
// 第二呼び出し: 実際のスキャンアルゴリズムを実行
cub::DeviceScan::ExclusiveSum(d_temp_storage, temp_storage_bytes, d_input, d_output, num_items);

柔軟性はあるものの、このアプローチは繰り返しコードと、呼び出し間で変更可能なパラメータが不明確という欠点がありました。

Laptop displaying CUDA C++ code for GPU programming

新シングルコールAPIの利点

新しいAPIは全てを1行に集約します。内部的にメモリ割り当てを処理するため、パフォーマンスオーバーヘッドはありません。

機能従来の2段階API新しいシングルコールAPI
呼び出し回数2回 (サイズ確認 + 実行)1回
明示的割り当て必要 (cudaMalloc)不要 (内部処理)
コードの可読性低い (ボイラープレート多)高い
パフォーマンスオーバーヘッドなしなし
実行環境制御限定的env 引数による柔軟な制御可能

新しいAPIは env 引数を通じて、メモリリソースやCUDAストリームを渡すことができるため、従来の柔軟性も維持しています。

Data analysis and algorithm visualization on a screen

実践的なアドバイスとまとめ

cub::DeviceReduce::Sumcub::DeviceScan::ExclusiveSum などの主要アルゴリズムが新インターフェースをサポートしています。env 引数を活用すれば、カスタムメモリプールや特定のストリームを組み合わせて実行環境を細かく制御できます。パフォーマンスを損なうことなくコードを簡潔にできるこの新しい標準を積極的に導入し、GPUの計算能力を最大限に活用してください。CUDA 13.1以降で利用可能です。