我想编写对float和double精度都有效的代码。 我正在做这样的事情:
typedef real float;
//typedef real double;
__global__ void foo(real a, real *b){
b[0] = real(0.5)*a;
}
int main(){
real a = 1.0f;
real *b;
cudaMalloc(&f, sizeof(real));
foo<<<1,1>>>(a,b);
return 0;
}
这让我思考,我不想在执行双精度时将常量中的精度松散为0.5f,但我不希望在进行单精度时将0.5提升到双倍!
所以我最终使用了运算符real(),如示例所示。 在单精度模式下,如果我使用real(0.5)反汇编函数'foo',我认为没有促销加倍,而只使用0.5,促销发生。
您可以使用以下方式查看:
$nvcc test.cu -arch=sm_52 -lineinfo --source-in-ptx -g -G -O0 ; cuobjdump -sass a.out | grep "foo" -A 35
我看到了
/*0078*/ FMUL R0, R0, 0.5; /* 0x3868004000070000 */
使用real(0.5)或0.5f时 和
/*0078*/ F2F.F64.F32 R4, R0; /* 0x5ca8000000070b04 */
/*0088*/ DMUL R4, R4, 0.5; /* 0x3880004000070404 */
/*0090*/ F2F.F32.F64 R0, R4; /* 0x5ca8000000470e00 */
仅写0.5时。
这可能听起来太明显了。但由于我不知道什么是“真实(0.5)”,我不知道这是否只是编译器在这个非常特殊的情况下播放。反汇编代码在real(0.5)和0.5f中都是相同的!
所以问题仍然存在:
什么是真实的(0.5)(AKA浮点数(0.5))究竟在做什么?
float(0.5)和0.5f之间有什么区别吗? (或双倍(0.5)和0.5)
我想这也适用于C / C ++。
答案 0 :(得分:4)
real(0.5)
function-style cast,在这种情况下,降至static_cast
real(0.5)
static_cast<real>(0.5) //exactly the same thing
这意味着a
与real
变量相乘(在本例中为float
),这意味着无需对double
进行宣传,就像double * float
乘法的情况。
有人可能会说float
与0.5
的初始化可能会在运行时发生,但这对于任何现代编译器都是不现实的。它应该是一个无操作,它已经是OP。
除此之外,使用float(0.5f)
与使用0.5f
没有任何区别,double(0.5)
和0.5
也是如此。