2

我们在一些英特尔 FORTRAN 代码中遇到了一些奇怪的崩溃,我最终追踪到:

L_F = EXP(-L_B2*L_BETASQ*L_DS)

其中 -L_B2*L_BETASQ*L_DS 项评估为大约 -230。碰巧,EXP(-230) 的计算结果约为 1e-100。在所有其他已知情况下,L_DS 小得多,导致 EXP 的最小(已知)返回值约为 1e-50,这不会导致错误。

一旦 FORTRAN 计算子句 EXP(-230),你就会得到:

forrtl: severe (157): Program Exception - access violation
Image              PC        Routine            Line      Source

但没有其他信息。

异常 157 通常与互操作性有关,您无法在 FORTRAN 中调试 EXP,因为它找不到特定的 .c 文件——这可能意味着 EXP 是用 C 实现的(我觉得这很奇怪)。

我的假设是 FORTRAN 在 C 中实现了 EXP,但接口无法将小于 1e-100 的浮点数转换为 REAL(4)s。由于我之前认为浮点数和 REAL(4) 在字节方面是相同的,所以我无法支持这个假设——而且我在任何地方都找不到任何关于它的信息。

在我关闭这个错误之前,任何人都可以确认或否认我的假设 - 或者为我提供另一个假设吗?

此致,

麦克风

编辑: 我将把这个问题标记为已回答,因为高性能标记已经回答了直接问题。

不幸的是,我的假设是不正确的——我试图解决这个问题:

L_ARG = L_B2*L_BETASQ*L_DS

IF (L_ARG .GT. 230.0) THEN
    L_F = 0.0
ELSE
    L_F = EXP(-L_ARG)
ENDIF

不幸的是,现在(显然)异常发生在 L_ARG .GT 中。230.0 条款。这要么意味着发布模式下的调试比我想象的要糟糕,要么是某种“存储”的浮点错误(在将浮点数输入到字符串流时,请参阅“浮点无效操作”)。

4

1 回答 1

5

Fortran 没有(必然)在 C 中实现任何东西。标准内在函数的实现是特定于编译器的;通常会发现实现调用libm或其亲属之一。从英特尔(或任何其他编译器编写者)的角度来看,这是有道理的,exp用您喜欢的任何语言编写一个健壮且快速的实现,并从 Fortran、C、Ada、COBOL 以及您曾经使用过的所有其他语言中调用它听说。用 C 语言编写它甚至可能是明智的。因此,您的部分假设可能是正确的。

但是,除非您明确编写 C 代码和 Fortran 代码并从中生成单个二进制文件,否则实际上并没有任何互操作性(在 Fortran 标准意义上),所有这些肮脏的细节都对您隐藏(或应该隐藏);编译器应该生成对它用来实现的任何库的正确调用,exp并获取返回值,无论它们可能包含NaNs 和类似内容。

当然, 的值exp(-230)0.000000004 字节实数,但我看不出为什么使用 C 编写的库的 Fortran 程序会因为遇到这些数字而引发访问冲突。我认为您的程序中的其他地方更有可能出现错误,可能试图访问数组边界之外的数组元素,并且您的运行时无法在源代码中的正确位置识别它。这并不少见。

编辑

在(重新)阅读问题之前,我写了有关互操作性的内容。既然您已经澄清您正在使用互操作性功能,它可能会引起您的兴趣或使用...

你当然不能依赖你的 Fortranreal(4)和你的 Cfloat是相同的。很有可能但不确定。大多数现代 Fortran 编译器(包括 Intel 编译器)使用与其表示形式中的字节数相匹配的种类类型参数,因此代码4表明您正在处理 4 字节实数,在符合 IEEE-754 的处理器上,应该是与 C 相同float。Fortran 标准不要求这些种类类型参数与用于表示数字的字节数之间存在任何对应关系。检查编译器文档或进行一些测试总是值得的。

如果您担心互操作性,您可能应该使用 Fortran 的内在特性。例如,如果你

use :: iso_c_binding

您有许多可用的常量,包括C_FLOAT可以像这样使用的常量:

real(C_FLOAT) :: a_fortran_float

如果您的 Fortran 编译器支持此功能,a_fortran_float则应匹配配套处理器上的 C 浮点数。最后一个术语有些不确定,实际上来自同一个稳定的编译器似乎总是伴随,因为不同的稳定有时是有时不是。英特尔 Fortran 和 C 和 C++ 编译器似乎是所需意义上的伴侣。得知英特尔 Fortran 和 MS C++ 编译器不能很好地协同工作,我不会感到惊讶。

我对 C 的模糊回忆包括float标准化的不确定性,在这种情况下,如果不测试或阅读文档,您无法确定您确实在该侧确实有一个 4 字节 IEEE 单精度浮点数您的互操作。

于 2013-01-15T11:57:01.617 回答