CUDA が静的コード解析に与える影響

このブログは「CUDA's Impact on Static Code Analysis」を翻訳・一部加筆したものです。

グラフィックス処理ユニット(GPU)の活用が人工知能、機械学習、高性能計算など多様な分野で急速に広がっている中、これらのデバイス上で動作するソフトウェアアプリケーションが信頼性が高く、効率的でエラーのないものであることを確保することは不可欠です。CUDAはNVIDIAが開発したGPU向けの人気のあるプログラミングモデルで、開発者が並列処理の力を活用してアプリケーションの性能を向上させることができます。しかし、CUDA コードの分析は、固有の並列処理、バリエーション、浮動小数点値などの特性により、困難を伴います。このブログ記事では、静的解析システムが CUDA コードの分析時に直面する主な課題について解説します。

当社はこれらの課題に取り組み、Axivion Suite 7.10 から CUDA を利用するアプリケーションの解析を完全にサポートしています。

 

CUDA のコード分析における課題

テンプレートの多用

C++ テンプレートを使用する通常の利点(型チェックや定数化を含むコンパイル時評価など)は、CUDA コードにも適用されます。さらに、CUDA の性質は、テンプレートを使用する利点のいくつかを特にうまく活用しています。

  • 複数のタイプや構成で再利用可能な汎用コードを記述できることは、基盤となるハードウェアのさまざまな演算能力に対応しなければならない CUDA アプリケーションにとって非常に有益です。
  • メタプログラミング技術や、SFINAE のようなコンパイル時にコードの有効化/無効化を可能にする技術は、異なる計算能力や機能が存在する場合にバイナリのサイズを削減するのに役立ちます。

その結果、一般的な CUDA アプリケーションでは C++ テンプレートが大量に使用されています。これは CUDA 標準ライブラリや、NVIDIA が提供する cuBLAS(線形代数用)や cuDNN(ニューラルネットワーク用)などのサポートライブラリにも当てはまります。

ただし、テンプレートはコンパイラに負荷をかけ、さらに静的解析システムにも影響を及ぼします。テンプレートのコンパイルには、依存関係の解析、オーバーロードの解決、適切なインスタンス化の特定が含まれます。静的解析ツールは、純粋なソースコードだけでは必要な情報を十分に得られないため、CUDA コードを適切に解析するために同じ手順を実行する必要があります。

固有の並列性

多くの高度な解析技術は、最終的にはアプリケーションの制御フローまたはデータフローを通じて情報を伝播させることに依存しています。線形だが分岐する制御フローの場合でも既に複雑ですが、異なるスレッドのインターリーブの可能性を解析することはさらに複雑であり、より多くの計算リソースを消費します。しかし、並列性は CUDA の本質です。計算を GPU にオフロードすることは、GPU のコア数と並列化能力の恩恵を最大限に活用できます。

これにより、分析ツールが潜在的な問題行動を検出するために探索する必要のあるプログラムの行動の検索空間が爆発的に拡大します。さらに、これらのシステムでは新たな種類の課題が発生する可能性があり、静的解析システムで検出する必要があります。例えば、デッドロック、データレース、共有メモリの不正使用などが挙げられます。

 

バリエーションと計算機能

計算機能とは、NVIDIA GPU のアーキテクチャおよび CUDA カーネルを実行する能力を指します。各計算機能は NVIDIA GPU の特定の世代を表し、新しい世代ほど通常、パフォーマンス、電力効率、および高度な機能のサポートが向上しています。

古いハードウェアと新しいハードウェアを同時にサポートするため、CUDA アプリケーションは計算機能に対応する必要があります。これらは、コンパイル時に条件付きコンパイルと __CUDA_ARCH__ マクロを使用するか、実行時に compute_capability() 関数を使用して動的に行うことができます。以下の例を参照してください。

void perform_operation(…) {
#ifdef(__CUDA_ARCH__) && __CUDA_ARCH__ >= 302
   // code using features available in the architectures
#else
   // code for older architectures' capabilities
#endif
}

