【问题标题】:How do I prevent my parallel code using up all the available system memory?如何防止我的并行代码用完所有可用的系统内存?
【发布时间】:2013-07-14 11:37:35
【问题描述】:

我正在 Linux 上开发一个 c++ 代码,它可能会耗尽内存、进入交换状态并显着降低速度,有时甚至会崩溃。我想通过允许用户指定进程可以用完的总系统内存的比例限制来防止这种情况发生。如果程序超过这个限制,那么代码可能会输出一些中间结果,并干净地终止。

我可以通过从 /proc/self/stat 读取驻留集大小来确定正在使用多少内存。然后我可以在所有并行进程中总结这一点,从而为我提供程序的总内存使用量。

可用的总系统内存可以通过调用 sysconf(_SC_PHYS_PAGES) 获得(参见How to get available memory C++/g++?)。但是,如果我在并行集群上运行,那么大概这个数字只会给我当前集群节点的总内存。例如,我可能在 4 个集群节点(每个节点有 12 个核心)上运行 48 个进程。

所以,我真正的问题是如何找出给定进程在哪个处理器上运行?然后,我可以总结在同一集群节点上运行的进程使用的内存,并将其与该节点上的可用内存进行比较,如果这超过程序运行的任何节点上的指定百分比,则终止程序。我会为此使用 sched_getcpu(),但不幸的是,我正在使用 glibc 2.5 版的系统上编译和运行,而 sched_getcpu() 仅在 glibc 2.6 中引入。此外,由于集群在旧的 linux 操作系统(版本 2.6.18)上使用,我也不能使用 syscall() 来调用 getcpu() !有没有其他方法可以获取处理器编号或任何类型的处理器标识符,以便我可以分别汇总每个处理器使用的内存?

或者有没有更好的方法来解决这个问题?我愿意接受建议。

【问题讨论】:

  • 您是否尝试使用系统限制 (linux.die.net/man/2/setrlimit)?您必须分别对每个节点设置限制,但这应该不是问题。
  • @gawi 我不熟悉 getrlimit/setrlimit,所以我没有尝试过。感谢您指出了这一点。我想这可以让我检测到任何给定进程是否接近内核设置的限制,但是仍然没有任何进程接近限制的可能性,但是所有进程使用的内存是太高了?
  • 是的,此方法允许您为当前进程和所有子进程的资源设置软限制。但是,如果它对您不可用,请告诉我您使用什么来分配计算? MPI?为什么必须手动检查资源使用情况?正如 markhahn 所提到的 - 这不是用户的责任,而是调度系统的责任。
  • @gawi 是的,我正在使用 MPI 进行并行通信。我真的不想搞乱资源分配 - 正如您和 markhahn 所提到的,这最好留给调度系统。我只想知道我是否接近内存限制,以便我可以在我的代码中做一些事情。例如,至少输出一个中间结果。也许我没有正确表达我的问题。
  • 我还是不明白为什么...如果你在节点上设置了内存限制,那么你不需要做额外的检查——当你达到限制时,你会在请求期间得到 NULL以获得额外的内存,并且可以根据需要自行处理。无论如何,如果这对您有帮助,请尝试使用 MPI_Get_processor_name (mcs.anl.gov/research/projects/mpi/www/www3/…) 来确定您的代码正在运行的节点。

标签: c++ linux memory-management parallel-processing mpi


【解决方案1】:

运行良好的集群会将您的作业置于某种形式的资源限制(RLIMIT_AS 或 cgroups)之下。您只需致电setrlimit(RLIMIT_AS,...) 即可自行完成。我认为您担心 sysconf 会使事情变得过于复杂,因为在共享集群上,没有理由认为您的代码应该使用物理内存大小的固定部分。相反,您应该选择一个合理的内存要求(如果您的集群还没有提供一个 - 大多数调度程序都可以很好地进行内存调度。)即使您坚持自己做,自动调整大小,您也不需要知道正在使用哪些内核:只需弄清楚节点上有多少个进程副本,然后适当划分即可。 (当然,您需要弄清楚每个进程在哪个节点(主机)上运行。)

值得指出的是内核是 RLIMIT_AS,而不是 RLIMIT_RSS。而且当你达到这个限制时,新的分配将会失败。

最后,我质疑一个使用无限内存的程序的设计。你确定没有更好的算法吗?用户会发现你的程序使用起来非常烦人,如果在计算上投入大量时间后,它决定尝试分配更多,然后失败。有时人们会在错误地认为分配尽可能多的内存会给他们更好的 IO 缓冲(这是天真的页面缓存等)时提出这类问题。

【讨论】:

  • 是的,正如你所指出的,我需要弄清楚每个进程在哪个节点(主机)上运行——这就是我所坚持的!有什么建议么?我并不想为我的程序分配一块内存来运行。恐怕我不能详细介绍我的算法,但我本质上是根据某些标准细化三角形表面网格。但是,我不知道表面需要有多精细。我已经对面孔数量进行了限制,但我想根据可用的硬件资源做一些更智能的事情。无论如何,谢谢你的帮助。
猜你喜欢
  • 2020-11-14
  • 1970-01-01
  • 2021-11-11
  • 1970-01-01
  • 2017-04-26
  • 2013-11-01
  • 2012-10-23
  • 1970-01-01
  • 2012-04-05
相关资源
最近更新 更多