Windows ML 效能和記憶體
在本文中,我們將討論如何在使用 Windows Machine Learning 時,管理應用程式的效能。
執行緒和並行處理
執行階段中公開的每個物件都是「敏捷式 (agile)」物件,表示可以從任何執行緒存取這些物件。 如需有關「敏捷式」的詳細,請參閱 C++/WinRT 中的敏捷式物件。
您將使用的一個主要物件是 LearningModelSession.。 從任何執行緒呼叫此物件都一律是安全的。
針對 GPU 會話 :物件會鎖定並同步處理並行呼叫。 如果您需要進行並行處理,則必須建立多個工作階段才能達成。
針對 CPU 會話 :物件不會鎖定,而且會允許在單一會話上進行並行呼叫。 您必須負責管理自己的狀態、緩衝區和繫結物件。
您應該留意並測量您案例的目標。 新式 GPU 架構的工作方式與 CPU 不同。 例如,如果您的目標是低延遲,您可以使用管線 (而非並行處理) 管理 CPU 和 GPU 引擎上的工作排程方式。 本文提供多引擎同步的相關資訊,是絕佳的入門文章。 如果輸送量是您的目標 (例如盡可能一次處理多個影像),您通常可以使用多執行緒和並行處理來使 CPU 飽和。
用到執行緒和並行處理時,您可以執行實驗及測量時間。 您的效能會根據您的目標和案例而大幅變更。
記憶體使用率
LearningModel 和 LearningModelSession 的每個執行個體在記憶體中都有模型的複本。 如果您使用的是小型模型,可能不會擔心,但如果您使用的是非常大型的模型,這就變得很重要。
若要釋放記憶體,請在模型或工作階段上呼叫 Dispose。 請不要只是加以刪除,因為有些語言會執行延遲記憶體回收。
LearningModel 會在記憶體中保留複本,以啟用新的工作階段建立。 當您處置 LearningModel 時,所有現有的工作階段都會繼續正常執行。 不過,您無法再使用該 LearningModel 執行個體來建立新的工作階段。 對於大型模型,您可以建立模型和工作階段,然後處置模型。 藉由針對所有 Evaluate 呼叫使用單一工作階段,您就會在記憶體中擁有單一大型模型。
Float16 支援
為了提升效能並降低模型使用量,您可以使用 ONNXMLTools 將模型轉換成 float16。
轉換之後,所有權數和輸入都會是 float16。 以下顯示您可以使用 float16 輸入和輸出的方式:
-
- 建議的使用方式。
- 將色彩和 tensorizes 轉換成 float16。
- 支援 bgr8 和 8 位元影像格式,可以安全地轉換成 float16,而不會遺失資料。
-
- 進階路徑。
- Float32 轉換成 float16。
- 對於影像而言,這可以安全地轉型,因為 bgr8 很小且符合。
- 若是非影像,繫結將會失敗,而且您必須改為傳入 TensorFloat16Bit。
-
- 進階路徑。
- 您必須轉換成 float16,並以 float32 的格式傳遞輸入,這樣會轉換成 float16。
注意
在大部分情況下,運算子仍然會執行 32 位元數學。 溢位的風險較低,且結果會被截斷為 float16。 不過,如果硬體公告 float16 支援,則執行階段將會利用它。
預先處理輸入資料
WinML 會在幕後執行一些前置處理步驟,讓處理輸入資料更簡單且更有效率。 例如,指定輸入影像可能會採用各種色彩格式和形狀,而且可能會與模型所預期的不同。 WinML 會執行影像的轉換,使其符合,進而減少開發人員的負載。
WinML 也會利用整個硬體堆疊 (CPU、GPU 等等),為特定裝置和案例提供最有效率的轉換。
不過,在某些情況下,因為您有一些特定的需求,您可能會想要手動 tensorize 您的輸入資料。 例如,您可能不想針對您的影像使用 VideoFrame,或者您想要將像素值從範圍 0-255 標準化為範圍 0-1。 在這些情況下,您可以在資料上執行自己的自訂 tensorization。 如需範例,請參閱自訂 Tensorization 範例。
注意
使用下列資源取得 Windows ML 的說明:
- 如需詢問或回答有關 Windows ML 的技術問題,請使用 Stack Overflow 上的 windows-machine-learning 標籤。
- 如需回報錯誤 (bug),請在 GitHub 上提出問題。