CUDA signbit() 是否消除分歧?
Does CUDA signbit() remove divergence?
我看到有人建议使用signbit()可以消除warp divergence并提高性能。如果这是正确的,那么它是如何在 GPU 中实现的呢?在特殊功能单元 (SFU) 等中是否有用于此功能的专用硬件?
signbit()
的实现在 CUDA 版本(包括 CUDA 6.5)中开放。它可以在头文件 math_functions.h
中找到。对于较新版本的 CUDA,您可以使用 cubobjdump --dump-sass
检查机器代码以查看其实现方式。
查看 CUDA 6.5 中的头文件,可以看到 signbit()
是一个映射到内联函数的宏,该函数从浮点操作数的原始位表示中提取符号位。在 GPU 上这很容易实现,因为整数和浮点操作数共享相同的寄存器文件。在 CUDA 6.5 的情况下,符号位是用一条右移指令提取的。
所以signbit()
的实现是无分支且高效的,但是没有专门的硬件指令,因为这是不必要的。
一般来说,CUDA 程序员不需要经常担心分支,特别是当 if-then-else
涉及小主体的构造时。编译器经常使用 select 类型指令(C/C++ 三元运算符的机器等价物)的任一谓词将它们呈现为无分支代码。它还可以将统一分支与谓词结合起来。
我看到有人建议使用signbit()可以消除warp divergence并提高性能。如果这是正确的,那么它是如何在 GPU 中实现的呢?在特殊功能单元 (SFU) 等中是否有用于此功能的专用硬件?
signbit()
的实现在 CUDA 版本(包括 CUDA 6.5)中开放。它可以在头文件 math_functions.h
中找到。对于较新版本的 CUDA,您可以使用 cubobjdump --dump-sass
检查机器代码以查看其实现方式。
查看 CUDA 6.5 中的头文件,可以看到 signbit()
是一个映射到内联函数的宏,该函数从浮点操作数的原始位表示中提取符号位。在 GPU 上这很容易实现,因为整数和浮点操作数共享相同的寄存器文件。在 CUDA 6.5 的情况下,符号位是用一条右移指令提取的。
所以signbit()
的实现是无分支且高效的,但是没有专门的硬件指令,因为这是不必要的。
一般来说,CUDA 程序员不需要经常担心分支,特别是当 if-then-else
涉及小主体的构造时。编译器经常使用 select 类型指令(C/C++ 三元运算符的机器等价物)的任一谓词将它们呈现为无分支代码。它还可以将统一分支与谓词结合起来。