我不时地读到Fortran在繁重的计算中比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代码比编写C(或c++)代码更容易。Fortran和C都是“历史悠久”的语言(按照今天的标准),被大量使用,并且很好地支持免费和商业编译器。

我不知道这是否是一个历史事实,但Fortran感觉它是为并行/分布式/向量化/多核化而构建的。今天,当我们谈论速度时,它几乎是“标准度量”:“它能缩放吗?”

对于纯粹的cpu计算,我喜欢Fortran。对于任何与IO相关的东西,我发现使用c更容易(无论如何这两种情况都很困难)。

当然,对于并行计算密集型代码,你可能需要使用GPU。C和Fortran都有很多或多或少很好地集成了CUDA/OpenCL接口(现在还有OpenACC)。

我比较客观的回答是:如果你对这两种语言都同样了解或不了解,那么我认为Fortran更快,因为我发现用Fortran写并行/分布式代码比用c更容易(一旦你明白你可以写“自由形式”Fortran,而不仅仅是严格的F77代码)

Here is a 2nd answer for those willing to downvote me because they don't like the 1st answer : Both language have the features required to write high-performance code. So it's dependent of the algorithm you're implementing (cpu intensive ? io intensive ? memory intensive?), the hardware (single cpu ? multi-core ? distribute supercomputer ? GPGPU ? FPGA ?), your skill and ultimately the compiler itself. Both C and Fortran have awesome compiler. (i'm seriously amazed by how advanced Fortran compilers are but so are C compilers).

PS:我很高兴你特别排除了库,因为我有很多关于Fortran GUI库的不好的东西要说。:)

这两种语言具有相似的特性集。性能上的差异来自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.

I was doing some extensive mathematics with FORTRAN and C for a couple of years. From my own experience I can tell that FORTRAN is sometimes really better than C but not for its speed (one can make C perform as fast as FORTRAN by using appropriate coding style) but rather because of very well optimized libraries like LAPACK (which can, however, be called from C code as well, either linking against LAPACK directly or using the LAPACKE interface for C), and because of great parallelization. On my opinion, FORTRAN is really awkward to work with, and its advantages are not good enough to cancel that drawback, so now I am using C+GSL to do calculations.

我还没有听说过Fortan比C快得多,但是可以想象在某些情况下它会更快。关键不在于语言特征的存在,而在于那些(通常)不存在的特征。

一个例子是C指针。C指针几乎到处都在使用,但指针的问题是编译器通常无法判断它们是否指向同一个数组的不同部分。

例如,如果你写了一个strcpy例程,看起来像这样:

strcpy(char *d, const char* s)
{
  while(*d++ = *s++);
}

编译器必须在d和s可能是重叠数组的假设下工作。所以当数组重叠时,它不能执行会产生不同结果的优化。正如您所期望的,这在很大程度上限制了可以执行的优化类型。

[我应该注意到,C99有一个“restrict”关键字,显式地告诉编译器指针不重叠。还要注意,Fortran也有指针,语义不同于C语言,但指针不像C语言那样无处不在。

但是回到C与Fortran的问题上,可以想象,Fortran编译器能够执行一些对于(直接编写的)C程序可能无法实现的优化。所以我不会对这种说法感到太惊讶。不过,我确实希望性能差异不会太大。(~ 5 - 10%)

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

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