NVIDIA GPU的浮点数与IEEE 754标准合规性

涵盖NVIDIA GPU最常见问题的白皮书。

与浮点精度和合规性相关的许多问题经常在CPU和GPU上引起混淆。本白皮书的目的是讨论与NVIDIA GPU相关的最常见问题,并补充CUDA C++编程指南中的文档。

1. 简介

自1985年《二进制浮点运算标准》(IEEE 754-1985 [1])被广泛采用以来,几乎所有主流计算系统都实现了该标准,包括采用CUDA架构的NVIDIA。IEEE 754标准化了浮点运算结果的近似方式。在处理非精确结果时,编程决策会影响计算精度。为了在满足特定应用所需精度的前提下实现最高性能,必须全面考虑浮点运算行为的各个方面。在异构计算环境中尤其如此,因为运算将在不同类型的硬件上执行。

理解浮点数的复杂性以及NVIDIA硬件处理浮点数的具体方式,对于CUDA程序员实现正确的数值算法显然非常重要。此外,使用诸如cuBLAScuFFT等库的用户也会发现,了解NVIDIA底层如何处理浮点数非常有帮助。

我们将在第2章回顾浮点运算的一些基本特性。同时会讨论融合乘加运算器,该运算器于2008年被纳入IEEE 754标准[2],并内置于NVIDIA GPU硬件中。第3章通过计算两个短向量点积的实例,展示不同实现方式如何影响最终结果的精度。第4章介绍影响浮点运算的NVIDIA硬件版本和NVCC编译器选项。第5章探讨CPU与GPU结果比较的相关问题。最后在第6章,我们将为程序员提供具体建议,以处理GPU浮点运算相关的数值问题。

2. 浮点数

2.1. 格式

浮点数编码和功能定义在2008年最新修订的IEEE 754标准[2]中。Goldberg[5]对浮点数及其引发的诸多问题提供了很好的介绍。

标准规定二进制浮点数据由三个字段编码:一个1位符号字段,随后是指数字段(其编码的指数偏移量由每种格式特定的数值偏差决定),以及编码有效数(或小数部分)的位字段。

_images/sign-exponent-fraction.png

为了确保跨平台计算的一致性和浮点数据交换,IEEE 754标准定义了基本格式和交换格式。32位和64位基本二进制浮点格式分别对应C语言数据类型floatdouble。它们对应的表示形式具有以下位长度:

_images/float-double.png

对于表示有限值的数值数据,符号可以是负或正,指数字段以2为基数编码指数,小数部分字段编码有效数字但不包含最高非零位。例如,值-192等于(-1)1 x 27 x 1.5,可以表示为具有负号、指数为7和小数部分0.5。指数分别通过127和1023进行偏置,以允许指数范围从负到正。因此,指数7对应的位串值在浮点数中为134,在双精度数中为1030。整数部分1.隐含在小数部分中。

_images/float-1-double-1.png

此外,用于表示无穷大和非数字(NaN)数据的编码格式被保留。IEEE 754标准[2]完整描述了浮点数编码规范。

由于分数字段使用的位数有限,并非所有实数都能精确表示。例如,分数2/3的数学值在二进制中表示为0.10101010...,小数点后有无限位数。为了用有限精度的浮点数表示,2/3的值必须先进行舍入。IEEE 754标准中规定了舍入规则和舍入模式,最常用的是"就近舍入或偶数舍入"模式(简称就近舍入)。在此模式下舍入后的2/3值用二进制表示为:

_images/float-0-double-0.png

符号为正且存储的指数值表示-1的指数。

2.2. 运算与精度

IEEE 754标准要求支持一系列运算操作。这些操作包括算术运算(加、减、乘、除)、平方根、融合乘加运算、求余运算、类型转换运算、缩放运算、符号运算以及比较运算。对于给定的数据格式和舍入模式,标准保证所有这些运算结果在所有实现中保持一致。

由于浮点数精度的限制,数学运算的规则和性质不能直接适用于浮点运算。例如,下表展示了单精度值ABC,以及使用不同结合律计算它们和的数学精确值。

