作为我的研究项目的一部分,我正在处理分成许多文件的大量数据。
文件夹中的所有文件都foo
必须由myScript
涉及文件夹所有元素的脚本处理bar
。
这是myScript
:
for f in bar/*
do
awk 'NR==FNR{a[$0]=$0;next}!a[$0]' $f $1 > tmp
cp tmp $1
done
用 for 循环处理所有文件的第一个想法是有效的:
for f in foo/*
do
./myScript $f
done
然而,这需要很长时间。简单地通过附加方式在后台启动每个 myScript&
会创建数千个并行执行的 和 实例awk
,并cp
具有巨大的输入,这显然是不好的。
我想限制使用以下命令创建的“线程”的数量
for f in foo/*
do
THREAD_COUNT=$(ps | wc -f)
while [ $THREAD_COUNT -ge 12 ]
do
sleep 1
THREAD_COUNT=$(ps | wc -f)
done
./myScript $f &
done
附带说明:我正在与 12 进行比较,因为我的节点上有 8 个核心,并且显然总是有bash
,正在运行ps
,wc
并且在调用 时的标题行也在运行ps | wc -l
。
不幸的是, 的调用myScript
会导致 中出现多个附加条目ps
,因此我的脚本的行为并不符合预期。
所以这是我的问题:有没有更简单的方法?哪种方式更稳定?
我没有在节点上做任何其他事情,所以发生的一切都是由脚本引起的。
答案1
虽然您可以使用 shell 脚本来完成此操作,但这却很困难。 Shell 脚本不太擅长操作多个后台作业。
我的建议是使用GNU 使或者其他版本的 make 可以-j
选择并行执行多个作业。将每个子任务编写为 makefile 规则。
我认为下面的 makefile 片段实现了您的规则,但您的代码很难遵循,所以我现在可能已经得到了正确的结果。第一行枚举输入文件的输出文件(注意:永远不要覆盖任何输入文件!如果作业由于任何原因在中间停止,您最终将得到不知道是否已处理的数据) 。缩进行是要运行的命令。使用制表符缩进每个命令,而不是 8 个空格。在这些命令中,$<
代表源文件(.in
文件),$@
代表目标文件(.out
文件),并且$*
是不带扩展名的目标。 shell 命令中的所有$
符号都必须加倍,并且每个命令行都在单独的子 shell 中执行,除非您\
在末尾添加 a 来取消换行符(因此 shell 会看到以 开头set -e
和结尾的一长行done
)。
all: $(patsubst %.in,%.out,$(wildcard foo/*.in))
%.out: %.in
cp $< $*.tmp.in
set -e; \
for f in bar/*; do \
awk 'NR==FNR{a[$$0]=$$0;next}!a[$$0]' $$f $*.tmp.in >$*.tmp.out; \
mv $*.tmp.out $*.tmp.in; \
done
mv $*.tmp.in $@
Makefile
将其放入名为并调用 的文件中make -j12
。
答案2
使用 GNU Parallel (http://www.gnu.org/software/parallel/),它看起来像这样:
parallel awk \'NR==FNR\{a\[\$0\]=\$0\;next\}\!a\[\$0\]\' {1} {2} '>{2}.tmp; mv {2}.tmp {2}' ::: bar/* ::: foo/*
这将为每个核心运行一项作业。用于-j150%
每个核心运行 1.5 个作业。
如果您只想并行运行多个,myScript
请执行以下操作:
parallel ./myScript ::: foo/*
观看介绍视频以了解更多信息:https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
答案3
您可以尝试使用ulimit
.来自 bash 手册页:
ulimit [-HSTabcdefilmnpqrstuvx [limit]]
Provides control over the resources available to the shell and to processes started by it,
on systems that allow such control.
[...]
-u The maximum number of processes available to a single user
因此,如果您将其置于ulimit -u 8
脚本内的适当位置,则会将该 shell 可用的进程限制为 8 个。
不过没有测试过。