FORTRAN 内存利用率 - 静态与动态

Posted

技术标签:

【中文标题】FORTRAN 内存利用率 - 静态与动态【英文标题】:FORTRAN memory utilization - static vs dynamic 【发布时间】:2012-01-27 01:44:53 【问题描述】:

我有一个问题,我之前曾尝试询问过,但没走多远,找到了新信息,希望能得到更多帮助。该代码是一个混合的MPI/OPENMP 代码,在尝试跨多个节点运行时会因分段错误而崩溃(尽管如果它只在一个节点上执行,它是有效的,它是生成主进程的节点)。问题中有静态数组,我发现如果静态数组“太大”会导致 seg 错误,但如果它们“小”则一切正常。我还将代码转换为动态内存分配作为测试,这解决了问题......无论大小(即使是在静态世界中失败的较大的),代码都可以正常运行。这个解决方案不是一个长期的解决方案,因为测试代码只是......一个测试代码,有一个更大的代码表现出相同的行为并且将其更改为动态不是一种选择。我需要确定导致静态数组段错误情况的原因。

基本上,如何处理静态分配和动态分配的内存有什么区别?我应该尝试什么(除了我尝试过的事情)来克服这个问题?我认为问题与系统设置有关,可能仅在通过 MPICH2 传递作业时才违反,但在登录节点时不是问题(因此为什么它在我当前登录的节点上运行良好)。

在我的.bashrc 文件中,我有“ulimit -s unlimited”、“export OMP_STACKSIZE=4g”和“export KMP_STACKSIZE=4G”,因为我使用的是 ifort 编译器。我相信这一定是一个相对简单的解决方法,但我做不到。

如果需要违规程序源代码,我可以将其发送出去,但我认为这里给出的描述涵盖了问题,请告诉我。

【问题讨论】:

【参考方案1】:

静态分配的东西出现在堆栈上,而动态分配的东西出现在堆上。这就是为什么小型静态数组可以正常工作而大型静态数组不能正常工作的原因。

由于您使用的是 ifort 编译器,您可以尝试使用 -heap-arrays 进行编译,但这只会将动态分配的数组放在堆上(ifort 的独特之处在于“临时”可分配数组可能会进入堆栈,就像那些在子程序中分配)。

要检查的另一件事是 MPI 作业实际上允许您设置堆栈大小。尝试运行mpirun -n <numprocs> ulimit -s,它应该显示所有unlimited,否则它不尊重你的bashrc。

您可以尝试使用 bash 脚本 (myScript.sh),例如:

#!/bin/bash
ulimit -s unlimited
./myProg

然后运行:

mpiexec -n <numprocs> myScript.sh

【讨论】:

你想通了。问题是当通过 mpiexec 调用时,shell 值和 .bashrc 文件不会被转发/执行。 4 个节点的堆栈大小为“无限,8192、8192、8192”,第一个是我登录的节点。我的下一个问题......如何解决这个问题?我可以通过 mpiexec 调用传递“ulimit -s unlimited”,但不知道语法。更好的是,我应该在集群的管理方面更改它吗? (我必须将命令“ulimit -s”添加到文件中并使该文件成为可执行文件,然后通过 mpiexec 传递 ./that_file 以使其工作)。 我试图“投票”你的答案,但我没有足够的声誉或其他东西。对不起。 快速说明,我不得不使用可执行文件方法,因为发送“mpiexec -np 4 -machinefile machines ulimit -s”失败并出现错误,就像我尝试使用各种引号的任何其他方法一样。我不知道如何在一个命令中发送所有内容而不会导致错误。 如何提交作业? qfiles 还是手动?如果通过 qfile,只需将ulimit -s unlimited 放入 qfile。不是,您的另一个选择是编写一个简单的批处理脚本,您可以使用mpiexec 运行它设置堆栈大小然后执行您的exe。示例在答案中。 如果您可以在管理员端更改它,那至少可以工作。但是无限堆栈大小也有缺点,特别是在多用户系统上。但是,如果保证你是唯一一个在节点上运行的人,那么无限的堆栈大小不会在你吃光它的情况下搞砸其他人的工作。

以上是关于FORTRAN 内存利用率 - 静态与动态的主要内容,如果未能解决你的问题,请参考以下文章

静态代理与动态代理

设计模式 动态代理

使用 LAPACK 的 Fortran2003 中的动态内存分配错误

从结构体内存池初始化到申请释放,详细解读鸿蒙轻内核的动态内存管理

c语言实现静态与动态通讯录

Java静态代理和动态代理的区别