\(\begin{matrix} A & = & {2^{1} \times 1.00000000000000000000001} \\ B & = & {2^{0} \times 1.00000000000000000000001} \\ C & = & {2^{3} \times 1.00000000000000000000001} \\ {(A + B) + C} & = & {2^{3} \times 1.01100000000000000000001011} \\ {A + (B + C)} & = & {2^{3} \times 1.01100000000000000000001011} \\ \end{matrix}\)

数学上,(A + B) + C 确实等于 A + (B + C)。

设rn(x)表示对x的一次舍入操作。根据IEEE 754标准,在单精度浮点运算中以四舍五入模式执行这些相同计算,我们得到:

\(\begin{matrix} {A + B} & = & {2^{1} \times 1.1000000000000000000000110000...} \\ {\text{rn}(A + B)} & = & {2^{1} \times 1.10000000000000000000010} \\ {B + C} & = & {2^{3} \times 1.0010000000000000000000100100...} \\ {\text{rn}(B + C)} & = & {2^{3} \times 1.00100000000000000000001} \\ {A + B + C} & = & {2^{3} \times 1.0110000000000000000000101100...} \\ {\text{rn}\left( \text{rn}(A + B) + C \right)} & = & {2^{3} \times 1.01100000000000000000010} \\ {\text{rn}\left( A + \text{rn}(B + C) \right)} & = & {2^{3} \times 1.01100000000000000000001} \\ \end{matrix}\)

作为参考,上表中也计算了精确的数学结果。不仅根据IEEE 754计算的结果与精确数学结果不同,而且对应于求和rn(rn(A + B) + C)和求和rn(A + rn(B + C))的结果也彼此不同。在这种情况下,rn(A + rn(B + C))比rn(rn(A + B) + C)更接近正确的数学结果。

这个例子强调,即使所有基本运算都符合IEEE 754标准,看似相同的计算也可能产生不同的结果。

在这里,操作的执行顺序会影响结果的准确性。这些结果与主机系统无关。使用任何支持单精度浮点运算的微处理器、CPU或GPU都会得到相同的结果。

2.3. 融合乘加运算(FMA)

2008年,IEEE 754标准进行了修订,加入了融合乘加运算(FMA)。FMA运算只需一次舍入步骤即可计算\(\text{rn}(X \times Y + Z)\)。若不使用FMA运算,则结果需要通过\(\text{rn}\left( \text{rn}(X \times Y) + Z \right)\)两次舍入步骤来计算,一次用于乘法,一次用于加法。由于FMA仅使用单次舍入步骤,因此计算结果更加精确。

让我们通过一个示例来说明FMA操作的工作原理,首先使用十进制算术以便更清晰理解。假设我们要计算\(x^{2} - 1\),并保留小数点后四位精度,或者说总共五位精度(包括小数点前的前导数字)。

\(x = 1.0008\)时,正确的数学结果是\(x^{2} - 1 = 1.60064 \times 10^{- 4}\)。仅使用小数点后四位的最接近数值是\(1.6006 \times 10^{- 4}\)。此时\(\text{rn}\left( x^{2} - 1 \right) = 1.6006 \times 10^{- 4}\)对应融合乘加运算\(\text{rn}\left( x \times x + ( - 1) \right)\)。另一种方法是分别计算乘法和加法步骤。对于乘法,\(x^{2} = 1.00160064\),因此\(\text{rn}\left( x^{2} \right) = 1.0016\)。最终结果为\(\text{rn}\left( \text{rn}\left( x^{2} \right) - 1 \right) = 1.6000 \times 10^{- 4}\)

分别对乘法和加法进行四舍五入会导致结果偏差0.00064。而对应的FMA计算仅偏差0.00004,其结果最接近正确的数学答案。结果总结如下:

\(\begin{matrix} x & = & 1.0008 & \\ x^{2} & = & 1.00160064 & \\ {x^{2} - 1} & = & {1.60064 \times 10^{- 4}\text{~~}} & \text{真实值} \\ {\text{rn}\left( x^{2} - 1 \right)} & = & {1.6006 \times 10^{- 4}} & \text{融合乘加运算} \\ {\text{rn}\left( x^{2} \right)} & = & {1.0016 \times 10^{- 4}} & \\ {\text{rn}\left( \text{rn}\left( x^{2} \right) - 1 \right)} & = & {1.6000 \times 10^{- 4}} & \text{先乘后加} \\ \end{matrix}\)

