我不时地读到Fortran在繁重的计算中比C更快。这是真的吗?我必须承认我几乎不懂Fortran,但是到目前为止我看到的Fortran代码并没有显示出该语言具有C语言所不具备的特性。

如果是真的,请告诉我原因。请不要告诉我什么语言或库适合处理数字,我不打算写一个应用程序或库来做这个,我只是好奇。


当前回答

There is another item where Fortran is different than C - and potentially faster. Fortran has better optimization rules than C. In Fortran, the evaluation order of an expressions is not defined, which allows the compiler to optimize it - if one wants to force a certain order, one has to use parentheses. In C the order is much stricter, but with "-fast" options, they are more relaxed and "(...)" are also ignored. I think Fortran has a way which lies nicely in the middle. (Well, IEEE makes the live more difficult as certain evaluation-order changes require that no overflows occur, which either has to be ignored or hampers the evaluation).

另一个更聪明的规则领域是复数。这不仅是因为直到c99才有了它们,而且Fortran中管理它们的规则更好;由于gfortran的Fortran库部分是用C编写的,但实现了Fortran语义,GCC获得了这个选项(也可以用于“普通”C程序):

-fcx-fortran-rules 复杂的乘法和除法遵循Fortran规则。范围缩减是作为复杂除法的一部分进行的,但是没有检查复杂乘法或除法的结果是否是“NaN + I*NaN”,试图在这种情况下挽救这种情况。

The alias rules mentioned above is another bonus and also - at least in principle - the whole-array operations, which if taken properly into account by the optimizer of the compiler, can lead faster code. On the contra side are that certain operation take more time, e.g. if one does an assignment to an allocatable array, there are lots of checks necessary (reallocate? [Fortran 2003 feature], has the array strides, etc.), which make the simple operation more complex behind the scenes - and thus slower, but makes the language more powerful. On the other hand, the array operations with flexible bounds and strides makes it easier to write code - and the compiler is usually better optimizing code than a user.

总的来说,我认为C和Fortran的速度差不多;选择应该更多的是你更喜欢哪种语言,或者是使用Fortran的全数组操作及其更好的可移植性更有用,还是使用C中更好的系统接口和图形用户界面库。

其他回答

在某种程度上,Fortran在设计时就考虑到了编译器优化。该语言支持整个数组操作,编译器可以利用并行性(特别是在多核处理器上)。例如,

密集矩阵乘法很简单:

matmul(a,b)

向量x的L2范数为:

sqrt(sum(x**2))

此外,FORALL、PURE和ELEMENTAL程序等语句进一步有助于优化代码。由于这个简单的原因,即使是Fortran中的指针也不如C语言灵活。

即将发布的Fortran标准(2008)具有协同数组,允许您轻松地编写并行代码。G95(开源)和来自CRAY的编译器已经支持它。

所以是的,Fortran可以很快,因为编译器可以比C/ c++更好地优化/并行化。但是就像生活中的其他事情一样,有好的编译器和坏的编译器。

这两种语言具有相似的特性集。性能上的差异来自Fortran不允许混淆的事实,除非使用了EQUIVALENCE语句。任何有别名的代码都不是有效的Fortran,但是它是由程序员而不是编译器来检测这些错误的。因此,Fortran编译器忽略了可能的内存指针别名,并允许它们生成更有效的代码。看一下C语言中的这个小例子:

void transform (float *output, float const * input, float const * matrix, int *n)
{
    int i;
    for (i=0; i<*n; i++)
    {
        float x = input[i*2+0];
        float y = input[i*2+1];
        output[i*2+0] = matrix[0] * x + matrix[1] * y;
        output[i*2+1] = matrix[2] * x + matrix[3] * y;
    }
}

这个函数在优化后会比Fortran函数运行得慢。为什么如此?如果你在输出数组中写入值,你可能会改变矩阵的值。毕竟,指针可以重叠并指向相同的内存块(包括int指针!)C编译器被迫从内存中重新加载所有计算的四个矩阵值。

在Fortran中,编译器只加载一次矩阵值,并将它们存储在寄存器中。它可以这样做是因为Fortran编译器假定指针/数组在内存中不重叠。

Fortunately, the restrict keyword and strict-aliasing have been introduced to the C99 standard to address this problem. It's well supported in most C++ compilers these days as well. The keyword allows you to give the compiler a hint that the programmer promises that a pointer does not alias with any other pointer. The strict-aliasing means that the programmer promises that pointers of different type will never overlap, for example a double* will not overlap with an int* (with the specific exception that char* and void* can overlap with anything).

If you use them you will get the same speed from C and Fortran. However, the ability to use the restrict keyword only with performance critical functions means that C (and C++) programs are much safer and easier to write. For example, consider the invalid Fortran code: CALL TRANSFORM(A(1, 30), A(2, 31), A(3, 32), 30), which most Fortran compilers will happily compile without any warning but introduces a bug that only shows up on some compilers, on some hardware and with some optimization options.

This is more than somewhat subjective, because it gets into the quality of compilers and such more than anything else. However, to more directly answer your question, speaking from a language/compiler standpoint there is nothing about Fortran over C that is going to make it inherently faster or better than C. If you are doing heavy math operations, it will come down to the quality of the compiler, the skill of the programmer in each language and the intrinsic math support libraries that support those operations to ultimately determine which is going to be faster for a given implementation.

编辑:@Nils等人提出了一个很好的观点,即C语言中指针使用的差异,以及可能存在的别名,这可能会使C语言中最简单的实现变慢。然而,在C99中有一些方法可以解决这个问题,比如通过编译器优化标志和/或C语言的实际编写方式。这在@Nils的回答和随后的评论中有很好的介绍。

大多数帖子已经提出了令人信服的论点,所以我只是在另一个方面加上众所周知的2美分。

在处理能力方面,fortran更快或更慢是有其重要性的,但如果用fortran开发一些东西需要5倍多的时间,因为:

it lacks any good library for tasks different from pure number crunching it lack any decent tool for documentation and unit testing it's a language with very low expressivity, skyrocketing the number of lines of code. it has a very poor handling of strings it has an inane amount of issues among different compilers and architectures driving you crazy. it has a very poor IO strategy (READ/WRITE of sequential files. Yes, random access files exist but did you ever see them used?) it does not encourage good development practices, modularization. effective lack of a fully standard, fully compliant opensource compiler (both gfortran and g95 do not support everything) very poor interoperability with C (mangling: one underscore, two underscores, no underscore, in general one underscore but two if there's another underscore. and just let not delve into COMMON blocks...)

那么这个问题就无关紧要了。如果某样东西很慢,大多数时候你无法在给定的限制范围内改进它。如果你想要更快,改变算法。最后,使用电脑的时间很便宜。人类的时间不是。珍惜减少人类时间的选择。如果它增加了使用电脑的时间,无论如何它都是有成本效益的。

Fortran有更好的I/O例程,例如隐含的do工具提供了C标准库无法比拟的灵活性。

Fortran编译器直接处理更复杂的 涉及到语法,而且这样的语法不能轻易简化 参数传递形式,C不能有效地实现它。