版本記錄
版本號 | 時間 |
---|---|
V1.0 | 2018.10.07 星期日 |
前言
很多做視頻和圖像的,相信對這個框架都不是很陌生,它渲染高級3D圖形,并使用GPU執行數據并行計算。接下來的幾篇我們就詳細的解析這個框架。感興趣的看下面幾篇文章。
1. Metal框架詳細解析(一)—— 基本概覽
2. Metal框架詳細解析(二) —— 器件和命令(一)
3. Metal框架詳細解析(三) —— 渲染簡單的2D三角形(一)
4. Metal框架詳細解析(四) —— 關于GPU Family 4(一)
5. Metal框架詳細解析(五) —— 關于GPU Family 4之關于Imageblocks(二)
6. Metal框架詳細解析(六) —— 關于GPU Family 4之關于Tile Shading(三)
7. Metal框架詳細解析(七) —— 關于GPU Family 4之關于光柵順序組(四)
8. Metal框架詳細解析(八) —— 關于GPU Family 4之關于增強的MSAA和Imageblock采樣覆蓋控制(五)
9. Metal框架詳細解析(九) —— 關于GPU Family 4之關于線程組共享(六)
10. Metal框架詳細解析(十) —— 基本組件(一)
11. Metal框架詳細解析(十一) —— 基本組件之器件選擇 - 圖形渲染的器件選擇(二)
Device Selection and Fallback for Compute Processing - 計算處理的設備選擇和后退
演示如何使用多個GPU并有效執行計算密集型仿真。
本篇是macOS相關,要是看關于iOS的請忽略這篇文章。
Overview - 概覽
macOS
支持具有多個GPU的系統,使Metal應用程序能夠提高計算能力。 一個例子是iMac Pro,它具有內置的獨立GPU并連接到多個外部GPU。 外部GPU可以比內置GPU更強大,因此它們是計算密集型工作負載的絕佳選擇。 但是,為了利用這種增加的功能,Metal應該準備安全地處理添加和刪除任何外部GPU以實現更強大的執行。 無論一個GPU還是多個GPU可用于系統,Metal
應用程序應始終表現良好。
Sample Simulation Modes - 樣本模擬模式
此示例執行N-body
模擬,并在模擬進展到完成時連續呈現模擬的中間結果的子集。 模擬完成后,樣品將所有N-body
粒子渲染到最終狀態,呈現全套最終結果。
該示例以兩種模式之一運行,具體取決于系統可用的GPU數量。
Simulation with a single Metal device - 使用單個Metal設備進行模擬。 當只有一個Metal設備可用時,樣本執行模擬并連續呈現中間結果。 計算模擬和圖形渲染由同一設備在同一線程上執行。
Simulation with multiple Metal devices - 使用多個Metal設備進行仿真。當有多個Metal
設備可用時,該示例會產生第二個線程,以分隔兩個GPU之間的計算處理和圖形渲染工作。 線程并發和重復運行,共享數據如下:
- 模擬線程生成中間結果并將其傳輸到系統內存。
- 渲染線程 - 主線程 - 消耗并呈現系統內存的中間結果。 (所有圖形渲染都發生在主線程上。)
線程不會彼此等待;他們以不同的速度獨立工作。 模擬線程盡可能快地運行,渲染線程的運行速度與顯示器的幀速率一樣快。
Handle External GPU Notifications - 處理外部GPU通知
當外部GPU連接到系統時,此示例在外部GPU上執行計算模擬,并在內置GPU上執行圖形渲染。否則,該示例在單個內置GPU上執行計算和圖形工作。
當樣本收到外部GPU移除通知時,它會將所有計算模擬數據從外部GPU傳輸到應用程序的視圖控制器,后者會將數據傳輸到內置GPU。此動態響應可確保有效保留和傳輸計算模擬的結果,以便在新GPU上繼續處理。它還確保不會丟棄正在進行的工作,并且不會重新開始模擬。
當示例收到外部GPU添加的通知時,它首先使用內置GPU完成當前模擬,然后使用外部GPU啟動下一次模擬。
此示例實現了 Device Selection and Fallback for Graphics Rendering示例中描述的許多技術。有關處理外部GPU通知的信息,請參閱該示例的以下部分:
- 設置GPU彈出策略
- 注冊外部GPU通知
- 響應外部GPU通知
- 從通知中取消注冊
Transfer Simulation Data Between Devices - 在設備之間傳輸模擬數據
此示例使用兩個單獨的類來編碼Metal命令:用于計算命令的AAPLSimulation
和用于圖形命令的AAPLRenderer
。 該示例使用模擬類創建計算管道,初始化N-body
數據集并執行模擬。 該示例使用渲染器類創建渲染管道并繪制模擬生成的N-body
數據。 (該示例使用AAPLViewController
類來分隔模擬和渲染器類之間的工作。)
當示例在單個設備上運行時,視圖控制器將連續執行模擬和渲染器工作。 對于每個幀,它們都將命令編碼到相同的MTLCommandBuffer
,并且它們都通過相同的MTLBuffer
共享N-body
粒子的位置。
當示例在多個設備上運行時,視圖控制器將模擬工作分配給一個設備,渲染器工作到另一個設備。 模擬在單獨的模擬線程上循環重復執行。 對于每次迭代,它會更新N-body
粒子的位置,并將此數據blits到由系統內存支持的新MTLBuffer
。 該示例將此系統內存支持傳遞給視圖控制器,然后視圖控制器將其傳遞給渲染器。 渲染器在主線程的循環中重復執行。 對于每次迭代,它創建一個新的MTLBuffer
,由模擬線程填充的相同系統內存支持,并根據最新的可用位置數據呈現N-body
粒子。
注意:
MTLBuffer
不能直接在不同設備之間傳輸;其數據必須通過系統內存傳輸。
Allocate System Memory for a Buffer - 為緩沖區分配系統內存
該示例調用vm_allocate
函數來分配頁面對齊的緩沖區updateAddress
,由系統內存支持。 然后該示例調用newBufferWithBytesNoCopy:length:options:deallocator:
方法創建一個新的MTLBuffer,_updateBuffer
,由用于前一個緩沖區的相同系統內存支持。
void *updateAddress;
kern_return_t err = vm_allocate((vm_map_t)mach_task_self(),
(vm_address_t*)&updateAddress,
updateDataSize,
VM_FLAGS_ANYWHERE);
assert(err == KERN_SUCCESS);
_updateBuffer[i] = [_device newBufferWithBytesNoCopy:updateAddress
length:updateDataSize
options:MTLResourceStorageModeShared
deallocator:nil];
由于應用程序直接負責管理此系統內存,因此該示例調用initWithBytesNoCopy:length:deallocator
方法將updateAddress
緩沖區包裝在NSData
對象中。 此方法允許樣本注冊解除分配器deallocProvidedAddress
,以便在應用程序不再有對緩沖區的引用時釋放系統內存。
// Block to deallocate memory created with vm_allocate when the NSData object is no
// longer referenced
void (^deallocProvidedAddress)(void *bytes, NSUInteger length) =
^(void *bytes, NSUInteger length)
{
vm_deallocate((vm_map_t)mach_task_self(),
(vm_address_t)bytes,
length);
};
// Create a data object to wrap system memory and pass a deallocator to free the
// memory allocated with vm_allocate when the data object has been released
_updateData[i] = [[NSData alloc] initWithBytesNoCopy:updateAddress
length:updateDataSize
deallocator:deallocProvidedAddress];
后記
本篇主要講述了計算處理的設備選擇,感興趣的給個贊或者關注~~~