当我们用通常的C / C ++ CUDA代码编写内联PTX程序集时,例如:
__device__ __inline__ uint32_t bfind(uint32_t val)
{
uint32_t ret;
asm ("bfind.u32 %0, %1;" : "=r"(ret): "r"(val));
return ret;
}
我们可以在volatile
之后添加asm
关键字,例如:
__device__ __inline__ uint32_t bfind(uint32_t val)
{
uint32_t ret;
asm volatile ("bfind.u32 %0, %1;" : "=r"(ret): "r"(val));
return ret;
}
CUDA documentation on inline PTX assembly说:
除了更改输出操作数之外,编译器假定
asm()
语句没有副作用。为确保在生成PTX期间不删除或移动asm
,您应该使用volatile关键字
我不明白这意味着什么。所以,
asm()
会被删除?或者更确切地说,如果编译器注意到它没有效果,我为什么要介意它被删除?asm()
被移动,为什么会出现问题?这是优化过程的一部分,不是吗?asm()
指令时,如何更准确地描述编译器的行为?答案 0 :(得分:3)
为什么我的asm()会被删除?或者更确切地说,如果编译器注意到它 没有效果,我为什么要介意它被删除?
如果编译器检测到你的内联PTX没有在线程局部范围以外的任何地方改变状态,那么可以将其作为优化删除。 一般来说,这正是您想要发生的事情。但有时候,它并不是。您的意图和编译器的优化策略可能并不总是以您想要或期望的方式相交。警告和所有这些。
如果在生成PTX期间移动了我的asm(),为什么会出现问题? 这是优化过程的一部分,不是吗?
这不是问题,是优化过程的一部分;但有时候你可能想要绕过它。想象一下你正在制作微基准测试,并且编译器决定重新排序你在内联PTX中编码的精心设计的指令序列(经典案例是将调用移到错误的位置)代码,以便定时部分或内存事务模式设计被破坏)。结果不是你想要的。我想这可能会非常令人沮丧。
如何更准确地描述编译器的行为 分别面对非易失性和易变的asm()指令?
与标准CUDA内核代码一样,volatile确保编译器尊重在其输出中发出给定的内联PTX操作,而不是将其暴露给通过代码分析进行优化。