void perform_operation(…) {
   cudaDeviceProp prop;
   cudaGetDeviceProperties(&prop, 0);
   if (prop.major * 10 + prop.minor >= 30) {
      // code using features available in the architectures
   } else {
       // code for older architectures' capabilities
   }
}

両方のアプローチは静的解析システムに影響を及ぼします。静的解析の場合、計算能力はコンパイル時に決定されるため、解析ツールは対象のコードを検証する際、どの分岐(または2つの解析では両方の分岐!)を選択するかを決定する必要があります。

これはソフトウェア製品ラインを考慮する際の複雑さの増加と類似していますが、同一ではありません。ただし、製品ラインを考慮する際は、各実現形態が直接相互作用しないため、通常はそれぞれを個別に考慮すれば十分です。CUDAの場合、異なるデバイス向けに異なるバージョンをコンパイルし、同じアプリケーション内で使用することが完全に可能です。したがって、解析ツールは解析対象のアプリケーションの異なるバージョンをコンパイルし、それらを同時に解析する必要があります。

同様に、動的ケースでは考慮する必要のあるバリエーションが増加するのではなく、考慮する必要のある制御フローの複雑さが増加します。

 

浮動小数点値

グラフィックス処理にルーツを持つ GPU および NVIDIA の AI 専用チップは、浮動小数点データ、さらには倍精度浮動小数点データを第一に処理します。これは、科学計算や機械学習といった主な用途には適していますが、静的解析システムが通常適用される分野では珍しいものです。実際、安全クリティカルシステム向けのよく知られたMISRAルールセットは、浮動小数点数とその演算の使用を一定程度禁止しています。したがって、ツールは浮動小数点値の分析に最適化されていません。さらに、浮動小数点数は、丸め処理、精度処理、メモリ内の表現方法、その他の特殊な動作のため、分析が困難です。

しかし、CUDAやさまざまなAIライブラリ・システムによる浮動小数点数への新たな注目は、MISRAやCERTなどの他のルールセットの結果改善にも寄与するでしょう。同時に、これらのルールセットの例をCUDAに拡張することで、どのような性質が合理的にチェックすべきか、最初の印象を得ることができます。

例えば、CERT C(C++にも一部適用可能)には、CUDAアプリケーションでも遵守すべき浮動小数点に関する3つのルールが含まれています。

  • FLP34: 浮動小数点変換が新しい型の範囲内にあることを確認。つまり、浮動小数点数を変換する際に精度やデータの損失が発生しないことを確認します。異なる計算能力について考える場合、デバイスによって異なる精度も考慮に入れる必要があります。
  • FLP36-C: 整数値を浮動小数点型に変換する際は精度を維持。つまり、整数から浮動小数点数を作成する際は、データ損失が発生しないことを再度確認します。整数と浮動小数点数の範囲は完全に重ならないため、最小値または最大値の単純な比較では不十分です。代わりに、個々のプラットフォームの個々の特性を再度考慮する必要があります。
  • FLP37-C. 浮動小数点値の比較にオブジェクト表現を使用しないこと。異なる浮動小数点表現を使用するデバイスを含むシステムを考慮する場合、このルールはさらに重要性が増します。これらのシステムは、浮動小数点数のビット単位の個々の表現に関する知識に依存できません。

まとめ

CUDAコードを解析することには、静的解析に特有のいくつかの課題があります。CUDAプログラミングの複雑さを理解し、それに応じて解析手法を調整することで、AxivionはCUDAコードを含む場合でも、安全性が求められるアプリケーションを高い品質と保守性をもって開発できるよう支援します。GPUの利用はさまざまな安全重視の分野で広がり続けており、信頼性の高いCUDAアプリケーションの重要性は今後さらに高まるでしょう。AxivionはこうしたCUDA特有の課題に対応することで、時代の一歩先を行く静的解析ツールを提供し、高い基準を満たすソフトウェア開発をサポートしています。

 

Axivion for CUDA の詳細をご覧になるか、弊社の専門家にデモをご依頼ください。


Blog Topics:

Comments