스레드/병렬을 사용하여 bash 스크립트를 실행하는 방법

스레드/병렬을 사용하여 bash 스크립트를 실행하는 방법

다음 bash 스크립트를 있는 그대로 실행하고 있습니다. 즉, 순차적으로 진행합니다. 및 는 데이터베이스에서 파일을 다운로드하기 위한 호출 prefetch이고 , 가져온 파일을 축소하기 위해 작성한 C++ 프로그램입니다(제한된 저장 공간으로 인해).fastq-dump_shrink

이 기능을 구현하기 위해 스레드를 사용할 수 있습니까? 파일을 다운로드하는 데 시간이 오래 걸립니다.

중요한! 각 블록 내의 명령은 순차적으로 실행되어야 하지만 블록은 병렬로 실행될 수 있습니다. 그리고 한 번에 10블록만 실행하고 싶습니다.

#!/bin/bash
g++ -std=c++11 shrink_files.cpp -o _shrink

#block1    
prefetch SRR837459
fastq-dump --fasta 0 SRR837459
rm ../../sra_sequences/sra/SRR837459.sra
./_shrink SRR837459
rm SRR837459.fasta
echo "SRR837459" >> list_of_done.txt

#block1    
prefetch SRR805782
fastq-dump --fasta 0 SRR805782
rm ../../sra_sequences/sra/SRR805782.sra
./_shrink SRR805782
rm SRR805782.fasta
echo "SRR805782" >> list_of_done.txt

#... more blocks

답변1

명령을 병렬화하는 좋은 방법은 다음과 같습니다.암소 비슷한 일종의 영양parallel. 블록을 함수로 정의하세요.글렌 잭맨이 제안한 것그런 다음 병렬로 실행되며 -j최대 병렬 실행이 정의될 수 있습니다. Glenn의 접근 방식에 비해 장점은 한 블록이 완료되면 새 블록이 시작되므로 항상 10개의 블록이 동시에 실행된다는 것입니다. 이를 보려면 병렬 함수를 내보내야 합니다.

#!/bin/bash
g++ -std=c++11 shrink_files.cpp -o _shrink

block() {
  prefetch "$1"
  fastq-dump --fasta 0 "$1"
  ...
}

export -f block

parallel -j 10 block ::: id1 id2 id3 id4 ....

본인의 아이디로 교체하세요 idi. 또는 유사한 파일(SRR837459 등)에 ID가 있는 경우

id1
id2
id3

그런 다음 다음 줄을 사용합니다(다른 입력 소스가 없으면 GNU Parallel은 표준 입력에서 읽습니다).

parallel -j 10 block

스크립트를 실행하여

bash script < idlist.txt

답변2

백그라운드에서 실행할 명령을 그룹화할 수 있습니다.

테스트되지 않은

#!/bin/bash
g++ -std=c++11 shrink_files.cpp -o _shrink

block() {
    local id=$1
    prefetch "$id"
    fastq-dump --fasta 0 "$id"
    rm ../../sra_sequences/sra/"$id".sra
    ./_shrink "$id"
    rm "$id".fasta
    echo "$id" >> list_of_done.txt
}

# run first 10 blocks in the background
block SRR837459 &
block SRR805782 &
...
block 10th_id &

# and wait for them to complete
wait

# now start up on the next 10 ...
block 11th_id &
...

또는 다음 코드가 더 프로그래밍적입니다.

# all the ids to fetch
ids=( SRR837459 SRR805782 ... )

while (( ${#ids[@]} > 0 )); do
    # copy the first 10 as positional parameters
    set -- "${ids[@]:0:10}"
    # launch the blocks
    for id; do
        block "$id" &
    done
    # wait until done
    wait
    # remove the first 10 from the list
    ids=( "${ids[@]:10}" )
done

관련 정보