以下是另一个使用二进制单精度值的示例:

\(\begin{matrix} A & = & & 2^{0} & {\times 1.00000000000000000000001} \\ B & = & - & 2^{0} & {\times 1.00000000000000000000010} \\ {\text{rn}(A \times A + B)} & = & & 2^{- 46} & {\times 1.00000000000000000000000} \\ {\text{rn}\left( \text{rn}(A \times A) + B \right)} & = & & 0 & \\ \end{matrix}\)

在这个特定情况下,计算 \(\text{rn}\left( \text{rn}(A \times A) + B \right)\) 时,先进行 IEEE 754 乘法运算再进行 IEEE 754 加法运算会导致所有精度位丢失,最终计算结果为 0。而采用融合乘加运算计算 \(\text{rn}(A \times A + B)\) 则能得到与数学理论值相等的结果。一般而言,融合乘加运算比先乘后加的计算方式能产生更精确的结果。是否使用融合运算取决于平台是否支持该操作以及代码的编译方式。

Figure 1 展示了与上述示例中输入AB及其操作对应的CUDA C++代码和输出结果。该代码在两个不同的硬件平台上执行:使用单精度SSE指令集的x86架构CPU,以及计算能力2.0的NVIDIA GPU。在本文撰写时(2011年春季),市面上尚无支持硬件FMA的x86 CPU商用产品。因此,SSE单精度计算结果将为0。而具备计算能力2.0的NVIDIA GPU确实提供硬件FMA支持,因此默认情况下执行此代码将获得更高精度的结果。但根据IEEE 754标准,两种结果都是正确的。该代码片段在编译时未针对任一平台使用特殊内联函数或编译器选项。

融合乘加运算有助于避免在减法抵消过程中损失精度。减法抵消发生在符号相反、量级相近的数值相加时。在这种情况下,许多前导位会相互抵消,导致结果中有效的精度位数减少。融合乘加运算在乘法阶段会计算双倍宽度的乘积。因此,即使在加法过程中发生减法抵消,乘积中仍保留足够的有效位,从而获得精确无误的结果。

3. 点积:精度示例

考虑计算两个短向量\(\overset{\rightarrow}{a}\)\(\overset{\rightarrow}{b}\)的点积问题,这两个向量都包含四个元素。

  • \(\overset{\rightharpoonup}{a} = \begin{bmatrix} a_{1} \\ a_{2} \\ a_{3} \\ a_{4} \\ \end{bmatrix}\mspace{2mu}\quad\overset{\rightharpoonup}{b} = \begin{bmatrix} b_{1} \\ b_{2} \\ b_{3} \\ b_{4} \\ \end{bmatrix}\quad\overset{\rightharpoonup}{a} \cdot \overset{\rightharpoonup}{b} = a_{1}b_{1} + a_{2}b_{2} + a_{3}b_{3} + a_{4}b_{4}\)

这个操作在数学上很容易表达,但在软件实现中涉及多个选择。我们将讨论的所有策略都完全遵循IEEE 754标准操作。

3.1. 示例算法

我们提出了三种算法,这些算法的区别在于乘法、加法以及可能的融合乘加运算的组织方式。这些算法展示在图2图3图4中。这三种算法都以图形方式呈现。单个操作显示为一个圆圈,箭头从参数指向操作。

计算点积的最简单方法是使用一个短循环,如图2所示。乘法和加法是分开进行的。

Serial Method to Compute Vectors Dot Product. The serial method uses a simple loop with separate multiplies and adds to compute the do t product of the vectors.

计算向量点积的串行方法。

串行方法使用一个简单的循环,通过单独的乘法和加法运算来计算向量的点积。最终结果可以表示为((((a1 x b1) + (a2 x b2)) + (a3 x b3)) + (a4 x b4))。

FMA Method to Compute Vector Dot Product. The FMA method uses a simple loop with fused multiply-adds to compute the dot product of the vectors.

计算向量点积的FMA方法。

FMA方法使用一个简单的循环结合融合乘加运算来计算向量的点积。最终结果可以表示为a4 x b4 = (a3 x b3 + (a2 x b2 + (a1 x b1 + 0)))。

