2012-09-20 46 views
1

我正在編寫一個需要維護每個線程的小關聯數組的CUDA內核。小的話,我的意思是最壞的情況下有8個元素,預計有兩個左右的元素;所以沒有什麼幻想;只是一個鍵和數組值的數組,索引和插入發生在所述數組上的循環。CUDA線程本地數組

現在我通過線程本地內存的方式來做到這一點;這是標識符[大小];其中size是編譯時間常量。現在我聽說在某些情況下,這個存儲器被存儲在片外,在某些情況下它被存儲在芯片上。很顯然,我希望後者在任何情況下。我知道我可以用一個共享內存塊來完成這個任務,我讓每個線程都在它自己的私有塊上工作;但真的嗎?我不想在線程之間分享任何東西,這將是一個可怕的混亂。

這條記憶去哪裏的規則究竟是什麼?我似乎無法從nvidia中找到任何單詞。爲了記錄,我正在使用CUDA5並瞄準開普勒。

回答

3

局部變量要麼存儲在寄存器中要麼存儲在片外存儲器中(緩存的計算能力大於2.0)。

如果所有的數組索引都是常量並且可以在編譯時確定,那麼寄存器僅用於數組,因爲架構無法在運行時索引訪問寄存器。

在你的情況下,鍵的數量可能足夠小,以使用寄存器(並容忍寄存器壓力的增加)。在數組訪問中展開所有循環以允許編譯器將鍵放入寄存器中,並使用cuobjdump -sass來檢查它是否實際執行。

如果你不想花掉寄存器,你可以選擇帶有每個線程偏移量的共享內存(但是檢查用於將每個線程索引保存到共享內存中的附加寄存器不會超過如你所說的,或者什麼都不做,並且使用片外「本地」內存(真正的「全局」內存,只有一個不同的尋址方案),希望緩存能夠完成工作。

如果你希望緩存保存鍵和價值觀,不要用太多的共享內存,它可能是有益的選擇48KB緩存/ 16kB的共享內存設置在使用cudaDeviceSetCacheConfig()默認16KB/48KB分裂。

+0

謝謝,很好的答案。我實際上正在編寫一個基於python的CUDA預處理器;抽象出'共享'數組機制以獲得片上每個線程的本地數組是正確的項目的衚衕,因此不太可能與此相伴。不完全確定這是我的瓶頸,並且會讓我的內核更快,但只有一種方法可以找到答案。 –

+0

最好的選擇顯然是確保8個元素駐留在寄存器中。另外一個線程局部數組是一個安全的替代方案,因爲它可能被完全緩存在L1中。我對這種使用共享內存有所保留,我預計不會超過L1緩存帶來的性能優勢,也不會實現代碼簡化。 – akk

+0

只要代碼簡單,寄存器選項似乎是最不吸引人的,不是?另外,我還要補充一點,我可能要擴展到30個左右的元素;這對我的255 kepler寄存器實際上可行是可行的,但仍然... L1和共享訪問時間如何比較?如果L1甚至相當快,那麼強烈推薦它;請記住,這30個分配的元素,可能只有3或4個在任何時候都在使用。特別是如果我交叉鍵/值對,我可以在99%的時間內從一行L1緩存中讀取數據嗎?如果是這樣,我稱自己的過早優化... –