浮点表达式有时可以在处理硬件上收缩,例如使用融合乘法和加法作为单个硬件操作。
显然,使用这些不仅仅是一个实现细节,而是受编程语言规范控制。具体来说,C89 标准不允许这样的收缩,而在 C99 中,只要定义了一些宏,它们是允许的。请参阅此 SO 答案中的详细信息。
但是 C++ 呢?不允许浮点收缩吗?在某些标准中允许吗?普遍允许?
浮点表达式有时可以在处理硬件上收缩,例如使用融合乘法和加法作为单个硬件操作。
显然,使用这些不仅仅是一个实现细节,而是受编程语言规范控制。具体来说,C89 标准不允许这样的收缩,而在 C99 中,只要定义了一些宏,它们是允许的。请参阅此 SO 答案中的详细信息。
但是 C++ 呢?不允许浮点收缩吗?在某些标准中允许吗?普遍允许?
允许收缩,但为用户提供了禁用它们的工具。标准中不明确的语言掩盖了禁用它们是否会提供预期结果的问题。
我在官方 C++ 2003 标准和 2017 n4659 草案中对此进行了调查。除非另有说明,否则 C++ 引用来自 2003 年。
两份文件中均未出现“合同”文本。但是,第 5 条表达式 [expr] 第 10 段(2017 年 8 [expr] 13 中的相同文本)说:
浮动操作数的值和浮动表达式的结果可以用比类型要求更高的精度和范围来表示;类型不会因此而改变。
我希望这个声明明确说明这个额外的精度和范围是否可以自由使用(实现可以在某些表达式中使用它,包括子表达式,而在其他表达式中不使用它)或者必须统一使用(如果实现使用额外的精度,它必须在每个浮点表达式中使用它)或根据其他一些规则(例如它可能对 使用一种精度float
,对 使用另一种精度double
)。
a*b+c
如果我们宽容地解释它,则意味着a*b
可以以无限的精度和范围来评估加法,然后可以以实现正常的任何精度和范围来评估加法。a*b+c
这在数学上等同于收缩,因为它与使用融合乘加指令进行评估具有相同的结果。
因此,通过这种解释,实现可能会收缩表达式。
17.4.1.2 [lib.headers] 3(2017 年的 20.5.1.2 [headers] 3 中的类似文本)说:
标准 C 库的功能在 18 个附加头文件中提供,如表 12 所示……</p>
表 12 包括<cmath>
,第 4 段表明这对应于math.h
。从技术上讲,C++ 2003 标准是指 C 1990 标准,但我没有电子版,也不知道我的纸质副本在哪里,所以我将使用 C 2011 标准(但非官方草案 N1570),即 C++ 2017年草案参考。
C 标准在 in 中定义了<math.h>
一个 pragma FP_CONTRACT
:
#pragma STDC FP_CONTRACT on-off-switch
其中on-off-switch是on
允许表达式收缩或off
禁止它们。它还说 pragma 的默认状态是实现定义的。
C++ 标准没有定义“facility”或“facility”。字典对“设施”的定义是“为特定目的提供的场所、便利设施或设备”(新牛津美国词典,苹果词典应用程序版本 2.2.2 (203))。便利设施是“建筑物或地方的理想或有用的特征或设施”。pragma 是为特定目的提供的有用功能,因此它似乎是一种工具,因此包含在<cmath>
.
因此,使用这个 pragma 应该允许或不允许收缩。
启用时允许收缩FP_CONTRACT
,默认情况下可能会启用。
8 [expr] 13 的文本可以解释为有效地允许收缩,即使FP_CONTRACT
是关闭的,但对于最终解释来说不够清楚。
是的,这是允许的。
例如,在 Visual Studio 编译器中,默认情况下fp_contract
是打开的。这告诉编译器尽可能使用浮点压缩指令。设置fp_contract
为off
保留单个浮点指令。
// pragma_directive_fp_contract.cpp
// on x86 and x64 compile with: /O2 /fp:fast /arch:AVX2
// other platforms compile with: /O2
#include <stdio.h>
// remove the following line to enable FP contractions
#pragma fp_contract (off)
int main() {
double z, b, t;
for (int i = 0; i < 10; i++) {
b = i * 5.5;
t = i * 56.025;
z = t * i + b;
printf("out = %.15e\n", z);
}
}
有关指定浮点行为的详细信息。
杂注的默认状态FP_CONTRACT
(C99 和 C11 7.12.2)。此编译指示未实施。表达式目前仅在使用 -ffp-contract=fast
或-funsafe-math-optimizations
时才收缩-ffast-math
。