对该算法的一个简单改进是使用融合乘加运算,将乘法和加法合并为一步以提高精度。图3展示了这个版本。

另一种计算点积的方法是采用分治策略:首先分别计算向量前半部分和后半部分的点积,然后通过加法合并这些结果。这是一种递归策略,其基本情况是长度为1的向量的点积计算,此时只需单次乘法运算。图4直观展示了这种方法。我们将该算法称为并行算法,因为两个子问题可以并行计算(它们之间不存在依赖关系)。不过该算法并不强制要求并行实现,仍然可以使用单线程来实现。

3.2. 对比

所有三种计算点积的算法都使用IEEE 754算术标准,可以在任何支持IEEE标准的系统上实现。事实上,在多个系统上实现串行算法将得到完全相同的结果。FMA或并行算法的实现也是如此。然而,串行算法实现计算的结果可能与其他两种算法实现计算的结果不同。

The Parallel Method to Reduce Individual Elements Products into a Final Sum.

并行方法:将各个元素乘积累加为最终总和。

并行方法使用树形结构将所有元素的乘积逐步归约为最终总和。最终结果可以表示为((a1 x b1) + (a2 x b2)) + ((a3 x b3) + (a4 x b4))。

4. CUDA与浮点运算

NVIDIA随着每一代硬件产品的推出不断扩展GPU的功能。当前NVIDIA架构如Tesla KxxGTX 8xxGTX 9xx系列,均支持符合IEEE 754标准的单精度和双精度运算,并包含对单双精度融合乘加运算的硬件支持。在CUDA中,GPU支持的特性通过计算能力数值进行编码。运行时库支持通过函数调用来确定GPU的计算能力;《CUDA C++编程指南》还包含了多种设备的计算能力对照表[7]

4.1. 计算能力2.0及以上

计算能力2.0及以上的设备支持单精度和双精度IEEE 754标准,包括单双精度的融合乘加运算。默认情况下,平方根和除法等运算将产生最接近正确数学结果的单双精度浮点值。

4.2. 舍入模式

IEEE 754标准定义了四种舍入模式:就近舍入、正向舍入、负向舍入和零向舍入。CUDA支持所有四种模式。默认情况下,运算采用就近舍入模式。通过使用如下表所列的编译器内置函数,可以为单个运算选择其他舍入模式。

模式

解释

rn

四舍五入到最接近的值,平局时取偶数

rz

向零舍入

ru

\(+ \text{∞}\)方向舍入

rd

\(- \text{∞}\)方向舍入

x + y

__fadd_[rn | rz | ru | rd] (x, y)

加法

x * y

__fmul_[rn | rz | ru | rd] (x, y)

乘法

fmaf (x, y, z)

__fmaf_[rn | rz | ru | rd] (x, y, z)

FMA

1.0f / x

__frcp_[rn | rz | ru | rd] (x)

倒数

x / y

__fdiv_[rn | rz | ru | rd] (x, y)

除法

sqrtf(x)

__fsqrt_[rn | rz | ru | rd] (x)

平方根

x + y

__dadd_[rn | rz | ru | rd] (x, y)

加法

x * y

__dmul_[rn | rz | ru | rd] (x, y)

乘法

fma (x, y, z)

__fma_[rn | rz | ru | rd] (x, y, z)

FMA

1.0 / x

__drcp_[rn | rz | ru | rd] (x)

倒数

x / y

__ddiv_[rn | rz | ru | rd] (x, y)

除法

sqrtf(x)

__dsqrt_[rn | rz | ru | rd] (x)

平方根

4.3. 控制融合乘加运算

通常情况下,融合乘加运算比执行单独的乘法和加法运算更快且更精确。但有时您可能希望禁用将乘法和加法合并为融合乘加指令的操作。要抑制这种优化,可以使用带有显式舍入模式的内联函数来编写乘法和加法运算,如前面表格所示。直接以内联函数形式编写的运算可以保证保持独立,不会被合并为融合乘加指令。也可以通过编译器标志来禁用FMA合并。

4.4. 编译器标志

IEEE 754运算相关的编译器标志包括-ftz={true|false}-prec-div={true|false}-prec-sqrt={true|false}。这些标志控制计算能力2.0及以上设备的单精度运算。

模式

标志

