DirectML デバッグ レイヤーの使用

DirectML デバッグ レイヤーは、DirectML コードのデバッグに役に立つオプションの開発時コンポーネントです。 有効にすると、DirectML デバッグ レイヤは DirectML API 呼び出しをラップし、開発者として追加の検証とメッセージを提供します。 デバッグ レイヤは別のライブラリ DirectML.Debug.dll に実装され、コア ランタイム ライブラリ DirectML.dll によって実行時に条件付きで読み込まれます。

DirectML を使用してアプリケーションを開発中にデバッグ レイヤーを有効にすることを強くお勧めします。無効な API を使用した場合に、貴重な情報が提供される可能性があるためです。

デバッグ レイヤ メッセージの概要

次のコード例は、デバッグ レイヤが不適切な API 使用状況の診断にどのように役立つかを示しています。 このコードは、DirectML ID 操作の構築を試みます。そのため、入力テンソルと出力テンソルの形状とデータ型は同じである必要があります。 ただし、この例では、出力テンソル パラメーターの間違いを示しています。

uint32_t sizes[] = { 1 };

DML_BUFFER_TENSOR_DESC inputBufferDesc = {};
inputBufferDesc.DataType = DML_TENSOR_DATA_TYPE_FLOAT32;
inputBufferDesc.DimensionCount = ARRAYSIZE(sizes);
inputBufferDesc.Sizes = sizes;
inputBufferDesc.TotalTensorSizeInBytes = 256;

DML_BUFFER_TENSOR_DESC outputBufferDesc = {};
outputBufferDesc.DataType = DML_TENSOR_DATA_TYPE_FLOAT16; // Invalid: doesn't match input type!
outputBufferDesc.DimensionCount = ARRAYSIZE(sizes);
outputBufferDesc.Sizes = sizes;
outputBufferDesc.TotalTensorSizeInBytes = 256;

DML_TENSOR_DESC inputDesc = { DML_TENSOR_TYPE_BUFFER, &inputBufferDesc };
DML_TENSOR_DESC outputDesc = { DML_TENSOR_TYPE_BUFFER, &outputBufferDesc };

DML_ELEMENT_WISE_IDENTITY_OPERATOR_DESC identityDesc = {};
identityDesc.InputTensor = &inputDesc;
identityDesc.OutputTensor = &outputDesc;

DML_OPERATOR_DESC opDesc = { DML_OPERATOR_ELEMENT_WISE_IDENTITY, &identityDesc };

Microsoft::WRL::ComPtr<IDMLOperator> op;
THROW_IF_FAILED(dmlDevice->CreateOperator(&opDesc, IID_PPV_ARGS(&op)));

DirectML デバッグ レイヤがないと、演算子を作成する最後の行が失敗し、E_INVALIDARG (0x80070057) が返されます。 THROW_IF_FAILED マクロ (詳細については、WIL を参照) は、そのエラー コードを汎用メッセージ "パラメーターが正しくありません" に変換し、デバッガーの出力ウィンドウに出力します。

TensorValidator.h(203)\DirectML.dll!00007FF83D25ADC9: (caller: 00007FF83D267523) Exception(1) tid(3b54) 80070057 The parameter is incorrect.

ただし、DirectML デバッグ レイヤ有効になっている場合は、原因を絞り込むための追加情報が表示されます。

