멀티 코어 CPU를 활용하기 위해 스톡 리눅스 도구가있는 최소 "작업 대기열"
-
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