[英]How to define CUDA device constant like a C++ const/constexpr?
在.cu文件中,我在全局范圍內嘗試了以下內容(即不在函數中):
__device__ static const double cdInf = HUGE_VAL / 4;
並得到nvcc錯誤:
error : dynamic initialization is not supported for __device__, __constant__ and __shared__ variables.
如果可能的話,如何在設備上定義C ++ const / constexpr?
注1: #define
不僅僅是出於美學原因,而且因為在實踐中表達式更復雜並且涉及內部數據類型,而不僅僅是雙重。 因此,每次在每個CUDA線程中調用構造函數都會太昂貴。
注2:我懷疑__constant__
的性能,因為它不是編譯時常量,而是像用cudaMemcpyToSymbol
編寫的變量。
使用constexpr __device__
函數:
#include <stdio.h>
__device__ constexpr double cdInf() { return HUGE_VAL / 4; }
__global__ void print_cdinf() { printf("in kernel, cdInf() is %lf\n", cdInf()); }
int main() { print_cdinf<<<1, 1>>>(); return 0; }
PTX應該是這樣的:
.visible .entry print_cdinf()(
)
{
.reg .b64 %SP;
.reg .b64 %SPL;
.reg .b32 %r<2>;
.reg .b64 %rd<7>;
mov.u64 %rd6, __local_depot0;
cvta.local.u64 %SP, %rd6;
add.u64 %rd1, %SP, 0;
cvta.to.local.u64 %rd2, %rd1;
mov.u64 %rd3, 9218868437227405312;
st.local.u64 [%rd2], %rd3;
mov.u64 %rd4, $str;
cvta.global.u64 %rd5, %rd4;
// Callseq Start 0
{
.reg .b32 temp_param_reg;
// <end>}
.param .b64 param0;
st.param.b64 [param0+0], %rd5;
.param .b64 param1;
st.param.b64 [param1+0], %rd1;
.param .b32 retval0;
call.uni (retval0),
vprintf,
(
param0,
param1
);
ld.param.b32 %r1, [retval0+0];
//{
}// Callseq End 0
ret;
}
沒有constexpr功能的代碼。 您也可以使用constexpr __host__
函數,但這在CUDA 7中是實驗性的:使用nvcc命令行選項似乎是--expt-relaxed-constexpr
並在此處查看更多詳細信息(感謝@harrism)。
要使您顯示的代碼按預期編譯和工作,您需要在運行時初始化變量,而不是編譯時。 要執行此操作,請向cudaMemcpyToSymbol
添加主機端調用,例如:
__device__ double cdInf;
// ...
double val = HUGE_VAL / 4
cudaMemcpyToSymbol(cdInf, &val, sizeof(double));
但是,對於單個值,將其作為內核參數傳遞似乎更為合理。 編譯器將自動將參數存儲在所有支持的體系結構的常量內存中,並且存在“自由”常量高速緩存廣播機制,這應該使得在運行時訪問該值的成本可以忽略不計。
要初始化它,您必須使用cudaMemcpyToSymbol
。 它不是編譯時常量,而是存儲在器件的常量存儲器中,並且與全局存儲器相比具有一些優勢。 來自CUDA blogspot:
對於半warp的所有線程,只要所有線程讀取相同的地址,從常量高速緩存讀取的速度與從寄存器讀取的速度一樣快。 半個warp中的線程對不同地址的訪問被序列化,因此成本與半warp中所有線程讀取的不同地址的數量成線性比例。
您不需要使用const
,也不能使用它。 它不是c ++常量,因為您需要通過cudaMemcpyToSymbol
修改它。 因此,至少從c ++的角度來看,它不是一個“真正的”常數。 但它在設備內核中的行為類似於常量,因為您只能通過僅可從主機調用的cudaMemcpyToSymbol
來修改它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.