[英]Is there a penalty to using char variables in CUDA kernels?
我似乎記得得到提示,我應該盡量避免在CUDA內核中使用char,因為SM喜歡32位整數。 使用它們會有一些速度懲罰嗎? 例如,它做得慢
int a[4];
int b = a[0] + a[1] + a[2] + a[3];
a[1] = a[3];
a2[0] = a[0]
比
char a[4];
char b = a[0] + a[1] + a[2] + a[3];
a[1] = a[3];
a2[0] = a[0]
在內核代碼?
筆記:
前面的快速說明:在C / C ++中, char
的簽名是實現定義的。 當使用char
執行8位整數運算時,因此強烈建議根據計算要求使用signed char
或unsigned char
。
可能會在CUDA中使用char
類型對性能產生負面影響。 我不建議使用char
類型,除非內存大小限制(包括共享內存大小限制)或計算的性質特別需要它。
CUDA是一種遵循基本C ++語言規范的C ++派生語言。 C ++(和C)指定在輸入計算之前,必須將類型窄於int
的表達式數據擴展為int
。 除非底層硬件的整數指令帶有內置轉換,否則這意味着需要額外的轉換指令,這將增加動態指令數量並可能降低性能。
請注意,允許編譯器在“as-if”規則下偏離抽象C ++執行模型:只要結果代碼的行為就像它遵循抽象模型,即它的語義相同,就可以消除這些轉換操作。 我最近的實驗表明,CUDA 6.5編譯器正在積極地應用這種優化,因此能夠徹底消除大多數轉換操作,或者將它們合並到其他指令中。
但是,這並不總是可行的。 一個簡單的設計示例是以下內核,當使用T = char
與T = int
實例化時,它包含一個額外的轉換指令I2I.S32.S8
。 我通過在可執行文件上運行cuobjdump --dump-sass
來轉儲機器代碼來驗證這一點。
template <class T>
__global__ void kernel (T *out, const T *in)
{
int tid = threadIdx.x;
if (threadIdx.x < 128) {
T foo = 5 * in[tid] + 7 * in[tid+1];
out [tid] = foo * foo;
}
}
除了增加指令數量之外,由於內存帶寬較低,使用char
類型也會對性能產生負面影響。 GPU的存儲器子系統的設計使得總可實現的全局存儲器帶寬通常隨着訪問的寬度而增加。 對此的一種可能解釋是跟蹤內存訪問的內部隊列的有限深度,但可能還有其他因素在起作用。
在由於用例的性質(例如圖像處理)而自然出現char
類型的情況下,人們會想要研究使用32位復合類型,例如uchar4
。 在加載和存儲操作期間使用更寬的類型允許改善的存儲器帶寬。 CUDA具有用於處理打包char
數據的SIMD內在函數 ,並且使用它們可以有利地減少動態指令計數。 請注意,SIMD內在函數僅在Kepler GPU上由硬件完全支持,在Fermi CPU上完全仿真,並在Maxwell GPU上進行部分仿真。 我已經看到軼事證據表明,與分別處理每個字節相比,即使是模擬版本仍然可以提供性能優勢。 我建議在任何特定用例的上下文中驗證。
在CUDA最佳實踐指南的第11.1.3節中也有一個非常簡短的參考問題:
編譯器必須偶爾插入轉換指令,引入額外的執行周期。 這是......的情況
- 在char或short上運行的函數,其操作數通常需要轉換為int 。
- ...
在一般意義上說,它是否會更快/更慢/不變是不可能的,盡管通常我不會期望有太大差異。 你說chars的算法是32位是正確的,但這是否需要類型轉換將取決於問題。 在問題的例子中,我希望看到編譯器將a
和b
存儲在32位寄存器中,並且在我的實驗中圍繞這個問題(注意,沒有完整的復制情況,很難保證這一點)我沒有看到SASS的差異。 對於在寄存器中完成所有操作的代碼區域,我不希望性能命中。
但是,因為char
變量被移動兩次並且從內存中移動,所以會產生影響。 由於char
必須在使用前被轉換為32位寄存器,因此會產生額外的指令。 這可能是相當大的影響,也可能不是。
現在,也有一些邊緣情況可能會有所不同。 編譯器可能能夠將多個char
打包到寄存器中並使用算術(寄存器保存與算術成本)提取它們。 您甚至可以使用聯合強制執行此行為。 保存是否值得指示將根據具體情況而有所不同。 我想不出任何其他會導致重大投射開銷的人。
很明顯,如果您可以將變量存儲在1個字節而不是4個字節中,那么您將需要節省4倍的內存和帶寬。 有些事情需要考慮:
我不知道有什么重要的理由不使用char
如果可能的話,而不是int
算術,其中一切都在寄存器中,盡管在讀/寫內存時你會支付轉換成本。 如果你小心的話,將數組存儲為char
而不是int
應該既節省帶寬又節省空間。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.