IEEE 754模式(默认)

-ftz=false

-prec-div=true

-prec-sqrt=true

快速模式

-ftz=true

-prec-div=false

-prec-sqrt=false

默认的IEEE 754模式表示单精度运算会按照IEEE 754标准进行正确舍入并支持非规格化数。在快速模式下,非规格化数会被刷新为零,且除法和平方根运算不会计算到最接近的浮点值。这些标志对双精度运算或计算能力低于2.0的设备没有影响。

4.5. 与x86架构的差异

NVIDIA GPU与x86架构的不同之处在于,其舍入模式被编码在每个浮点指令中,而不是动态使用浮点控制字。GPU不支持浮点异常的陷阱处理程序。在GPU上,没有状态标志来指示计算何时发生溢出、下溢或涉及不精确算术。与SSE类似,每个GPU操作的精度都被编码在指令中(对于x87架构,精度是通过浮点控制字动态控制的)。

5. 异构世界中的考量因素

5.1. 数学函数精度

到目前为止,我们只考虑了简单的数学运算,如加法、乘法、除法和平方根。这些运算足够简单,计算最佳浮点结果(例如,在四舍五入到最近时最接近的结果)是合理的。对于其他数学运算,计算最佳浮点结果则更为困难。

这个问题被称为制表者困境。要保证正确舍入的结果,通常仅将函数计算到固定的高精度是不够的。可能仍存在少数情况,高精度结果中的误差会影响低精度的舍入步骤。

对于特定函数,可以通过数学分析和形式化证明来解决这一难题[4],但大多数数学库选择放弃保证正确舍入。相反,它们提供数学函数的实现,并记录函数在输入范围内的相对误差界限。例如,CUDA中的双精度sin函数保证其精度在正确舍入结果的最后一位(ulp)的2个单位以内。换句话说,计算出的结果与数学结果之间的差异相对于浮点结果小数部分的最低有效位最多为±2。

对于大多数输入,sin函数能生成正确舍入的结果。以图6所示的C代码序列为例。我们使用gcc 4.4.3版本(Ubuntu 4.3.3-4ubuntu5)在64位x86平台上编译了这段代码序列。

这表明使用通用库计算cos(5992555.0)的结果会因代码编译模式(32位或64位)的不同而产生差异。

结果是,对于给定的输入,不能期望不同的数学库计算出完全相同的结果。这也适用于GPU编程。为GPU编译的函数将使用NVIDIA CUDA数学库实现,而为CPU编译的函数将使用主机编译器数学库实现(例如Linux上的glibc)。由于这些实现是独立的,且都不能保证完全精确,因此结果往往会略有不同。

5.2. x87与SSE

C编译器的一个不幸现实是,它们通常难以保持浮点运算的IEEE 754语义[6]。这在支持x87和SSE操作的平台上尤其令人困惑。与CUDA操作类似,SSE操作以单精度或双精度值执行,而x87操作通常使用额外的内部80位精度格式。有时使用x87的计算结果可能取决于中间结果是分配到寄存器还是存储到内存。存储到内存的值会四舍五入到声明的精度(例如,float为单精度,double为双精度)。保留在寄存器中的值可以保持扩展精度。此外,32位编译通常默认使用x87指令,而64位编译默认使用SSE指令。

由于这些问题,在CPU上保证特定的精度级别有时会比较棘手。当将CPU结果与GPU上计算的结果进行比较时,通常最好使用SSE指令进行比较。SSE指令遵循IEEE 754单精度和双精度标准。

在32位x86目标平台上,若未启用SSE指令集,使用volatile声明变量并将浮点值强制存储到内存中会很有帮助(Visual Studio中使用/Op选项,gcc中使用-ffloat-store选项)。这会将扩展精度寄存器中的结果转移到内存中,从而确保精度严格保持为单精度或双精度。另一种方法是,可以通过汇编指令fldcw或编译器选项(如gcc中的-mpc32-mpc64)来更新x87控制字,将精度设置为24位或53位。

5.3. 核心数量

如我们在第3节所示,使用IEEE 754算术计算的最终值可能取决于实现选择,例如是否使用融合乘加运算,或者加法是以串行还是并行方式组织。这些差异会影响CPU和GPU上的计算。

