멀티 코어 CPU를 활용하기 위해 스톡 리눅스 도구가있는 최소 "작업 대기열"

StackOverflow https://stackoverflow.com/questions/832253

  •  06-07-2019
  •  | 
  •  

문제

BASH 및 일반적인 도구를 사용하여 Linux 용 최소 작업 큐 시스템을 구축하는 가장/가장 쉬운 방법은 무엇입니까?

9'000 줄이있는 파일이 있고 각 줄에는 bash 명령 줄이 있으며 명령은 완전히 독립적입니다.

command 1 > Logs/1.log
command 2 > Logs/2.log
command 3 > Logs/3.log
...

내 상자에는 하나 이상의 코어가 있으며 동시에 X 작업을 실행하고 싶습니다. 나는 이것을 할 좋은 방법을 찾기 위해 웹을 검색했다. 분명히, 많은 사람들 이이 문제를 겪고 있지만 지금까지 좋은 해결책은 없습니다.

솔루션에 다음과 같은 기능이 있으면 좋을 것입니다.

  • 둘 이상의 명령을 해석 할 수 있습니다 (예 : command; command)
  • 선에서 스트림 리디렉션을 해석 할 수 있습니다 (예 : ls > /tmp/ls.txt)
  • 일반적인 Linux 도구 만 사용합니다

너무 이국적인 요구 사항없이 다른 Unix 클론에서 작동하는 경우 보너스 포인트.

도움이 되었습니까?

해결책

명령 목록을 makefile로 변환 할 수 있습니까? 그렇다면 "make -j x"를 실행할 수 있습니다.

다른 팁

GNU 평행 http://www.gnu.org/software/parallel/ PPS보다 병렬화하기위한보다 일반적인 도구입니다.

runfile에 포함 된 경우 :

command 1 > Logs/1.log
command 2 > Logs/2.log
command 3 > Logs/3.log

넌 할 수있어:

cat runfile | parallel -j+0

CPU 코어 당 하나의 명령을 실행합니다.

명령이 위와 같이 단순하면 런 파일이 필요하지 않지만 할 수 있습니다.

seq 1 3 | parallel -j+0 'command {} > Logs/{}.log'

처리를 수행 할 수있는 더 많은 컴퓨터가있는 경우 GNU 병렬에 대한 -sshlogin 및 -trc 옵션을 살펴볼 수 있습니다.

좋아, 여기에 질문을 게시 한 후, 나는 유망한 것으로 보이는 다음 프로젝트를 발견했다. ppss.

편집 : 내가 원하는 것이 아니라 PPSS는 "디렉토리 A의 모든 파일"을 처리하는 데 중점을 둡니다.

글쎄, 이것은 어쨌든 일종의 재미있는 질문입니다.

여기에 내가하는 일이 있습니다 배쉬 (1) 물론.

  • 이러한 명령 중 몇 개가 동시에 유용하게 실행할 수 있는지 알아 봅니다. 그것은 단지 코어의 수가되지 않을 것입니다. I/O와 그런 종류의 많은 명령이 중단됩니다. 그 숫자 N을 전화하십시오. N=15 예를 들어.
  • 하위 프로세스가 종료 될 때 발생하는 Sigchld 신호에 대한 트랩 신호 처리기를 설정합니다. trap signalHandler SIGCHLD
  • 당신의 명령 목록을 파이프에 고정하십시오
  • stdin을 읽고 명령을 하나씩 실행하는 루프를 작성하여 카운터를 줄입니다. 카운터가 0 일 때 wait에스.
  • Sigchld에서 실행되는 신호 핸들러, 증분 그 카운터.

이제 첫 번째로 실행됩니다 N 명령을 기다린 다음 기다립니다. 첫 번째 자식이 종료되면 대기가 반환되고 다른 줄을 읽고 새 명령을 실행하고 다시 기다립니다.

이제 이것은 많은 일자리가 함께 종료되는 것을 돌보는 경우입니다. 나 의심하다 더 간단한 버전으로 도망 갈 수 있습니다.

 N=15
 COUNT=N
 cat mycommands.sh | 
 while read cmd 
 do
   eval $cmd &
   if $((count-- == 0))
   then
       wait
   fi
 od

