隨著GPU可程式化效能的增強以及GPGPU技術的不斷髮展,人們希望基於流處理器模型的GPU能夠像CPU一樣,在支援流程分支的同時,也允許對儲存空間進行靈活的讀寫操作。在進行早期的GPU通用可程式化技術研究時,Ian Buck [1]就曾經指出,缺乏靈活的儲存空間操作,是制約GPU完成複雜計算任務的關鍵,因此他在設計Brook [2]時增加了對scatter/gather特性的支援,但是其實現過程仍然是通過一些以犧牲效能為代價的技巧完成的。
在GPU中scatter/gather的實現與第一向量機中的很相似,scatter允許將資料輸出到非連續的儲存空間地址內,而gather則允許從非連續的儲存空間地址內讀取資料。因此如果認為儲存空間(如DRAM)是一個二維數組,scatter可以看作利用下標將資料寫入數組中的任意位置,即a[i] = x,而gather可以看作是利用下標從數組中的任意位置讀出資料,即x = a[i]。
在CUDA [5]的架構中(圖1),每個ALU可以看作是一個處理核心,通過scatter/gather操作,多個ALU間可以共用儲存空間,實現對任意地址資料的讀寫操作。
圖1:CUDA的scatter/gather
scatter/gather有什麼用?
舉個常見的排序例子,如果要我們對一個數組中的資料進行排序,最直接的想法就是用冒泡演算法,即通過遍曆數組找到其中最大的數,將它與隊列中的第一個資料對調,然後將剩餘數組中第二大的數與第二個資料對調,依次執行直到剩下數組的最後一項時排序結束。在這個過程中,兩個資料項目的對調,在儲存空間操作上,就可以通過對數組中的任意位置讀取和寫入資料來完成。
上面的例子在CPU上很容易實現,因為IA(Intel Architecture)架構的處理器架構是支援scatter/gather操作的。但是在GPU上,由於存在vertex shader與fragment shader,以及流處理器模型對並行性的追求,情況變得有點複雜。
GPU中的scatter/gather實現
先說fragment shader,因為可以對紋理進行預取(fetch),並通過紋理座標的調節擷取紋理中的任意資料 [4],所以片段處理器實際上可以從儲存空間(顯存)中的任意地址讀取資料,也就是說能夠實現gather操作。但是反過來看,fragment shader的輸出只能指向特定的片段,而且必須是依據固定順序排列的,因此fragment shader實際上並不能夠實現scatter操作。
但是,利用多渲染對象(render to texture)以及多次渲染(multi-pass rendering)技術,可以將前一次渲染出的資料以紋理形式儲存,並作為下一次渲染的輸入,即通過從任意位置讀取資料的方式來彌補無法向任意位置寫入資料的缺陷。這樣,只要規劃好資料的索引(紋理座標),是可以在多次渲染過程中實現偽scatter效果的。這也就是大家通常都感覺fragment shader比vertex shader用起來靈活的原因,但這種靈活是以耗時的多次渲染和佔用大量儲存空間空間為代價的。
再來看vertex shader,一般在對頂點流中的每個頂點進行處理時,只能夠針對當前頂點的一些資料進行處理,而無法同時使用多個頂點的資料,這就意味著無法實現對儲存空間任意地址的資料進行讀寫操作,也就是不具備scatter/gather功能。
但是隨著vertex texture技術的出現,vertex shader能夠像fragment shader一樣通過紋理採樣的方式從紋理中擷取資料,因此就具備了從儲存空間的任意位置讀取資料的gather能力。
而Geometry shader的出現以及vertex buffer技術的發展,為幾何處理過程中實現scatter操作提供了可能。無論是DirectX10還是即將推出的OpenGL 3.0 [6],都提出了幾何處理過程中需要具備資料反饋(feed-back)與多次操作(multi-pass)的能力(圖2),這實際上已經讓我們看到了幾何處理階段實現scatter的可能。
圖2:DirectX 10 pipeline
結論
在GPGPU領域中,儲存空間的靈活操作至關重要,隨著圖形處理器的發展,人們已經可以在處理流水線的各個階段實現並行的的scatter/gather操作。但是考慮到圖形處理器中的資料精度、儲存空間操作效能等因素,在目前階段,GPU中的scatter/gather操作仍然存在很大局限,這一方面限制了GPGPU領域的發展,但同時也為圖形處理器今後的發展指明了方向。
參考文獻
1. Ian Buck, Pat Hanrahan, "Data Parallel Computation on Graphics Hardware"
2. Ian Buck, Tim Foley, "Brook for GPUs: Stream Computing on Graphics Hardware"
3. Ian Buck, “Stream Computing On Graphics Hardware”, Ph.D. 2004
4. Timothy John Purcell, "Ray Tracing on a Stream Processor", 2004, p19
5. Nvidia, “CUDA Programming Guide”, 2007
6. Evan Hart, “New OpenGL Features”, 2006, GDC 2007
7. Christophe, “OpenGL Vertex Buffer Objects”, 2006, http://www.ozone3d.net//tutorials//opengl_vbo_p1.php