0

PTX 是一种中间表示,用于将 C/C++ GPU 代码最终编译为单个微架构的 SASS 汇编语言。因此,它不应该受到特定 nVIDIA GPU 微架构的实际指令集中的特定孔/gaffs/flukes/特质的阻碍。

现在,PTX 有一条指令用于计算寄存器中前导零的数量:clz. 然而 - 它缺少相应的ctz指令,该指令计算尾随零的数量。这些操作是“对称的”,人们肯定会期望在指令集中看到两者或一个都没有——同样,特别是如果它是抽象的并且不受特定硬件上可用的东西的约束。流行的 CPU 架构已经拥有这两种架构多年了。

奇怪的是,CUDA 标头device_functions.h声明了函数

 * \brief Find the position of the least significant bit set to 1 in a 32 bit integer.
 *
 * [etc.]
 *
 * \return Returns a value between 0 and 32 inclusive representing the position of the first bit set.
 * - __ffs(0) returns 0.
 */
__DEVICE_FUNCTIONS_DECL__ __device_builtin__ int                    __ffs(int x);

这个功能:

  • 具有与计数尾随零几乎相同的语义 - 仅在全零输入上有所不同。
  • 不会转换为单个 PTX 指令,而是两个:按位否定,然后clz.
  • 也错过了它的潜在对手,__fls- 找到最后一组。

那么,这是为什么呢?为什么 PTX 中缺少一个明显显而易见的指令,以及一个与标题中几乎相同的“假内置”?

4

1 回答 1

2

一般来说,和x86架构一样,CUDA和GPU架构的很多特性都是根据客户的反馈和需求有机地积累起来的,而不是源于某种大统一的正交设计。

我个人将__ffs()__ffsll()设备函数内在函数添加到 CUDA。它们被包括在内是因为它们代表了有用的位操作原语并且与ffs()POSIX 定义的功能完全匹配。

对于位操作,特别是对于定点操作和浮点仿真的实现,CLZ是比CTZ. 最初,我在 CUDA 中将__clz()和实现__clz()为短仿真序列。硬件支持CLZ是后来添加的。我不是硬件架构团队的一员,但我有理由确定该指令是根据客户反馈添加的。

PTX 的主要目标之一是以抽象形式公开底层硬件功能,因为每一代 GPU 都会对硬件的实际微架构进行重大更改。此虚拟 ISA 旨在作为原生指令集的精简包装器。原生 GPU 指令集非常少。例如,没有关于除法的说明。简单的硬件可实现更小的裸片面积和更高的核心数。

为了为现有编译器提供一个实用的目标(CUDA 使用了 Open64 和 LLVM 工具链),一些更高级别的操作被添加到 PTX,即使缺乏底层硬件支持。由于这代表了软件支持负担,因此可能几乎没有动力添加更多此类操作。并非所有现有的仿真都具有尽可能高的性能。在 NVIDIA 任职期间,我致力于优化最重要的PTX 操作的仿真序列。

CUDA 用户可以通过错误报告机制提交增强请求(例如包含CTZ为 PTX 操作)。

于 2017-04-23T19:53:18.020 回答