parallel コマンド

forループで逐次処理させるのもいいのですが、大抵1coreしか使わない.
複数coreを使って逐次処理を複数同時に流したいときがある.
っで使うのがこの parallel コマンド.

本家様 https://www.gnu.org/software/parallel/

簡単な例として「fastq.bz2」なファイルを戻してgzファイルにしてみる

(解凍)
ls *.fastq.bz2 | parallel bzip2 -d {}
 
(gzip圧縮)
ls *.fastq | parallel gzip {}

計算機が持っているすべてのcoreを使ってcore分の解凍プロセスと圧縮プロセスが発生します. pigz,pixzは複数coreを同時に使っての並列処理です

ほかに簡単な例としてeman2のe2proc2dでmrcをjpegに変換してみる.
*実際には「*.mrc」とかで複数のファイルを一度に指定できるけどforを使った場合のお話

relionのMotionCorrでfload32で出力したデータを対象にしてます. fload16にeman2は未対応っぽい

for i in `find ./MotionCorr/job036 -type f -name "*_frameImage.mrc"`; do
 
  cmd="e2proc2d.py ${i} /tmp/$(basename $i .mrc).jpeg"
  echo $cmd
  eval $cmd
 
done

findコマンドでmrcファイルを見つけて、それをforで変数iに一枚づつ入れて e2proc2d.py で jpeg で処理するって流れです.
なのでtopコマンドで見ても1つのプロセスしか表示されません
2023y05m21d_065210097.png

これを parallel コマンドで複数プロセスを流すようにしてみます.

「for .. done」で回すのではなく、lsとかfindで対象を集め、それを parallel コマンドに渡します
一度に実行できる数は「-j」で指定できますが、何も指定しないとそのマシンのcore数となります

[saber@rockylinux relion40_tutorial_precalculated_results]$ find ./MotionCorr/job036 -type f -name "*_frameImage.mrc"
./MotionCorr/job036/Movies/20170629_00021_frameImage.mrc
./MotionCorr/job036/Movies/20170629_00022_frameImage.mrc
./MotionCorr/job036/Movies/20170629_00023_frameImage.mrc
./MotionCorr/job036/Movies/20170629_00024_frameImage.mrc
./MotionCorr/job036/Movies/20170629_00025_frameImage.mrc
./MotionCorr/job036/Movies/20170629_00026_frameImage.mrc
./MotionCorr/job036/Movies/20170629_00027_frameImage.mrc
./MotionCorr/job036/Movies/20170629_00028_frameImage.mrc
./MotionCorr/job036/Movies/20170629_00029_frameImage.mrc
./MotionCorr/job036/Movies/20170629_00030_frameImage.mrc
./MotionCorr/job036/Movies/20170629_00031_frameImage.mrc
./MotionCorr/job036/Movies/20170629_00035_frameImage.mrc
./MotionCorr/job036/Movies/20170629_00036_frameImage.mrc
./MotionCorr/job036/Movies/20170629_00037_frameImage.mrc
./MotionCorr/job036/Movies/20170629_00039_frameImage.mrc
./MotionCorr/job036/Movies/20170629_00040_frameImage.mrc
./MotionCorr/job036/Movies/20170629_00042_frameImage.mrc
./MotionCorr/job036/Movies/20170629_00043_frameImage.mrc
./MotionCorr/job036/Movies/20170629_00044_frameImage.mrc
./MotionCorr/job036/Movies/20170629_00045_frameImage.mrc
./MotionCorr/job036/Movies/20170629_00046_frameImage.mrc
./MotionCorr/job036/Movies/20170629_00047_frameImage.mrc
./MotionCorr/job036/Movies/20170629_00048_frameImage.mrc
./MotionCorr/job036/Movies/20170629_00049_frameImage.mrc
 
