提问人:Another User 提问时间:10/2/2023 最后编辑:Another User 更新时间:10/2/2023 访问量:66
为什么当矩阵维度过大(在 ifort 中)时,我在此程序中会遇到分割故障问题?
Why do I get a segmentation fault problem in this program when the matrix dimension is too large (in ifort)?
问:
我正在 Fortran 中使用矩阵和向量进行基本的线性代数计算。我已将编译器从 gfortran 更改为 ifort,我发现当我的矩阵变得太大时(特别是当它们的大小为 724 x 724 时,类型为 complex double),我会出现以下错误(分割错误):
forrtl: severe (174): SIGSEGV, segmentation fault occurred
Image PC Routine Line Source
dummy 000000000040C9DA Unknown Unknown Unknown
libpthread-2.28.s 00007FB2CAB57CE0 Unknown Unknown Unknown
dummy 0000000000403D57 Unknown Unknown Unknown
dummy 0000000000402B22 Unknown Unknown Unknown
libc-2.28.so 00007FB2CA7BACF3 __libc_start_main Unknown Unknown
dummy 0000000000402A2E Unknown Unknown Unknown
我设法将问题归结为这个最小的程序:
program dummy
use ifport
use iso_c_binding, dp => c_double, ip => c_int, dcp => c_double_complex
implicit none
integer (ip) :: dim
complex(dcp), dimension(:,:), allocatable :: U
write (*,*) "dim"
read (*,*) dim
print*,""
print *, "Allocating U."
allocate(U(dim,dim))
print *, "dim = ", dim, "dim^2 = ", dim**2, "size(U) = ", size(U)
print *, "Building U..."
U = 0
print *, "U initialized (set to zero)."
print *, "Testing matrix multiplication matmul(U, U)"
U = matmul(U,U)
print *, "U built."
end program
使用 或 编译(ifport 不与 gfortran 一起使用)。其他标志(例如)不会提供有关错误源的其他信息。ifort dummy.f90 -o dummy
gfortran dummy.f90 -o dummy
-fpp -check all, bounds -warn all -pedantic
这不再适用于 ifort,而它适用于 gfortran 的更大尺寸(我已经测试了几千个没有问题)。一旦执行矩阵乘法,就会出现错误。事实上,即使在我用两个程序分配第一个矩阵都没有问题,但是使用 ifort 我总是得到分割错误错误(尽管使用 gfortran 它非常慢,尽管预计会有这些大小 - 我没有检查矩阵乘法的结果是否正确在任何情况下)。dim = 724
dim = 10000
此外,该程序已在两台不同的机器上运行,尽管我不希望使用 ifort 的机器出现内存问题,因为通过简单的计算,我有 72 个处理器,每个处理器都有 ~10GB 内存(目前没有其他人使用这个集群)。
因此,通过挥手计算,复数双精度类型的矩阵需要具有维度才能完全填满一个处理器的内存,而我远未达到这个水平。free
cat /proc/cpuinfo/
sqrt(10 * 10^9 / 16) ~ 25000
错误的根源是什么?由于它非常通用,我还没有设法理解原因,以及 gfortran 和 ifort 之间的不一致。使用不同的机器和编译器版本进行测试也将非常受欢迎。谢谢。
答:
该语句需要一个大小为 的隐藏临时数组。默认情况下,ifort 编译器将分配堆栈上的所有临时数组(大小有限),而 gfortran 编译器会分配堆上的大型数组(仅受机器上可用内存的限制)。U = matmult(U,U)
U
所以你这里有 2 个解决方案:
- 增加堆栈大小。在 linux 上,键入命令以删除堆栈的任何大小限制
ulimit unlimited
- 使用 ifort 选项,该选项强制在堆上分配所有临时(和自动)数组
-heap-arrays
评论