D3D12 ERROR: Mismatched tensor data types. Tensor 'Output' has DataType of DML_TENSOR_DATA_TYPE_FLOAT16, while tensor 'Input' has DataType of DML_TENSOR_DATA_TYPE_FLOAT32. Both tensors are expected to have the same DataType. [ UNKNOWN ERROR #1: STRING_FROM_APPLICATION]

TensorValidator.h(203)\DirectML.Debug.dll!00007FF86DF66ADA: (caller: 00007FF86DF81646) Exception(1) tid(9f34) 80070057 The parameter is incorrect.

拡張情報が D3D12 ERROR で始まる方法に注目してください。 DirectML デバッグ レイヤで問題が検出されると、DirectML デバイスの作成時に渡された ID3D12Device に関連付けられている ID3D12InfoQueue にエラー メッセージを送信することを常に優先します。 情報キュー内のエラー メッセージには、上記のように常に D3D12 ERROR というプレフィックスが付けられます。また、Direct3D 12 デバッグ レイヤ メッセージ コールバックを使用してプログラムでアクセスすることもできます (ブログ投稿の「D3D12 デバッグ レイヤ メッセージ コールバック」を参照)。

ID3D12InfoQueue は、Direct3D 12 デバッグ レイヤが ID3D12Debug::EnableDebugLayer で有効になっている場合にのみ使用できます。 Direct3D 12 と DirectML の両方のデバッグ レイヤを一緒に有効 (または無効) にすることは常に望ましいですが、DirectML の新しいバージョンでは、Direct3D 12 デバッグ レイヤなしで基本的なパラメーター検証がサポートされます。 Direct3D 12 デバッグ レイヤが有効になっていないときに DML_CREATE_DEVICE_FLAG_DEBUG を使用して DirectML デバイスを作成すると、代わりに OutputDebugStringA を使用してエラー メッセージが出力されます。

[DIRECTML WARNING]: enable the D3D debug layer for enhanced validation with DML_CREATE_DEVICE_FLAG_DEBUG.

[DIRECTML ERROR]: Mismatched tensor data types. Tensor 'Output' has DataType of DML_TENSOR_DATA_TYPE_FLOAT16, while tensor 'Input' has DataType of DML_TENSOR_DATA_TYPE_FLOAT32. Both tensors are expected to have the same DataType.

TensorValidator.h(218)\DirectML.Debug.dll!00007FF820C43AFB: (caller: 00007FF820C01CD1) Exception(1) tid(5df8) 80070057 The parameter is incorrect.

警告メッセージが示すように、DirectML デバッグ レイヤも使用する場合は、Direct3D 12 デバッグ レイヤを有効にすることをお勧めします。 一部の種類の検証は、両方のデバッグ レイヤが有効になっている場合にのみ可能です。

DirectML および Direct3D 12 デバッグ レイヤのインストール (システム コンポーネント)

DirectML をシステム コンポーネントとして使用する場合 (「DirectML バージョン履歴」を参照)、デバッグ レイヤは個別のグラフィックス ツール パッケージの一部であり、オンデマンド機能 (FOD) として配布されます (「オンデマンド機能」を参照)。 DirectML のシステム バージョンでデバッグ レイヤを使用するには、グラフィックス ツール FOD をシステムに追加する必要があります。 FOD には Direct3D 12 デバッグ レイヤも含まれています。これは DirectML アプリケーションのデバッグにも役立ちます (ただし、必須ではありません)。

オプションのグラフィックス ツールの FOD パッケージを追加するには、管理者 Powershell プロンプトから次のコマンドを実行します。

Add-WindowsCapability -Online -Name "Tools.Graphics.DirectX~~~~0.0.1.0"

または、Windows 設定内からグラフィックス ツール パッケージを追加できます。 Windows 10 22H2 および Windows 11 では、[設定]>[システム]>[オプション機能]>[オプション機能の追加] の順に移動した後、[グラフィックス ツール] を探します。 Windows 10 22H2 よりも旧バージョンでは、代わりに [設定]>[アプリ]>[アプリ&機能]>[オプション機能]>[オプション機能の追加] の順に移動します。

DirectML デバッグ レイヤのインストール (スタンドアロン再頒布可能)

スタンドアロンの再頒布可能ライブラリとして DirectML を使用する場合 (Microsoft.AI.DirectML を参照)、DirectML デバッグ レイヤはコア ランタイム ライブラリと共にパッケージに提供されます。 DirectML.Debug.dllDirectML.dll の両方をアプリケーションの実行可能ファイルの横に配置します。

Visual Studio を使用して Microsoft.AI.DirectML を NuGet パッケージの依存関係として追加する場合、プロジェクトには、コア ランタイム ライブラリとデバッグ レイヤ ライブラリのコピーまたはコピーをスキップするオプションがプロジェクト構成ページに表示されます。 既定では、DirectML NuGet パッケージは、常に両方の DLL をプロジェクト出力フォルダーにコピーするように構成されます。 ただし、デバッグ レイヤが使用されていない場合は、リリース ビルドでデバッグ レイヤのコピーをスキップすることもできます。

Redistributable Debug Layer in Visual Studio

Direct3D 12 デバッグ レイヤの有効化

Direct3D 12 (d3d12sdklayers.dll) のデバッグ レイヤは DirectML デバッグ レイヤ (DirectML.Debug.dll) に依存しません。DirectML デバッグ レイヤは DirectML API の使用に対して強化された検証を提供し、Direct3D 12 デバッグ レイヤは Direct3D 12 API の使用を対象とします。 ただし、実際には、DirectML アプリケーションを開発するときに両方のデバッグ レイヤを有効にすることをお勧めします。 Direct3D 12 デバッグ レイヤは、上で説明したグラフィックス ツール FOD の一部としてインストールされます。 Direct3D 12 デバッグ レイヤをアクティブにする方法の例については、ID3D12Debug::EnableDebugLayer を参照してください。

重要

まず、Direct3D 12 デバッグ レイヤーを有効にする必要があります。 "次に" DMLCreateDevice を呼び出して、DirectML デバッグ レイヤーを有効にします。

DirectML デバッグ レイヤーの有効化

DMLCreateDevice の呼び出し時に DML_CREATE_DEVICE_FLAG_DEBUG を指定することで DirectML デバッグ レイヤを有効にできます。

DirectML デバッグ レイヤーを有効にしたら、すべての DirectML エラーまたは無効な API 呼び出しにより、デバッグ情報がデバッグ出力として出力されるようになります。 次に例を示します。

DML_OPERATOR_CONVOLUTION: invalid D3D12_HEAP_TYPE. DirectML requires all bound buffers to be D3D12_HEAP_TYPE_DEFAULT.

DML_FEATURE_LEVEL_5_2 までは、DirectML デバッグ レイヤを有効にするために Direct3D 12 デバッグ レイヤを有効にする必要があります。 DirectML の以前のバージョンでは、DML_CREATE_DEVICE_FLAG_DEBUG フラグがフラグで指定されていて、デバッグ レイヤがインストールされていない場合、DMLCreateDeviceDXGI_ERROR_SDK_COMPONENT_MISSING を返します。 DirectML の新しいバージョンでは、ID3D12InfoQueue が使用できない場合、メッセージは OutputDebugStringA に送信されます。

コードの例

次のコードは、デバッグ ビルドに対してのみ Direct3D 12 と DirectML の両方のデバッグ レイヤを有効にすると示しています。

// By default, disable the DirectML debug layer.
DML_CREATE_DEVICE_FLAGS dmlCreateDeviceFlags = DML_CREATE_DEVICE_FLAG_NONE;

#if defined(_DEBUG)
// If the project is in a debug build, then enable the Direct3D 12 debug layer.
// This is optional (starting in DML_FEATURE_LEVEL_5_2) but strongly recommended!
Microsoft::WRL::ComPtr<ID3D12Debug> debugController;
if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController))))
{
    debugController->EnableDebugLayer();
}

// If the project is in a debug build, then enable debugging via DirectML debug layers with this flag.
dmlCreateDeviceFlags |= DML_CREATE_DEVICE_FLAG_DEBUG;
#endif

// Create the DirectML device.
Microsoft::WRL::ComPtr<IDMLDevice> dmlDevice;
THROW_IF_FAILED(DMLCreateDevice(
    d3D12Device.Get(),
    dmlCreateDeviceFlags,
    IID_PPV_ARGS(&dmlDevice));

関連項目