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具有相同的结果。

因此,通过这种解释,实现可以收缩表达式。

C 遗传的宫缩

17.4.1.2 [lib.headers] 3(2017 年的 20.5.1.2 [headers] 3 中的类似文本)说:

标准 C 库的功能在 18 个附加标头中提供,如表 12...

表12包括<cmath>,第4段表明这对应于math.h。从技术上讲,C++ 2003 标准是指 C 1990 标准,但我没有电子形式,也不知道我的纸质副本在哪里,所以我将使用 C 2011 标准(但非官方草案 N1570),C++ 2017 草案指的是。

C 标准在<math.h>中定义了一个编译指示FP_CONTRACT

#pragma STDC FP_CONTRACT on-off-switch

其中,on开关以允许收缩表达式或off不允许表达式。它还说编译指示的默认状态是实现定义的。

C++标准没有定义"设施"或"设施"。字典中"设施"的定义是"为特定目的提供的场所、便利设施或设备"(新牛津美国词典,Apple Dictionary 应用程序版本 2.2.2 (203))。便利设施是"建筑物或地点的理想或有用的特征或设施"。编译指示是为特定目的提供的有用功能,因此它似乎是一种工具,因此包含在<cmath>.

因此,使用此编译指示应允许或禁止收缩。

结论

  • FP_CONTRACT打开时允许收缩,默认情况下可能处于打开状态。

  • 8 [expr] 13的文本可以被解释为有效地允许收缩,即使FP_CONTRACT是关闭的,但不够清晰,无法确定解释。

是的,这是允许的。

例如,在Visual Studio Compiler中,默认情况下,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 = %.15en", z);
}
}

有关指定浮点行为的详细信息。

使用 GNU 编译器集合 (GCC):

FP_CONTRACT杂注的默认状态(C99 和 C11 7.12.2)。 未实现此编译指示。表达式目前仅在使用 -ffp-contract=fast-funsafe-math-optimizations-ffast-math时才签约。

相关内容

  • 没有找到相关文章

最新更新