是否可以仅针对某些特定的C ++ 11代码段{激活|取消激活} SIGFPE生成?

时间:2017-11-05 01:42:16

标签: linux c++11 exception floating-point ieee-754

我在Linux上用C ++ 11编写路径跟踪器,用于光传输的数值模拟,我正在使用

#include <fenv.h>
...
feenableexcept( FE_INVALID   | 
                FE_DIVBYZERO | 
                FE_OVERFLOW  | 
                FE_UNDERFLOW );

以捕获和调试在执行期间最终可能发生的任何数字错误。

在代码中的某个点上,我必须计算光线(线段)与轴对齐边界框(AABB)的交点。对于这种计算,我使用了非常优化且稳健的ray-box intersection algorithm,它依赖于IEEE 754标准中描述的一些特殊值(例如NaN和inf)的生成。显然,我对捕获这个光线盒交叉例程专门生成的浮点异常不感兴趣。

因此,我的问题是:

  1. 是否可以仅为代码的某些部分(即光线盒交叉点代码部分)停用浮点异常信号(SIGFPE)的生成?
  2. 当我们计算模拟时,我们非常关注 性能。在可以抑制异常的情况下 仅针对特定代码段的信号,可以在此处完成 编制时间(即在其编制过程中检测/取消检测代码) 生成,这样我们可以避免昂贵的函数调用)?
  3. 感谢您的帮助!

    更新

    可以通过使用feenableexceptfedisableexcept函数调用来检测/删除代码(实际上,我发布了这个问题,因为我不知道fedisableexcept,只有{ {1}} ......对我感到羞耻!)例如:

    feenableexcept

1 个答案:

答案 0 :(得分:1)

标准C ++没有提供任何方法在编译时标记代码是否应该在启用或禁用浮点陷阱的情况下运行。实际上,标准不需要支持操作浮点环境,因此实现是否完全依赖于实现。除标准C ++之外的任何答案都取决于您使用的特定硬件和软件,但您尚未报告该信息。

在典型的处理器上,通过更改处理器控制寄存器来实现启用和禁用浮点捕获。您不需要执行函数调用,但正如您在问题中所建议的那样,函数调用并不昂贵。实际指令可能消耗时间,因为它可能需要处理器序列化指令执行。 (现代处理器可能同时执行数百条指令 - 一些正在解码,一些等待处理器内的子单元,一些处于不同的计算阶段,一些等待将结果写入通用寄存器,等等。一个控制寄存器,处理器可能必须等待所有当前正在执行的指令完成,然后更改寄存器,然后开始执行新的指令。)如果您的硬件以这种方式运行,则无法绕过它。 (使用这种常见的硬件,如果没有实际执行运行时指令来更改控制寄存器,则无法编译代码来运行或不运行。)

您可以通过批处理路径跟踪计算来减少时间成本,因此它们只在对浮点控制寄存器进行两次更改的组中执行(一个用于关闭陷阱,一个用于打开它们)整个小组。