(これを)
[saber@rockylinux relion40_tutorial_precalculated_results]$ find ./MotionCorr/job036 -type f -name "*_frameImage.mrc" | parallel -j 4 e2proc2d.py {}  /tmp/{/} 
 
 
(テストを行うには「--dry-run」を加える
[saber@rockylinux relion40_tutorial_precalculated_results]$ find ./MotionCorr/job036 -type f -name "*_frameImage.mrc" | parallel -j 4 --dry-run e2proc2d.py {}  /tmp/{/}

で行ける
この際のtopは
2023y05m21d_070249412.png
となって4プロセスが同時に働いている.

findコマンドの後のパイプ(|)で見つかったPATH名そのものをsed/awk/perlやらで修正してparallelコマンドに繋げるものあり.

find ./MotionCorr/job036 -type f -name "*_frameImage.mrc" | \
  awk -F "/" '{print $0,$3,$5}' | \
  parallel -j 4 --colsep ' ' --dry-run e2proc2d.py {1} /tmp/{2}__{3}
 
1 images, processing 0-0 stepping by 1
1 images
1 images, processing 0-0 stepping by 1
1 images
 :
 :
 
(「--colsep」で区切り文字を定義します)
find ./MotionCorr/job036 -type f -name "*_frameImage.mrc" | parallel --colsep '/' echo {2}  {5}
MotionCorr 20170629_00021_frameImage.mrc
MotionCorr 20170629_00022_frameImage.mrc
 :
 :

1プロセスごとにGPUIDを変更したいなら、「-j」と「{%}」を駆使します. 「{#}」は連番となります

find ./MotionCorr/job036 -type f -name "*_frameImage.mrc" | parallel -j 4 --colsep '/' echo '$(({%} - 1))' {5} {#}
0 20170629_00021_frameImage.mrc 1
1 20170629_00022_frameImage.mrc 2
2 20170629_00023_frameImage.mrc 3
3 20170629_00024_frameImage.mrc 4
0 20170629_00025_frameImage.mrc 5
1 20170629_00026_frameImage.mrc 6
2 20170629_00027_frameImage.mrc 7
3 20170629_00028_frameImage.mrc 8
0 20170629_00029_frameImage.mrc 9
 :
 :

あと例としてGautomatchでGPU分のジョブを発行する方法とか Gautomatch/bash

parallelコマンド内での引数

bashの変数の文字列操作と似てますが

プレイスホルダ変換値
/data/projectA/raw/20230516/A00001.mrc{}/data/projectA/raw/20230516/A00001.mrc
{.}/data/projectA/raw/20230516/A00001
{/}A00001.mrc
{/.}A00001
{//}/data/projectA/raw/20230516
bash
mrc=/data/projectA/raw/20230516/A00001.mrc${mrc}/data/projectA/raw/20230516/A00001.mrc
${mrc#/}data/projectA/raw/20230516/A00001.mrc
${mrc##*/}A00001.mrc
${mrc#*.}mrc
${mrc%.*}/data/projectA/raw/20230516/A00001
${mrc%%.mrc}/data/projectA/raw/20230516/A00001
${mrc%/*}/data/projectA/raw/20230516
${mrc/data\/projectA\/raw\/}/20230516/A00001.mrc
${mrc/data\/projectA\/raw\//tmp/}/tmp/20230516/A00001.mrc
$(basename $mrc .mrc)A00001
$(basename $mrc .mrc).jpegA00001.jpeg

ctffindで.

ctffindは改行コードで区別して引数を充てている
こんな感じで.

/public/EM/ctffind/ctffind.exe --amplitude-spectrum-input > CtfFind/job003/Movies/20170629_00024_frameImage_PS_ctffind4.log << EOF
CtfFind/job003/Movies/20170629_00024_frameImage_PS.mrc
CtfFind/job003/Movies/20170629_00024_frameImage_PS.ctf
1.39955
200
1.4
0.1
512
30
5
5000
50000
500
no
no
yes
100
no
no
EOF
exit 0

これをparallelで回すならこんな感じかな.
ctfファイルを /tmp に置いてますけど適時変更よろ.

「echo -e」で埋め込んだ改行コード(\n)を展開させてそれをpipeで繋いでctffindに渡してます

find ./Micrographs/ -name *.mrc | \
  parallel -j 4 'echo -e "{}\n/tmp/{/.}.ctf\n1.39955\n200\n1.4\n0.1\n512\n30\n5\n5000\n50000\n500\nno\nno\nyes\n100\nno\nno\n"|/apps/ctffind-4.1.14/ctffind'
最新の60件
2024-05-21 2024-05-16 2024-04-26 2024-04-19 2024-04-18 2024-04-15 2024-04-11 2024-04-06 2024-04-05 2024-03-30 2024-03-29 2024-03-19 2024-03-17 2024-03-15 2024-03-06 2024-03-05 2024-03-03 2024-02-23 2024-02-22 2024-02-21 2024-02-20 2024-02-19 2024-02-18 2024-02-17 2024-02-13 2024-02-12 2024-02-09 2024-02-04 2024-02-03 2024-01-31 2024-01-30 2024-01-29 2024-01-28 2024-01-22 2024-01-16 2024-01-13 2024-01-09 2024-01-08 2024-01-07 2024-01-03 2023-12-22 2023-12-17

edit


トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2024-04-06 (土) 19:55:09