最近在做有關Cuda的一個項目, 碰到匪夷所思的問題,在異步的時候發現並沒有達到預期的效果,程序沒有異步起來,然後在網上找了一個Nvida的有關Cuda Streams的一個ppt,然後照着裏面的提示,使程序達到了異步的效果。
首先,先回顧一下簡單的簡單的處理流程。
- 將數據從CPU內存中拷貝到GPU內存中。
- 啓動一個GPU的kernel。
- 將結果從GPU內存中拷貝到CPU的內存中。
- 重複上面的操作。
在Pipelining中的併發相比於串型可以提高性能。
我們可以發現在併發的情況下,程序的運行速度有顯著提高。在Tile DGEMM的實驗中,將CPU的浮點數運算作爲baseline, 當串型使用GPU(K20X)時,達到519Gflop/s(提高2.3倍),當兩路併發時,達到了663Gflop/s(提高3倍),當3路併發時,速度達到990Gflops/s(提高4倍),在GPU和CPU同時的4路併發中,速度達到了1180Gflops/s(提高了5.3倍)。
通過MPS(Multi-process service)進行併發
背景介紹:
- 要求每一個進程擁有唯一的context。
- 設備上一次只能有一個context處於活躍狀態。
- 在單GPU上的多個進程不能併發操作。
MPS是驅動和應用之間的軟件層。
- 可以一個context可以涵蓋所有的CUDA調用。
- 多個進程可以併發的進行處理。
MPS的優點:
- Oversubscribe MPI 進程並自動進行併發操作。
- 簡單自然的加速路徑。(特別是當應用中已經準備好MPI)
MPS的缺點:
- MPS增加了啓動的延遲。
- 在舊的硬件上不支持。(Kepler或者之後的架構)
- 只能在Linux上使用
鑑於MPS的侷限性,可以考慮通過Streams方式來進行併發。
通過Streams進行併發
Cuda調用對於主機端來說不是同步的就是異步的,
- 同步:把work入隊然後等待工作完成。
- 異步:work入隊之後立刻返回。
運行的kernel會自動異步地overlap主機端。