版本記錄
版本號 | 時間 |
---|---|
V1.0 | 2017.10.05 |
前言
很多做視頻和圖像的,相信對
Metal Performance Shaders
框架都不是很陌生,它向您的Metal應用程序添加低級別和高性能的內核kernel
。 利用針對每個Metal GPU
系列的獨特特性進行微調的內核優化圖形和計算性能。接下來幾篇我們就詳細的解析一下Metal Performance Shaders
。
框架基本
首先看一下該框架的基本信息。
Metal Performance Shaders
框架包含一系列高度優化的計算和圖形著色器,旨在輕松高效地集成到Metal應用程序中。 這些數據并行原語被特別調整,以利用每個GPU系列的獨特硬件特性來確保最佳性能。 采用Metal Performance Shaders
框架的應用程序可以確保實現最佳性能,而無需為每個新的GPU系列更新自己的手寫著色器。 Metal性能著色器可以與應用程序的現有Metal資源一起使用(例如 MTLCommandBuffer, MTLTexture
MTLBuffer對象)和著色器。
在iOS 9和tvOS 9中,Metal Performance Shaders
框架引入了一系列常用的圖像處理內核,用于對Metal紋理進行圖像效果。
在iOS 10和tvOS 10中,Metal Performance Shaders
框架為以下內核提供了額外的支持:
- 卷積神經網絡
(CNN)
使用先前獲得的訓練數據實現和運行深入學習。 CNN是一種機器學習技術,它嘗試將視覺皮層建模為卷積,整流,合并和歸一化步驟的序列。 - 圖像處理進行顏色轉換。
- 矩陣乘法。
1. The MPSKernel Class
MPSK
內核是所有Metal Performance Shaders
內核的基礎類。 如果需要,它定義所有內核的基線行為,聲明設備運行內核,一些調試選項和用戶友好的標簽。 從這個類派生的是MPSUnaryImageKernel和MPSBinaryImageKernel
子類,它們為大多數圖像處理內核(過濾器)定義共享行為,例如邊緣模式,剪切和平鋪支持,用于消耗一個或兩個源紋理的圖像操作。 這些和MPSKernel 類都不是直接使用的。 它們只提供API抽象,在某些情況下可能允許對圖像內核對象進行一些級別的多態操作。
MPSUnaryImageKernel
和MPSBinaryImageKernel
類的子類提供專門的初始化和編碼方法來將各種圖像處理原語編碼到命令緩沖區中,并且還可以自己提供附加的可配置屬性。 許多這樣的圖像過濾器是可用的,例如:
- 卷積濾波器(Sobel,Gaussian)
- 形態運算符(擴張,侵蝕)
- 直方圖運算符(均衡,規范)
所有這些都直接在紋理和緩沖區對象上運行在GPU上。
作為MPSKernel,MPSUnaryImageKernel
和MPSBinaryImageKernel
類用于將多種圖像操作統一為簡單一致的界面和調用序列以應用圖像過濾器,子類實現與規范分歧的細節。 例如,一些過濾器可能需要一小組參數(例如,卷積內核)來管理它們的功能。 然而,使用內核子類的整體順序保持不變:
- 通過查詢 MPSSupportsMTLDevice 功能,確定
Metal Performance Shaders
框架是否支持您的設備。 - 分配通常的
Metal
對象以驅動Metal計算流水線:MTLDevice, MTLCommandQueue
和MTLCommandBuffer。 如果您的應用程序已經寫入任何命令緩沖區,Metal Performance Shaders
可以使用自己的工作負載進行編碼。 - 創建一個適當的內核 - 例如,一個MPSImageGaussianBlur
對象,如果你想做一個高斯模糊。 內核通常是輕量級的,但可以重復使用以節省一些安裝時間。 它們不能同時被多個線程使用,因此如果您的應用程序同時使用多個線程中的Metal,請添加額外的內核。 MPSKernel 對象遵守NSCopying
協議。 - 調用內核的編碼方法。 編碼調用的參數因內核類型而異,但操作類似。 他們創建一個命令編碼器,寫命令將內核運行到命令緩沖區,然后結束命令編碼器。 這意味著在調用內核的編碼方法之前,必須在當前命令編碼器上調用endEncoding方法。 在這一點上,您可以釋放內核或保留以備后續使用以節省一些設置成本。
- 如果要在命令緩沖區中編碼自己的其他命令,則必須創建一個新的命令編碼器。
- 完成命令緩沖區后,使用commit方法將其提交給設備。 然后,內核將開始在GPU上運行。 您可以使用waitUntilCompleted或 addCompletedHandler:
方法在工作完成時收到通知。
每個內核根據特定設備分配; 單個內核可能不會與多個設備一起使用。 這是必要的,因為initWithDevice:方法有時會分配緩沖區和紋理來保存作為參數傳遞給初始化方法的數據,并且需要一個設備來分配它們。 內核提供了一個copyWithZone:device:方法,允許它們被復制為新設備。
注意:內核對象不是完全線程安全的。 雖然它們可能在多線程上下文中使用,但您不應該嘗試同時將多個內核對象寫入同一個命令緩沖區。 它們在這方面與命令編碼器共享限制。 在有限的情況下,同一個內核可以同時寫入多個命令緩沖區。 但是,只有當內核被視為不可變對象時才有效。 也就是說,如果共享內核的子類屬性更改,則更改可以反映在另一個線程上,而另一個線程對其工作進行編碼,從而導致未定義的行為。 通常最安全的只是制作一個內核對象的副本,每個線程一個。
2. Tuning Hints - 調整提示
Metal Performance Shaders framework
已經針對各種設備和內核參數進行了優異的性能調整。 調整過程的重點是最小化同一命令緩沖區上的背靠背調用的CPU和GPU延遲。 然而,有可能通過將昂貴的操作引入到內核的管道中來無意中撤消此優化工作,從而導致令人失望的整體結果。
以下是避免常見錯誤的良好做法的一些要素:
- 在排隊更多的工作之前,不要等待結果完成。 通過管道到waitUntilCompleted 方法返回的地方,可以有一個明顯的延遲(高達2.5 ms)。 而是等待第一個完成時,開始對下一個命令緩沖區進行編碼。 使它們也排隊,所以他們可以在上一個退出GPU之后立即開始。 不要等待CPU內核注意到第一個命令緩沖區已完成,開始將其分開,最后在開始編寫下一個應用程序之前對應用程序進行回調。 通過允許CPU和GPU以這種方式同時工作,吞吐量可以提高高達10倍。
- 分配緩沖區和紋理有很大的代價。 這些成本可能會使CPU淹沒,從而阻止GPU的忙碌。 盡可能地預先分配和重用MTLResource對象。
- 在渲染和計算編碼器之間切換是有代價的。 每次使用新的渲染編碼器時,可能會有大量的GPU模式開關成本,這可能會破壞您的吞吐量。 為了避免成本,嘗試一起批量計算工作。 由于使用新的命令緩沖區強制您也創建一個新的命令編碼器,請嘗試使用較少的命令緩沖區來進行更多的工作。
- 對于某些圖像操作,特別是那些涉及多次通過(例如,將多個圖像濾波器連接在一起)的圖像操作,通過將工作分解成大小為約512 KB的瓦片,性能可以提高高達2倍。 使用sourceRegionForDestinationSize:方法查找每個圖塊所需的區域。
框架詳細結構
下面我們就看一下框架的詳細結構。
1. Device Support
-
MPSSupportsMTLDevice
- 決定
Metal Performance Shaders
框架是否支持Metal 器件。
- 決定
2. Image Filters
-
Image Filters
- 應用高性能過濾器,并從圖像中提取統計和直方圖數據。
3. Neural Networks
使用以前獲得的訓練數據實施和運行深入學習。
-
- 可以有多于4個通道用于卷積神經網絡的紋理。
-
- 用于卷積神經網絡的紋理,用于存儲要立即使用和丟棄的瞬態數據。
-
Objects that Simplify the Creation of Neural Networks
- 使用濾波器,圖像和狀態節點的網絡以簡化神經網絡的創建。
-
Convolutional Neural Network Kernels
- 用層建立神經網絡。
-
- 創建循環神經網絡。
4. Matrices and Vectors
-
Matrices and Vectors
- 求解方程組,分解矩陣和乘法矩陣和向量。
5. Base Types
-
-
Metal Performance Shaders kernels
的標準接口。
-
6. Reference
7. Related Symbols
8. Related Documentation
后記
未完,待續~~~~