这种差异产生的一种原因是计算中涉及的并发线程数量不同。在GPU上,一种常见的设计模式是让一个块中的所有线程协作对块内数据进行并行归约,然后对各块的结果进行串行归约。改变每个块的线程数量会重组归约过程;如果归约是加法运算,那么这种改变相当于在长串加法中重新排列括号。

即使在CPU和GPU上使用相同的通用策略(如并行归约),GPU上的线程数量通常与CPU有显著差异。例如,GPU实现可能启动每个块128个线程的块,而CPU实现可能总共只使用4个线程。

5.4. 验证GPU结果

对于CPU和GPU上给定精度的单个IEEE 754运算,相同的输入将产生相同的结果。正如我们所解释的,有许多原因可能导致CPU和GPU上不会执行相同的运算序列。GPU具有融合乘加运算而CPU没有。并行化算法可能会重新排列运算顺序,从而产生不同的数值结果。CPU可能以高于预期的精度计算结果。最后,IEEE 754标准并不要求许多常见的数学函数必须正确舍入,因此不应期望不同实现之间会产生完全相同的结果。

将数值计算代码从CPU移植到GPU时,使用x86 CPU结果作为参考当然是有意义的。但必须谨慎解读CPU与GPU结果之间的差异。这些差异并不能自动证明GPU计算结果是错误的,也不能说明GPU存在问题。

先以高精度计算得出结果,再与低精度计算的结果进行对比,有助于判断低精度是否满足特定应用需求。但需注意,将高精度结果四舍五入为低精度,并不等同于全程使用低精度进行计算。当使用x87架构并与GPU计算结果对比时,这可能引发问题:CPU在某些或全部运算中可能意外地采用扩展高精度计算,而GPU始终仅使用单精度或双精度进行计算。

6. 具体建议

我们涵盖的关键点如下:

Use the fused multiply-add operator.

GPU上的融合乘加运算符具有高性能并能提高计算精度。在CUDA程序中无需特殊标志或函数调用即可获得这一优势。需要注意的是,CPU上目前尚未提供硬件融合乘加运算,这可能导致数值结果存在差异。

Compare results carefully.

即使在严格的IEEE 754运算标准中,诸如括号组织方式或线程数等微小细节都可能影响最终结果。在进行不同实现之间的比较时,请务必考虑这一点。

Know the capabilities of your GPU.

数值计算能力通过GPU的计算能力编号进行编码。计算能力2.0及更高版本的设备能够按照IEEE 754标准执行单精度和双精度算术运算,并具备在单精度和双精度下执行融合乘加运算的硬件单元。

Take advantage of the CUDA math library functions.

这些函数在CUDA C++编程指南[7]中有详细文档说明。数学库包含C99标准[3]中列出的所有数学函数以及一些额外实用函数。这些函数在性能与精度之间实现了合理的平衡。 我们持续致力于提升数学库功能的质量。如果您发现我们未提供您需要的函数,或任何函数的精度/性能未满足需求,请通过NVIDIA CUDA论坛1留言,或加入注册开发者计划2提交反馈报告。

7. 致谢

本文由NVIDIA公司的Nathan Whitehead和Alex Fit-Florea撰写。

感谢Ujval Kapasi、Kurt Wall、Paul Sidenblad、Massimiliano Fatica、Everett Phillips、Norbert Juffa和Will Ramey提供的宝贵意见和建议。

允许出于任何用途对本作品的全部或部分内容进行数字或纸质复制,前提是复制件保留本声明及首页的完整引用信息,且无需支付费用。

8. 参考文献

[1] ANSI/IEEE 754-1985. 美国国家标准 - IEEE二进制浮点运算标准。美国国家标准协会,纽约,1985年。

[2] IEEE 754-2008. IEEE 754–2008浮点运算标准。2008年8月。

[3] ISO/IEC 9899:1999(E). 编程语言 - C. 美国国家标准学会, 纽约, 1999.

[4] 凯瑟琳·达拉米-洛瓦特、大卫·德福尔、弗洛朗·德丹钦、马蒂厄·加莱、尼古拉·加斯特和让-米歇尔·穆勒。CR-LIBM:双精度正确舍入基本函数库,2005年2月。

