并行地成对合并文件,直到只剩下 1 个文件

并行地成对合并文件,直到只剩下 1 个文件

ngram-merge我想使用 SRILM 的程序合并一堆语言模型 (LM) 计数文件。通过该程序,我可以合并计数文件的整个目录,例如ngram-merge -write combined_file -- folder/*.然而,根据我的数据量,它会运行几天,所以我很想并行合并文件!

下面的脚本基本上执行以下操作:

  1. 它将目录中的文件分成两个大小相等的集合(如果文件数量是奇数,则在构建集合之前合并两个文件)
  2. 它循环遍历集合并将两个文件合并在一起,从而将新文件写入新的子目录(这应该并行完成)
  3. 检查新子目录中是否只有一个文件;如果没有,1.在新创建的子目录中重新启动

不幸的是,该脚本可以工作,但ngram-merge命令不是并行编译的。你能解决这个问题吗?此外,动态创建的文件夹结构有点难看。而且我也不是 shell 专家。所以我会感谢每一个让整个事情变得更加优雅的评论!谢谢 :-)

#!/bin/bash

# Get arguments
indir=$1
# Count number of files
number="$(ls -1 $indir | wc -l)"
# Determine number of cores to be used in parallel
N=40

# While more than one file, combine files
while [ "$number" -gt 1 ]; do

    # determine splitpoint
    split="$((number/2))"
    # Determine whether number of files is odd
    if [ $((number%2)) -eq 1 ]
        # if it is odd, combine first and last file and rm last file
        then
            first="$indir$(ls -1 $indir | head -1)"
            last="$indir$(ls -1 $indir | tail -1)"
            new="$first""$last"
            /vol/customopt/lamachine.stable/bin/ngram-merge -write $new -- $first $last && rm -r $first $last
    fi

    # Determine first half of files and second half
    set1="$(ls -1 $indir | head -$split)"
    set2="$(ls -1 $indir | head -$((split*2)) | tail -$split)"
    # Make new dir
    newdir="$indir"merge/
    mkdir $newdir

    # Paralelly combine files pairwise and save output to new dir
    (
    for i in $(seq 1 $split); do
        file1="$indir$(echo $set1 | cut -d " " -f $i)"
        file2="$indir$(echo $set2 | cut -d " " -f $i)"
        newfile="$newdir""$i".counts
        /vol/customopt/lamachine.stable/bin/ngram-merge -write $newfile -- $file1 $file2 && rm -r $file $file2
        ((i=i%N)); ((i++==0)) && wait
    done
    )

    # Set indir = newdir and recalculate number of files
    indir=$newdir
    number="$(ls -1 $indir | wc -l)"

done

答案1

我不知道ngram-merge所以我用cat

n=$(ls | wc -l)
while [ $n -gt 1 ]; do
  parallel -N2 '[ -z "{2}" ] || (cat {1} {2} > '$n'.{#} && rm -r {} )' ::: *;
  n=$(ls | wc -l);
done

但它可能看起来像这样:

n=$(ls | wc -l)
while [ $n -gt 1 ]; do
  parallel -N2 '[ -z "{2}" ] || ( /vol/customopt/lamachine.stable/bin/ngram-merge -write '$n'.{#} -- {1} {2} && rm -r {} )' ::: *;
  n=$(ls | wc -l)
done

相关内容