Fortran 90 代码中 NxN 矩阵中的 N 的最大值是多少,从而不会发生分段错误?
例如,当我使用大小为 2^8 x 2^8 的矩阵并将它们用于乘法时(使用内在的“matmul”函数),我没有任何问题。
但是,当我使用 2^12 x 2^12 矩阵时,我没有发现任何编译错误,但我在程序中间遇到了分段错误。
我的内存分配用完了还是我的代码中可能存在错误?
我使用了动态分配,并且使用了 64 位 RedHat OS 和 64 GB RAM。
最大大小是否还取决于编译器或系统配置?
3 回答
Fortran 编译器通常在堆栈上分配可分配数组;或者也许在堆上。对此我不确定,但我确信 Fortran 标准没有规定可分配数组的放置位置。您的编译器文档将告诉您默认情况下可分配数组的放置位置。您可能会发现可以通过移动分配位置或扩展(由操作系统决定的)堆栈或堆大小来避免您看到的错误。
stat
您还可以通过对任何语句使用可选参数来帮自己一个忙,allocate
并在您的程序中捕获分配失败。当然,您仍然不会分配数组,但这将避免程序崩溃。
您还应该遵循@Alexander 答案中的建议并计算您尝试分配的数组的大小,摆弄堆和堆栈大小不会为您提供比可用 RAM 更多的空间。
(2) 最大可分配大小取决于您的主内存,数组构造函数(对于 gfortran)的最大大小默认为 65535,可以通过 设置-fmax-array-constructor=n
,请参见此处。
(1) 这很容易计算:
双精度复数变量为 16 字节。所以,如果你有一个N x N
矩阵和 64GB 的 RAM,这会导致N = \sqrt ( 64 GB / 16 B ) \approx 63245
.
因此,对于双精度复数值,您会受到主内存的限制。
Real
s (通常)为 4 字节的单精度和 8 字节的双精度。单精度复数变量使用 8 字节。
您应该尝试将堆栈大小设置为无限制使用
ulimit -s unlimited
我遇到了类似的问题,因为ifort
在堆栈上为矩阵操作创建了大型临时数组,这可能导致意外的段错误。