我需要在某处使用Fortran而不是C,而且我对Fortran很新。我正在尝试做一些大的计算但是与C相比它很慢(可能是10倍或更多,我使用英特尔的编译器)。我认为原因是Fortran将矩阵保持为列主格式,我正在尝试像sum(matrix(i,j,:))这样的操作,因为它是列专业,可能这会非常低效地使用缓存(可能不是完全使用)。但是,我不确定这是否是真正的原因(因为我对Fortran知之甚少)。问题是,Fortran中的约定是对列向量而不是行向量进行操作吗?
(顺便说一句:我已经检查过Fortran的速度已经使用了英特尔的LAPACK库,并且它非常快,所以它与任何编译器或构建问题无关。)
感谢。
METE
答案 0 :(得分:4)
尝试在进行矩阵运算时更改循环的顺序,例如如果你在C中有这样的东西:
for (i = 0; i < M; ++i) // for each row
{
for (j = 0; j < N; ++j) // for each col
{
// matrix operations on e.g. A[i][j]
}
}
然后在Fortran中你想要j(列)循环作为外循环而i(行)循环作为内循环。
实现相同目的的另一种方法是保持循环不变,但改变数组的定义,例如:如果在C中它是A[x][y][z][t]
,那么在FORTRAN中将其设为A[t][z][y][x]
,假设t
是变化最快的循环索引,x
是最慢的。
答案 1 :(得分:4)
因为在编写时,Fortran是列专业,第一个索引在内存布局中变化最快,因此sum(matrix(i,j,:))会导致非连续位置的总和。如果这确实是操作较慢的原因,那么您可以重新定义矩阵以具有不同的维度顺序,以便当前的第3维度为第1维度。是的,如果这是您的主要计算,则重新排列矩阵以使求和成为列操作。如@PaulR所述,显式循环应该像最早的索引一样快。如果您之前已经考虑过C的最佳索引顺序并且正在更改为Fortran,则这是可能需要更改的一个方面。虽然这在理论上是正确的,但我怀疑它在实践中确实很重要,除非数组是巨大的。 (最糟糕的情况是阵列的一部分在RAM中,部分在磁盘上交换!)关于运行时速度问题的第一条规则是不要猜测...测量。它通常是算法。