동시 명령 수 제한과 동시에 명령 실행


23

순차적 : for i in {1..1000}; do do_something $i; done-너무 느림

병렬 : for i in {1..1000}; do do_something $i& done-너무 많은 부하

명령을 병렬로 실행하는 방법 (예 : 순간 당 20 개 이하)?

이제는 일반적으로 hack과 같은 것을 사용 for i in {1..1000}; do do_something $i& sleep 5; done하지만 이것은 좋은 해결책이 아닙니다.

업데이트 2 : 허용 된 답변을 스크립트로 변환 : http://vi-server.org/vi/parallel

#!/bin/bash

NUM=$1; shift

if [ -z "$NUM" ]; then
    echo "Usage: parallel <number_of_tasks> command"
    echo "    Sets environment variable i from 1 to number_of_tasks"
    echo "    Defaults to 20 processes at a time, use like \"MAKEOPTS='-j5' parallel ...\" to override."
    echo "Example: parallel 100 'echo \$i; sleep \`echo \$RANDOM/6553 | bc -l\`'"
    exit 1
fi

export CMD="$@";

true ${MAKEOPTS:="-j20"}

cat << EOF | make -f - -s $MAKEOPTS
PHONY=jobs
jobs=\$(shell echo {1..$NUM})

all: \${jobs}

\${jobs}:
        i=\$@ sh -c "\$\$CMD"
EOF

"i ="를 사용하려면 8 개의 공백을 2 개의 탭으로 바꿔야합니다.

답변:


15

이를 위해 GNU Parallel 이 만들어졌습니다.

seq 1 1000 | parallel -j20 do_something

원격 컴퓨터에서 작업을 실행할 수도 있습니다. 다음은 server2와 CPU 코어 당 1 개의 작업을 실행하는 로컬 컴퓨터를 사용하여 MP3를 OGG로 다시 인코딩하는 예입니다.

parallel --trc {.}.ogg -j+0 -S server2,: \
     'mpg321 -w - {} | oggenc -q0 - -o {.}.ogg' ::: *.mp3

여기에서 GNU Parallel에 대한 소개 비디오를보십시오.

http://www.youtube.com/watch?v=OpaiGYxkSuQ


"moreutils"에 대해 알지 못했으며 이미 작업을위한 도구가 있습니다. 보고 비교하기.
Vi.

1
parallelmoreutils의는 GNU의 평행하지 않은 꽤 해당 옵션에 제한된다. 위의 명령은 moreutils의 병렬로 실행되지 않습니다.
Ole Tange

1
하나 더 옵션 : xargs --max-procs=20.
Vi.

4

bash 솔루션은 아니지만 Makefile을 사용해야합니다 -l. 최대로드를 초과하지 않아야합니다.

NJOBS=1000

.PHONY = jobs
jobs = $(shell echo {1..$(NJOBS)})

all: $(jobs)

$(jobs):
    do_something $@

그런 다음 한 번에 20 개의 작업을 시작하려면

$ make -j20

또는로드 5를 초과하지 않고 가능한 많은 작업을 시작

$ make -j -l5

지금은 해킹이 아닌 솔루션처럼 보입니다.
Vi.

2
echo -e 'PHONY=jobs\njobs=$(shell echo {1..100000})\n\nall: ${jobs}\n\n${jobs}:\n\t\techo $@; sleep `echo $$RANDOM/6553 | bc -l`' | make -f - -j20이제 다시 더 해키 보인다.
Vi.

@vi : oh my ....
Benjamin Bannier

솔루션을 스크립트로 변환했습니다. 이제 쉽게 사용할 수 있습니다.
Vi.

2

질문 형식으로 질문에 스크립트를 게시 :

#!/bin/bash

NUM=$1; shift

if [ -z "$NUM" ]; then
    echo "Usage: parallel <number_of_tasks> command"
    echo "    Sets environment variable i from 1 to number_of_tasks"
    echo "    Defaults to 20 processes at a time, use like \"MAKEOPTS='-j5' parallel ...\" to override."
    echo "Example: parallel 100 'echo \$i; sleep \`echo \$RANDOM/6553 | bc -l\`'"
    exit 1
fi

export CMD="$@";

true ${MAKEOPTS:="-j20"}

cat << EOF | make -f - -s $MAKEOPTS
PHONY=jobs
jobs=\$(shell echo {1..$NUM})

all: \${jobs}

\${jobs}:
        i=\$@ sh -c "\$\$CMD"
EOF

"i ="전에 8 개의 공백을 2 개의 탭으로 바꿔야합니다.


1

간단한 아이디어 :

i modulo 20을 확인하고 do_something 전에 wait shell 명령을 실행하십시오.


모든 현재 작업이 완료 될 때까지 기다리거나 (작업 수 줄거리에서 처짐 생성) 오랜 시간 동안 정지 될 수있는 특정 작업 (이 경우에는 처짐 생성)을 기다립니다
.

@Vi : 쉘 대기는이 쉘에 속하는 모든 백그라운드 작업을위한 것입니다.
harrymc

1

ps실행중인 프로세스 수를 계산하는 데 사용할 수 있으며 특정 임계 값 아래로 떨어질 때마다 다른 프로세스를 시작합니다.

의사 코드 :

i = 1
MAX_PROCESSES=20
NUM_TASKS=1000
do
  get num_processes using ps
  if num_processes < MAX_PROCESSES
    start process $i
    $i = $i + 1
  endif
  sleep 1 # add this to prevent thrashing with ps
until $i > NUM_TASKS

1
for i in {1..1000}; do 
     (echo $i ; sleep `expr $RANDOM % 5` ) &
     while [ `jobs | wc -l` -ge 20 ] ; do 
         sleep 1 
     done
done

수 있음 while [ `jobs | wc -l` -ge 20]; do?
Vi.

그러나 샘플에서는 njobs두 번 계산해야하며 절전 작업을 실행하는 셸 스크립트에서는 성능이 매우 중요합니다.)
msw

나는 당신의 버전이 예상대로 작동하지 않는 것을 의미합니다. 나는 20 개 대신 40-50 개로 평균 njobs를 변경 sleep 1하기 sleep 0.1시작합니다. 20 개가 넘는 작업이 있으면 1 초 정도 기다리지 않고 작업이 완료 될 때까지 기다려야합니다.
Vi.

0

이렇게 할 수 있습니다.

threads=20
tempfifo=$PMS_HOME/$$.fifo

trap "exec 1000>&-;exec 1000<&-;exit 0" 2
mkfifo $tempfifo
exec 1000<>$tempfifo
rm -rf $tempfifo

for ((i=1; i<=$threads; i++))
do
    echo >&1000
done

for ((j=1; j<=1000; j++))
do
    read -u1000
    {
        echo $j
        echo >&1000
    } &
done

wait
echo "done!!!!!!!!!!"

명명 된 파이프를 사용하면 매번 20 개의 하위 셸을 병렬로 실행합니다.

그것이 도움이되기를 바랍니다 :)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.