在 bash 或 zsh 脚本中使用所有核心的有效方法

在 bash 或 zsh 脚本中使用所有核心的有效方法

如果我想使用只能使用一个核心的命令“do_something”处理大量文件,假设每个文件都可以独立处理,那么使用所有可用核心的最佳方法是什么?

此刻我做了这样的事情:

#!/bin/zsh
TASK_LIMIT=8
TASKS=0
for i in *(.)
{
  do_something "$i"&
  TASKS=$(($TASKS+1))
  if [[ $TASKS -ge $TASK_LIMIT ]]; then
    wait; TASKS=0; fi
}
wait

显然,这并不高效,因为达到 $TASK_LIMIT 后,它会等待所有“do_something”完成。例如,在我的实际脚本中,我使用了 8 核 CPU 的约 500%,而不是 >700%。

在没有 $TASK_LIMIT 的情况下运行是不可能的,因为“do_something”可能会消耗大量内存。

理想情况下,脚本应尝试将并行任务数保持在 $TASK_LIMIT:例如,如果 8 个任务中的 1 个已完成并且至少还有一个文件需要处理,则脚本应运行下一个“do_something”,而不是等待剩余的 7 个任务完成。有没有办法在 zsh 或 bash 中实现这一点?

答案1

我强烈建议看看GNU并行。它完全按照您的需要进行操作,并且不依赖于任何特定的 shell。

答案2

记住您启动了多少个进程。当一个进程结束时,减少计数。当计数低于最大值时,启动一个新进程。

唯一的问题是如何发出进程结束的信号。例如,您可以在 /tmp 中创建一个给定名称的空文件(由 $$ 和 $BASHPID 组成)。

相关内容