上下文
我需要使用‘排序-u’优化去重复,我的linux机器有一个旧的‘排序’命令实现(即5.97),没有‘-并行’选项。虽然“排序”实现了可并行的算法(例如合并排序),但我需要使这种并行化显式化。因此,我是通过'xargs‘命令手工完成的,它的性能超过了~2.5xw.r.t。单一的“排序-u”方法..。当它正常工作的时候。
这里是我所做的事情的直觉。
我正在运行一个bash脚本,它将输入文件(例如file.txt)分成几个部分(例如file.txt.part1、file.txt.part2、file.txt.part3、file.txt.part4)。生成的部分被传递给'xargs‘命令,以便通过sortu.sh脚本执行并行去重复(后面是详细信息)。sortu.sh封装对'sort -u‘的调用并输出结果文件名(例如,"sortu.sh file.txt.part1“输出”file.txt.part1.order“)。然后,得到的排序部分被传递给一个“排序--合并-u”,它合并/重复输入部分,前提是这些部分已经排序。
我正在经历的问题是通过'xargs‘进行并行化。这里是我的代码的简化版本:
AVAILABLE_CORES=4
PARTS="file.txt.part1
file.txt.part2
file.txt.part3
file.txt.part4"
SORTED_PARTS=$(echo "$PARTS" | xargs --max-args=1 \
--max-procs=$AVAILABLE_CORES \
bash sortu.sh \
)
...
#More code for merging the resulting parts $SORTED_PARTS
...期望的结果是将部分排序到变量SORTED_PARTS中的列表:
echo "$SORTED_PARTS"
file.txt.part1.sorted
file.txt.part2.sorted
file.txt.part3.sorted
file.txt.part4.sorted症状
尽管如此,(有时)还是有一个缺失的排序部分。例如,file.txt.part2.排序如下:
echo "$SORTED_PARTS"
file.txt.part1.sorted
file.txt.part3.sorted
file.txt.part4.sorted这个症状在它的出现(即对同一个file.txt的执行成功,在另一个时间它失败)或在缺少的文件中(也就是说,它并不总是相同的排序缺失部分)中是不确定的。
问题
我有一个种族条件,所有的sortu.sh实例都完成了,'xargs‘在stdout被刷新之前发送EOF。
问题
在“xagrs”发送EOF之前,是否有办法确保stdout冲洗?
约束
sortu.sh代码
#!/bin/bash
SORTED=$1.sorted
sort -u $1 > $SORTED
echo $SORTED发布于 2015-08-11 16:04:12
下面的代码根本没有将内容写入磁盘,而是并行化拆分进程、排序进程和合并,同时执行所有这些操作。
这个版本已经移植到bash3.2;为更新版本bash构建的版本不需要eval。
#!/bin/bash
nprocs=5 # maybe call nprocs command instead?
fd_min=10 # on bash 4.1, can use automatic FD allocation instead
# create a temporary directory; delete on exit
tempdir=$(mktemp -d "${TMPDIR:-/tmp}/psort.XXXXXX")
trap 'rm -rf "$tempdir"' 0
# close extra FDs and clear traps, before optionally executing another tool.
#
# Doing this in subshells ensures that only the main process holds write handles on the
# individual sorts, so that they exit when those handles are closed.
cloexec() {
local fifo_fd
for ((fifo_fd=fd_min; fifo_fd < (fd_min+nprocs); fifo_fd++)); do
: "Closing fd $fifo_fd"
# in modern bash; just: exec {fifo_fd}>&-
eval "exec ${fifo_fd}>&-"
done
if (( $# )); then
trap - 0
exec "$@"
fi
}
# For each parallel process:
# - Run a sort -u invocation reading from an FD and writing from a FIFO
# - Add the FIFO's name to a merge sort command
merge_cmd=(sort --merge -u)
for ((i=0; i<nprocs; i++)); do
mkfifo "$tempdir/fifo.$i" # create FIFO
merge_cmd+=( "$tempdir/fifo.$i" ) # add to sort command line
fifo_fd=$((fd_min+i))
: "Opening FD $fifo_fd for sort to $tempdir/fifo.$i"
# in modern bash: exec {fifo_fd}> >(cloexec sort -u >$fifo_fd)
printf -v exec_str 'exec %q> >(cloexec; exec sort -u >%q)' "$fifo_fd" "$tempdir/fifo.$i"
eval "$exec_str"
done
# Run the big merge sort recombining output from all the FIFOs
cloexec "${merge_cmd[@]}" &
merge_pid=$!
# Split input stream out to all the individual sort processes...
awk -v "nprocs=$nprocs" \
-v "fd_min=$fd_min" \
'{ print $0 >("/dev/fd/" (fd_min + (NR % nprocs))) }'
# ...when done, close handles on the FIFOs, so their sort invocations exit
cloexec
# ...and wait for the merge sort to exit
wait "$merge_pid"https://stackoverflow.com/questions/31926950
复制相似问题