DirectML 偵錯層是選擇性的開發時間元件,可協助您偵錯 DirectML 程式代碼。 啟用時,DirectML 偵錯層會包裝 DirectML API 呼叫,並提供額外的驗證和訊息給身為開發人員。 偵錯層會在個別的連結庫中實作, DirectML.Debug.dll其會在運行時間由核心運行時間連結庫 DirectML.dll有條件地載入。
強烈建議您在使用 DirectML 開發應用程式時啟用偵錯層,因為它可以在 API 使用量無效時提供寶貴的資訊。
偵錯層訊息概觀
下列程式代碼範例說明偵錯層如何協助診斷不正確的 API 使用量。 此程式代碼會嘗試建構 DirectML 身分識別作業;因此輸入和輸出張量應該具有相同的圖形和數據類型。 不過,在此範例中,我們展示輸出張量參數中的錯誤。
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 錯誤開始。 當 DirectML 偵錯層偵測到問題時,它一律偏好將錯誤訊息傳送至與 DirectML 裝置建立期間傳入之 ID3D12Device 相關聯的 ID3D12InfoQueue。 資訊佇列中的錯誤訊息一律會加上 D3D12 ERROR,如上所示;而且也可以使用 Direct3D 12 偵錯層訊息回呼,以程式設計方式存取它們(請參閱部落格文章 D3D12 偵錯層訊息回呼)。
只有在使用ID3D12Debug::EnableDebugLayer 啟用 Direct3D 12 偵錯層時,才能使用ID3D12InfoQueue。 雖然最好同時啟用 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)(請參閱 功能隨選)。 圖形工具 FOD 必須新增至您的系統,才能將偵錯層與 DirectML 的系統版本搭配使用。 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.dll和DirectML.dll都放在應用程式的可執行檔案旁邊。
如果您使用 Visual Studio 設定 Microsoft.AI.DirectML 為 NuGet 套件相依性,專案組態頁面將會顯示選項,以複製或略過複製核心執行階段與偵錯層庫。 根據預設,DirectML NuGet 套件會設定為一律將這兩個 DLL 複製到您的項目輸出資料夾。 不過,如果未使用偵錯層,您可能會想要略過在發行組建中複製偵錯層。
啟用 Direct3D 12 偵錯層
Direct3D 12 (d3d12sdklayers.dll) 的偵錯層與 DirectML 偵錯層無關:DirectML.Debug.dllDirectML 偵錯層提供 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之前,您必須啟用 Direct3D 12 偵錯層,才能啟用 DirectML 偵錯層。 在舊版的 DirectML 中,如果旗標中指定了DML_CREATE_DEVICE_FLAG_DEBUG旗標,而且未安裝偵錯層,則 DMLCreateDevice 會傳回DXGI_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));