이제 이것은 처음 15 개의 명령을 시작한 다음 일부 명령이 종료 될 때 나머지는 한 번에 하나씩 실행됩니다.

비슷한 분산 컴퓨팅 재미는 MapReduce Bash 스크립트입니다.

http://blog.last.fm/2009/04/06/mapreduce-bash-script

PPSS를 지적 해 주셔서 감사합니다!

당신은 사용할 수 있습니다 Xargs 명령 -최대 프로그램 당신이 원하는 것을합니다. 예를 들어 Charlie Martin 솔루션은 Xargs와 함께됩니다.

tr '\012' '\000' <mycommands.sh |xargs --null --max-procs=$X bash -c

세부:

  • X는 최대 프로세스 수입니다. 예 : x = 15. -Max Procs는 마법을하고 있습니다
  • 첫 번째 TR은 XARGS에 대해 NULL 바이트로 라인을 종료하기 위해 여기에 있습니다.
  • bash -c는 명령을 실행합니다

예를 들어이 mycommands.sh 파일로 테스트했습니다.

date
date "+%Y-%m-%d" >"The Date".txt
wc -c <'The Date'.txt >'The Count'.txt

이것은 특정 사례이지만 파일 세트를 처리하고 다른 출력 파일 세트를 생성하려는 경우 #Cores 수의 프로세스를 시작하고 처리하기 전에 출력 파일이 있는지 확인할 수 있습니다. 아래 예제는 .m4b 파일 디렉토리를 .mp3 파일로 변환합니다.

코어가있는 만큼이 명령을 여러 번 실행하십시오.

ls *m4b | 읽는 동안 f; test -f $ {f%m4b} mp3 || mencoder -of rawaudio "$ f"-oac mp3lame -ovc copy -o $ {f%m4b} mp3; 완료 &

Bash에 내 작업 대기열이 작성된 것을 볼 수 있습니다. https://github.com/pavelpat/yastq

작업 대기열 + 병렬화 + 동적 추가

FIFO를 사용 하여이 스크립트 자체를 포크하여 대기열을 처리합니다. 이렇게하면 즉시 대기열에 명령을 추가 할 수 있습니다 (대기열이 이미 시작된 경우).

사용법 : ./queue 명령 [#의#] [대기열 이름

예, 1 스레드와 함께 :

./queue "sleep 5; echo ONE"
./queue "echo TWO"

산출:

ONE
TWO

예, 2 스레드와 함께 :

./queue "sleep 5; echo ONE" 2
./queue "echo TWO"

산출:

TWO
ONE

예를 들어 2 개의 대기열이 있습니다.

./queue "sleep 5; echo ONE queue1" 1 queue1
./queue "sleep 3; echo ONE queue2" 1 queue2

산출:

ONE queue2
ONE queue1

스크립트 ( "큐"로 저장하고 chmod +x 대기열로 저장) :

    #!/bin/bash

    #Print usage
    [[ $# -eq 0 ]] && echo Usage: $0 Command [# of children] [Queue name] && exit

    #Param 1 - Command to execute
    COMMAND="$1"

    #Param 2 - Number of childs in parallel
    MAXCHILD=1
    [[ $# -gt 1 ]] && MAXCHILD="$2"

    #Param 3 - File to be used as FIFO
    FIFO="/tmp/defaultqueue"
    [[ $# -gt 2 ]] && FIFO="$3"

    #Number of seconds to keep the runner active when unused
    TIMEOUT=5

    runner(){
      #Associate file descriptor 3 to the FIFO
      exec 3"$FIFO"

      while read -u 3 -t $TIMEOUT line; do
        #max child check
        while [ `jobs | grep Running | wc -l` -ge "$MAXCHILD" ]; do
          sleep 1
        done

        #exec in backgroud
        (eval "$line")&
      done
      rm $FIFO
    }

    writer(){
      #fork if the runner is not running
      lsof $FIFO >/dev/null || ($0 "QueueRunner" "$MAXCHILD" "$FIFO" &)

      #send the command to the runner
      echo "$COMMAND" > $FIFO
    }

    #Create the FIFO file
    [[ -e "$FIFO" ]] || mkfifo "$FIFO"

    #Start the runner if in the runner fork, else put the command in the queue
    [[ "$COMMAND" == "QueueRunner" ]] && runner || writer

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top