DirectML の概要

まとめ

Direct Machine Learning (DirectML) は、機械学習 (ML) 向けの低水準 API です。 ハードウェア高速化される機械学習プリミティブ (演算子と呼ばれます) が、DirectML の構成要素です。 これらの構成要素から、アップスケーリング、アンチエイリアシング、スタイル トランスファーなどの機械学習手法を開発することができます。 たとえば、ノイズ除去と超解像技術を使用すると、印象的なレイトレーシング効果を、1 ピクセルあたりの光線数を減らして実現できます。

機械学習の推測ワークロードをゲーム、エンジン、ミドルウェア、バックエンド、およびその他のアプリケーションに統合できます。 DirectML には、親しみやすい (ネイティブ C++、nano-COM) DirectX 12 スタイルのプログラミング インターフェイスとワークフローがあり、DirectX 12 対応のハードウェアすべてでサポートされています。 DirectML のサンプル アプリケーション (最小限の DirectML アプリケーションのサンプルも含まれます) については、DirectML のサンプル アプリケーションのページを参照してください。 ランディング ページも確認してください。

DirectML は、Windows 10、バージョン 1903、および Windows SDK の対応するバージョンで導入されます。

DirectML が適しているプロジェクト

DirectML は Windows Machine Learning の傘下にあるコンポーネントです。 高水準の WinML API は主にモデルを扱うものであり、"読み込み、バインド、評価" のワークフローが特徴です。 ただし、ゲームやエンジンなどを開発するときは、一般的に、より低水準の抽象化とより高度な開発者コントロールが必要になります。これは、ハードウェアの利点をフルに活用するためです。 開発するアプリケーションでミリ秒単位が重要であり、フレーム時間を短縮しているような場合は、DirectML がその機械学習のニーズを満たします。

信頼性の高いリアルタイム、高パフォーマンス、低待機時間が求められている、あるいはリソースの制約がある場合は、DirectML を使用します (WinML ではなく)。 DirectML を、既存のエンジンやレンダリング パイプラインに直接統合できます。 これよりも上のレベルで、独自の機械学習フレームワークやミドルウェアを開発する場合は、DirectML を利用すると高パフォーマンスのバックエンドを Windows 上で実現できます。

WinML 自体の実装にも、DirectML がそのバックエンドの 1 つとして使用されています。

DirectML がどの作業を行い、開発者がどの作業を行う必要があるか

DirectML は、開発者が作成した推論モデルの個々のレイヤーを GPU 上で (AI アクセラレーション コアが存在する場合はその上で) 効率的に実行します。 各レイヤーは 1 つの演算子であり、DirectML には低水準の、ハードウェア高速化される機械学習プリミティブ演算子のライブラリがあります。 DirectML 操作は、分離して実行することも、グラフとして実行することもできます (「DirectML のレイヤごとのワークフローとグラフ ベースのワークフロー」に関するセクションを参照)。

演算子とグラフは、ハードウェア固有およびアーキテクチャ固有の最適化を適用します。 開発者は、単一の、ベンダーにとらわれないインターフェイスでこれらの演算子を実行できます。

DirectML の演算子のライブラリには、機械学習のワークロードでの使用が想定される通常の操作がすべて含まれています。

  • アクティブ化演算子: linearReLUsigmoidtanh など。
  • 要素ごとの演算子: addexplogmaxminsub など。
  • 畳み込み演算子: 2D と 3D の convolution など。
  • 簡約演算子: argminaveragel2sum など。
  • プール演算子: averagelpmax など。
  • ニューラル ネットワーク (NN) 演算子: gemmgrulstmrnn など。
  • 他にも多数あります。

パフォーマンスを最大化するために、および使用しないものへの支出を防ぐために、DirectML では、機械学習ワークロードをハードウェア上でどのように実行するかを開発者が制御できるようになっています。 どの演算子をいつ実行するかを判断するのは、開発者の責任です。 開発者に判断が任されているタスクの例としては、モデルの転写、レイヤーの単純化と最適化、重みの読み込み、リソースの割り当て、バインド、メモリ管理 (Direct3D 12 と同様)、グラフの実行などがあります。

開発者は、自分のグラフについての高度な知識を保持しています (モデルを直接ハードコーディングすることや、独自のモデル ローダーをプログラミングすることができます)。 たとえば、アップスケーリング モデルを設計するとします。これには多数のレイヤーがあり、それぞれ upsampleconvolutionnormalizationactivation の演算子に対応しています。 このような熟知、慎重なスケジューリング、そしてバリア管理によって、開発者はハードウェアが持つ最大限の並列処理能力とパフォーマンスを引き出すことができます。 ゲームを開発する場合は、慎重なリソース管理とスケジューリング制御によって、機械学習のワークロードと従来のレンダリング作業を交互に実行させ、GPU を飽和状態にすることができます。

