10

特定の文字列を含むファイル(5MB)から、大きなファイル(27GB)の同じ文字列(およびその他の情報)をgrepする必要があります。分析を高速化するために、27GBのファイルを1GBのファイルに分割し、次のスクリプトを適用しました(ここにいる何人かの人々の助けを借りて)。ただし、あまり効率的ではありません(180KBのファイルを作成するには30時間かかります!)。

これがスクリプトです。grepよりも適切なツールはありますか?または、grepを使用するより効率的な方法はありますか?

#!/bin/bash

NR_CPUS=4
count=0


for z in `echo {a..z}` ;
do
 for x in `echo {a..z}` ;
 do
  for y in `echo {a..z}` ;
  do
   for ids in $(cat input.sam|awk '{print $1}');  
   do 
    grep $ids sample_"$z""$x""$y"|awk '{print $1" "$10" "$11}' >> output.txt &
    let count+=1
                                [[ $((count%NR_CPUS)) -eq 0 ]] && wait
   done
  done #&
4

4 に答える 4

16

あなたが試すことができるいくつかのこと:

input.sam1)あなたは複数回読んでいます。最初のループが始まる前に一度だけ読む必要があります。IDを一時ファイルに保存します。このファイルは。によって読み取られgrepます。

LC_ALL=C2) UTF-8の代わりにCロケールを使用するように、grepコマンドの前に付けます。これによりスピードアップしgrepます。

3)fgrep正規表現ではなく、固定文字列を検索するために使用します。

4)ループを使用するのではなく、ファイルから読み取りパターン-fを作成するために使用します。grep

5)複数のプロセスからの出力ファイルに書き込まないでください。行がインターリーブされ、ファイルが破損する可能性があります。

これらの変更を行った後、スクリプトは次のようになります。

awk '{print $1}' input.sam > idsFile.txt
for z in {a..z}
do
 for x in {a..z}
 do
  for y in {a..z}
  do
    LC_ALL=C fgrep -f idsFile.txt sample_"$z""$x""$y" | awk '{print $1,$10,$11}'
  done >> output.txt

また、ジョブを並行して実行するのに役立つように設計されたGNUParallelもチェックしてください。

于 2013-01-30T12:13:22.510 に答える
4

私の最初の考えは、あなたが繰り返しスポーンしているということですgrep。プロセスの生成は(比較的)非常にコストがかかるため、継続的なプロセスの作成を必要としない、ある種のスクリプト化されたソリューション(Perlなど)を使用したほうがよいと思います。

たとえば、開始する内部ループごとcatに(ファイルを読み取ることができるので必要ありません。実際、この/awk組み合わせは毎回同じものを返しませんか?)そして。次に、4が終了するのを待って、もう一度回ります。catawkcatawkgrepgreps

を使用する必要がある場合はgrep、を使用できます

grep -f filename

コマンドラインで単一のパターンではなく、ファイル名で一致するパターンのセットを指定します。上記のフォームから、そのようなリストを事前に生成できると思います。

于 2013-01-30T11:37:27.817 に答える
0

わかりました。4文字の文字列を含むテストファイルがあります。つまり、aaaaaaaabaaacなどです。

ls -lh test.txt
-rw-r--r-- 1 root pete 1.9G Jan 30 11:55 test.txt
time grep -e aaa -e bbb test.txt
<output>
real    0m19.250s
user    0m8.578s
sys     0m1.254s


time grep --mmap -e aaa -e bbb test.txt
<output>
real    0m18.087s
user    0m8.709s
sys     0m1.198s

したがって、mmapオプションを使用すると、2つの検索パターンを持つ2 GBファイルが明らかに改善されます。@BrianAgnewのアドバイスを受けて、grepを1回呼び出す場合は、-mmapオプションを試してください。

ただし、検索中にソースファイルが変更された場合、mmapは少し風変わりになる可能性があることに注意してください。mangrepから

--mmap

可能であれば、デフォルトのread(2)システムコールの代わりに、mmap(2)システムコールを使用して入力を読み取ります。状況によっては、-mmapの方がパフォーマンスが向上します。ただし、-mmapは、grepの動作中に入力ファイルが縮小した場合、またはI / Oエラーが発生した場合に、未定義の動作(コアダンプを含む)を引き起こす可能性があります。

于 2013-01-30T12:08:29.800 に答える
0

GNU Parallelを使用すると、次のようになります。

awk '{print $1}' input.sam > idsFile.txt
doit() {
   LC_ALL=C fgrep -f idsFile.txt sample_"$1" | awk '{print $1,$10,$11}'
}
export -f doit
parallel doit {1}{2}{3} ::: {a..z} ::: {a..z} ::: {a..z} > output.txt

行の順序が重要でない場合、これは少し速くなります。

parallel --line-buffer doit {1}{2}{3} ::: {a..z} ::: {a..z} ::: {a..z} > output.txt
于 2019-03-05T18:15:57.100 に答える