web-dev-qa-db-ja.com

GNU parallel-パラメータとしての配列からの2つのパラメータ

私はgnu並列を使用するスクリプトを持っています。 「反復」ごとに2つのパラメーターを渡したい

シリアル実行では、次のようなものがあります:

for (( i=0; i<=10; i++ ))
do
  a = tmp1[$i]
  b = tmp2[$i]
done

そして、これを次のように並行させたい

func pf()
{
   a=$1
   b=$2
}
export -f pf
parallel --jobs 5 --linebuffer pf ::: <what to write here?>
6
Martin Perry

集中するために他のparallelフラグを省略しています...

parallel --link pf ::: A B ::: C D

これは、最初にa=Ab=C、続いてa=Bb=Dを使用して関数を実行します。

a=A b=C
a=B b=D

--linkがないと、次のような完全な組み合わせになります。

a=A b=C
a=A b=D
a=B b=C
a=B b=D

pdate: Ole Tangeがコメントで言及したように[削除されたため-Ed。]これを行う別の方法があります:使用:::+演算子。ただし、2つの選択肢には重要な違いがありますif引数の数は各param位置で同じではありません。例を示します。

parallel --link pf ::: A B ::: C D E出力:

a=A b=C
a=B b=D
a=A b=E

parallel pf ::: A B :::+ C D E出力:

a=A b=C
a=B b=D

したがって、--linkはすべての引数が消費されるように「ラップ」し、:::+は余分な引数を無視します。 (一般的なケースでは、代替案はある意味で入力を黙って無視するので、--linkを好みます。YMMV。)

8
B Layer

簡単にするために、bashを想定し、配列には0ではなく1からインデックスが付けられていると仮定します。

parallel ... pf '$tmp1[{#}]' '$tmp2[{#}]' ::: $(seq 10)

ここで、pf関数への2つの引数はコマンドの一部であり、並列表記{#}を使用してジョブ番号を表します(10個のジョブでは1から10に設定されています。 seqを使用して:::の後に10個の引数を取得し、10個のジョブを実行するようにします(seq値は使用されず、たまたまジョブ番号と同じになります)。

残念ながら、bashは配列変数をエクスポートしないため、これは機能しません。ただし、関数をエクスポートできます。parallelのマニュアルページでは、単純なimport_array関数を使用して、選択した関数をエクスポート/インポートする回避策を示しています。my_importerは、配列変数を設定しますあなたの選択:

declare -a tmp1 tmp2
for (( i=1; i<=10; i++ ))
do tmp1[$i]=x$i
   tmp2[$i]=y$i
done

import_array(){
    local func=$1; shift;
    export $func='() {
      '"$(for arr in $@; do
            declare -p $arr|sed '1s/declare -./&g/'
          done)"'
    }'
}
import_array my_importer tmp1 tmp2

parallelmy_importer関数をpfコマンドの環境にオプション--env my_importerを指定して渡すように指示し、pf

pf(){ a=$1; b=$2; echo "job a=$a b=$b"; }
export -f pf 

parallel -v --jobs 5 --linebuffer \
 --env my_importer 'my_importer;'  pf '${tmp1[{#}]}' '${tmp2[{#}]}' ::: $(seq 10)

-vを使用した結果の出力は、次のようになります。

my_importer; pf ${tmp1[2]} ${tmp2[2]}
my_importer; pf ${tmp1[1]} ${tmp2[1]}
my_importer; pf ${tmp1[5]} ${tmp2[5]}
my_importer; pf ${tmp1[3]} ${tmp2[3]}
job a=x1 b=y1
my_importer; pf ${tmp1[6]} ${tmp2[6]}
job a=x2 b=y2
my_importer; pf ${tmp1[7]} ${tmp2[7]}
job a=x4 b=y4
...
1
meuh