概要レベルの DirectML ワークフロー

ここでは、DirectML の使い方を概要レベルで説明します。 大きく分けて初期化と実行の 2 つのフェーズがあり、その中で作業をコマンド リストとして記録してから、このコマンド リストをキューに対して実行します。

初期化

  1. Direct3D 12 のリソースを作成します。つまり、Direct3D 12 デバイス、コマンド キュー、コマンド リスト、その他のリソース (記述子ヒープなど) です。
  2. レンダリングのワークロードに加えて機械学習の推論を行うので、DirectML のリソース (DirectML デバイスと演算子インスタンス) を作成します。 作成する機械学習モデルで特定の種類の畳み込みを、特定のサイズのフィルター テンソルと特定のデータ型で実行する必要がある場合は、これらのすべてがパラメーターとして DirectML の convolution 演算子に渡されます。
  3. DirectML によって作業が Direct3D 12 のコマンド リストとして記録されます。 したがって、初期化が完了したら、たとえば convolution 演算子のバインドと初期化をコマンド リストとして記録します。 その後で、通常どおり、コマンド リストを閉じてキューに対して実行します。

実行

  1. 重みテンソルをリソースにアップロードします。 DirectML のテンソルは、通常の Direct3D 12 リソースを使用して表現します。 たとえば、重みデータを GPU にアップロードする方法は、他の Direct3D 12 リソースをアップロードするときと同じです (アップロード ヒープ、またはコピー キューを使用します)。
  2. 次に、これらの Direct3D 12 リソースを入力と出力のテンソルとしてバインドする必要があります。 演算子のバインドと実行をコマンド リストに記録します。
  3. コマンド リストを閉じて実行します。

Direct3D 12 と同様に、リソースの有効期間と同期の責任は開発者にあります。 たとえば、DirectML オブジェクトを解放するのは、少なくともそのオブジェクトの実行が GPU 上で完了するまで待つ必要があります。

DirectML でのレイヤごとのワークフローとグラフ ベースのワークフロー

DirectML では、モデルの実行に対するレイヤごとのアプローチとグラフベースのアプローチの両方がサポートされています。 レイヤごとに実行する場合は、各 DirectML 演算子を作成および初期化し、コマンド リストで実行するために個別に記録する必要があります。 一方、グラフを実行する場合は、代わりにノードとエッジのセットを作成します。各ノードは DirectML 演算子を表し、エッジはノード間を流れるテンソル データを表します。 その後、グラフ全体が初期化または実行のために一度に送信され、DirectML はユーザーに代わって個々の演算子のスケジュール設定と記録を処理します。

どちらのパターンも、さまざまな状況で役立ちます。 レイヤごとのアプローチを使用すると、コンピューティング作業の順序とスケジュールを最大限に制御できます。 たとえば、このレベルの制御により、Direct3D 12 レンダリング ワークロードを DirectML コンピューティング ディスパッチとインタリーブできます。 これは、他の場合はアイドル状態にある GPU 上の非同期コンピューティング ユニットまたはシェーダー ユニットを利用する場合に役立ちます。 レイヤごとに手動で実行すると、テンソル レイアウトとメモリ使用量を開発者が明示的に制御することもできます。

** ただし、機械学習モデルは、多くの場合、レイヤのグラフで表現されます。 レイヤごとのアプローチの代わりに、DirectML を使用すると、モデルをノードの有向非巡回グラフ (DirectML 演算子) とそれらの間のエッジ (テンソルの説明) として表現できます。 グラフの説明を作成したら、コンパイルして DirectML に一度に送信して初期化と実行を行うことができます。 この方法では、DirectML は走査の順序を決定し、各演算子とそれらの間のデータフローをユーザーに代わって処理します。 これは多くの場合、機械学習モデルを表現するためのよりシンプルで自然な方法であり、アーキテクチャ固有の最適化を自動的に適用できます。 さらに、DirectMLX ヘルパー ライブラリには、DirectML 演算子の複雑なグラフを構築するためのクリーンで便利な構文が用意されています。

どちらの方法を使用する場合でも、同じ広範な DirectML 演算子のスイートに常にアクセスできます。 つまり、レイヤごとのアプローチのきめ細かい制御を好む場合でも、グラフ アプローチの利便性を好む場合でも、機能を犠牲にする必要はありません。

関連項目