[5] David Goldberg. What every computer scientist should know about floating-point arithmetic. ACM Computing Surveys, March 1991. Edited reprint available at: http://download.oracle.com/docs/cd/E19957-01/806-3568/ncg_goldberg.html.

[6] David Monniaux. 验证浮点计算的陷阱. ACM Transactions on Programming Languages and Systems, 2008年5月.

[7] NVIDIA. CUDA C++ 编程指南 10.2版, 2019.

9. 公告

9.1. 注意事项

本文档仅供信息参考之用,不应视为对产品功能、状态或质量的保证。NVIDIA公司(“NVIDIA”)对本文件所含信息的准确性或完整性不作任何明示或暗示的陈述或保证,并对其中可能存在的错误不承担任何责任。NVIDIA对于因使用此类信息而产生的后果、或因使用该信息导致的第三方专利或其他权利侵权概不负责。本文件不构成对开发、发布或交付任何材料(定义见下文)、代码或功能的承诺。

NVIDIA保留随时对本文件进行更正、修改、增强、改进以及任何其他变更的权利,恕不另行通知。

客户在下单前应获取最新的相关信息,并确认这些信息是最新且完整的。

除非NVIDIA与客户授权代表签署的单独销售协议中另有约定,否则NVIDIA产品的销售均以订单确认时提供的NVIDIA标准销售条款和条件为准(以下简称"销售条款")。NVIDIA特此明确反对将任何客户通用条款适用于本文件所述NVIDIA产品的采购。本文件不直接或间接构成任何合同义务。

NVIDIA产品并非设计、授权或保证适用于医疗、军事、航空、航天或生命支持设备,也不适用于那些可以合理预期NVIDIA产品故障或失灵会导致人身伤害、死亡、财产或环境损害的应用场景。NVIDIA对于在此类设备或应用中使用和/或包含NVIDIA产品不承担任何责任,因此客户需自行承担相关风险。

NVIDIA不声明或保证基于本文档的产品适用于任何特定用途。NVIDIA未必会对每个产品的所有参数进行测试。客户应全权负责评估和确定本文档所含信息的适用性,确保产品适合并满足客户计划的应用需求,并执行必要的应用测试以避免应用或产品出现故障。客户产品设计中的缺陷可能会影响NVIDIA产品的质量和可靠性,并可能导致超出本文档范围的其他或不同的条件和/或要求。对于任何因以下原因导致的故障、损坏、成本或问题,NVIDIA不承担任何责任:(i) 以违反本文档的任何方式使用NVIDIA产品或(ii) 客户产品设计。

本文档不授予任何NVIDIA专利权、版权或其他NVIDIA知识产权的明示或暗示许可。NVIDIA发布的关于第三方产品或服务的信息,不构成NVIDIA对这些产品或服务的使用许可或担保认可。使用此类信息可能需要获得第三方基于其专利或其他知识产权的许可,或需要获得NVIDIA基于其专利或其他知识产权的许可。

本文件中的信息仅可在获得NVIDIA事先书面批准、未经改动完整复制且完全符合所有适用的出口法律法规,并附带所有相关条件、限制和声明的情况下进行复制。

本文件及所有NVIDIA设计规格、参考板、文件、图纸、诊断工具、清单和其他文档(统称及单独称为"材料")均以"现状"提供。NVIDIA不对材料作出任何明示或默示的保证,包括但不限于对不侵权、适销性和特定用途适用性的默示保证免责。在法律允许的最大范围内,NVIDIA不就因使用本文件导致的任何损害承担责任,包括但不限于任何直接、间接、特殊、附带、惩罚性或后果性损害,无论损害成因如何,也无论责任理论为何,即使NVIDIA已被告知发生此类损害的可能性。不论客户因任何原因可能遭受的任何损害,NVIDIA对客户就本文所述产品的全部及累计责任应受产品销售条款的限制。

9.2. OpenCL

OpenCL是苹果公司的商标,经Khronos Group Inc.授权使用。

9.3. 商标

NVIDIA和NVIDIA标识是美国及其他国家NVIDIA公司的商标或注册商标。其他公司及产品名称可能是其各自关联公司的商标。

1

https://forums.nvidia.com/index.php?showforum=62

2

https://developer.nvidia.com/join-nvidia-registered-developer-program