Windows ML 效能和記憶體

在本文中,我們將討論如何在使用 Windows Machine Learning 時,管理應用程式的效能。

執行緒和並行處理

執行階段中公開的每個物件都是「敏捷式 (agile)」物件,表示可以從任何執行緒存取這些物件。 如需有關「敏捷式」的詳細,請參閱 C++/WinRT 中的敏捷式物件

您將使用的一個主要物件是 LearningModelSession.。 從任何執行緒呼叫此物件都一律是安全的。

  • 針對 GPU 會話 :物件會鎖定並同步處理並行呼叫。 如果您需要進行並行處理,則必須建立多個工作階段才能達成。

  • 針對 CPU 會話 :物件不會鎖定,而且會允許在單一會話上進行並行呼叫。 您必須負責管理自己的狀態、緩衝區和繫結物件。

您應該留意並測量您案例的目標。 新式 GPU 架構的工作方式與 CPU 不同。 例如,如果您的目標是低延遲,您可以使用管線 (而非並行處理) 管理 CPU 和 GPU 引擎上的工作排程方式。 本文提供多引擎同步的相關資訊,是絕佳的入門文章。 如果輸送量是您的目標 (例如盡可能一次處理多個影像),您通常可以使用多執行緒和並行處理來使 CPU 飽和。

用到執行緒和並行處理時,您可以執行實驗及測量時間。 您的效能會根據您的目標和案例而大幅變更。

記憶體使用率

LearningModelLearningModelSession 的每個執行個體在記憶體中都有模型的複本。 如果您使用的是小型模型,可能不會擔心,但如果您使用的是非常大型的模型,這就變得很重要。

若要釋放記憶體,請在模型或工作階段上呼叫 Dispose。 請不要只是加以刪除,因為有些語言會執行延遲記憶體回收。

LearningModel 會在記憶體中保留複本,以啟用新的工作階段建立。 當您處置 LearningModel 時,所有現有的工作階段都會繼續正常執行。 不過,您無法再使用該 LearningModel 執行個體來建立新的工作階段。 對於大型模型,您可以建立模型和工作階段,然後處置模型。 藉由針對所有 Evaluate 呼叫使用單一工作階段,您就會在記憶體中擁有單一大型模型。

Float16 支援

為了提升效能並降低模型使用量,您可以使用 ONNXMLTools 將模型轉換成 float16。

轉換之後,所有權數和輸入都會是 float16。 以下顯示您可以使用 float16 輸入和輸出的方式:

  • ImageFeatureValue

    • 建議的使用方式。
    • 將色彩和 tensorizes 轉換成 float16。
    • 支援 bgr8 和 8 位元影像格式,可以安全地轉換成 float16,而不會遺失資料。
  • TensorFloat

    • 進階路徑。
    • Float32 轉換成 float16。
    • 對於影像而言,這可以安全地轉型,因為 bgr8 很小且符合。
    • 若是非影像,繫結將會失敗,而且您必須改為傳入 TensorFloat16Bit
  • 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 上提出問題。