Próbowałem zrównoleglić następujący skrypt, a konkretnie każdą z trzech instancji pętli FOR, używając GNU Parallel, ale nie byłem w stanie. 4 polecenia zawarte w pętli FOR działają szeregowo, każda pętla zajmuje około 10 minut.
#!/bin/bash
kar='KAR5'
runList='run2 run3 run4'
mkdir normFunc
for run in $runList
do
fsl5.0-flirt -in $kar"deformed.nii.gz" -ref normtemp.nii.gz -omat $run".norm1.mat" -bins 256 -cost corratio -searchrx -90 90 -searchry -90 90 -searchrz -90 90 -dof 12
fsl5.0-flirt -in $run".poststats.nii.gz" -ref $kar"deformed.nii.gz" -omat $run".norm2.mat" -bins 256 -cost corratio -searchrx -90 90 -searchry -90 90 -searchrz -90 90 -dof 12
fsl5.0-convert_xfm -concat $run".norm1.mat" -omat $run".norm.mat" $run".norm2.mat"
fsl5.0-flirt -in $run".poststats.nii.gz" -ref normtemp.nii.gz -out $PWD/normFunc/$run".norm.nii.gz" -applyxfm -init $run".norm.mat" -interp trilinear
rm -f *.mat
done
shell-script
gnu-parallel
Ravnoor S. Gill
źródło
źródło
wait
polecenie na końcu, aby skrypt główny nie zakończył działania, dopóki nie zakończą się wszystkie zadania w tle.nice
, ale nie wiem, czy to się kiedykolwiek skończy ...Przykładowe zadanie
Przebiegi sekwencyjne
Równoległe przebiegi
Równoległe przebiegi w partiach N-procesowych
Możliwe jest również użycie FIFO jako semaforów i użycie ich, aby zapewnić, że nowe procesy zostaną odrodzone tak szybko, jak to możliwe, i że nie więcej niż N procesów uruchomi się w tym samym czasie. Ale wymaga więcej kodu.
N procesów z semaforem opartym na FIFO:
źródło
wait
nim w zasadzie pozwala na uruchomienie wszystkich procesów, dopóki nie dotrze donth
procesu, a następnie czeka, aż wszystkie pozostałe zakończą działanie, prawda?i
wynosi zero, zadzwoń, czekaj. Przyrosti
po teście zerowym.wait
w / no arg czeka na wszystkie dzieci. To trochę marnuje. Podejście oparte na semaforze oparte na potoku zapewnia płynniejszą współbieżność (-nt
-ot
mkfifo pipe-$$
polecenie wymaga odpowiedniego dostępu do zapisu w bieżącym katalogu. Wolę więc podać pełną ścieżkę, ponieważ/tmp/pipe-$$
najprawdopodobniej ma ona dostęp do zapisu dla bieżącego użytkownika, zamiast polegać na jakimkolwiek bieżącym katalogu. Tak, zastąp wszystkie 3 wystąpieniapipe-$$
.To, czy rzeczywiście działa, zależy od twoich poleceń; Nie znam ich.
rm *.mat
Wygląda trochę podatne na konflikty jeśli przebiega równolegle ...źródło
rm *.mat
na coś takiego,rm $run".mat"
aby uruchomić to bez zakłócania jednego procesu przez drugi proces. Dziękuję .wait
, o których zapomniałem.Użyjemy semaforów, równolegle tyle iteracji, ile jest dostępnych rdzeni (-j +0 oznacza, że zrównoleglycie zadania N + 0 , gdzie N jest liczbą dostępnych rdzeni ).
sem --wait każe poczekać, aż wszystkie iteracje w pętli for zakończą wykonywanie przed wykonaniem kolejnych wierszy kodu.
Uwaga: będziesz potrzebować „równoległego” z równoległego projektu GNU (sudo apt-get install parallel).
źródło
Jeden naprawdę łatwy sposób, którego często używam:
Spowoduje to uruchomienie polecenia, przekazującego równolegle do każdej linii pliku „args”, co najwyżej $ NUM_PARALLEL w tym samym czasie.
Możesz także spojrzeć na opcję -I dla xargs, jeśli chcesz zastąpić argumenty wejściowe w różnych miejscach.
źródło
Wygląda na to, że zadania fsl zależą od siebie, więc 4 zadania nie mogą być uruchamiane równolegle. Przebiegi można jednak uruchamiać równolegle.
Uczyń funkcję bash uruchamiającą pojedynczy przebieg i uruchom tę funkcję równolegle:
Aby dowiedzieć się więcej, obejrzyj filmy wprowadzające: https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1 i poświęć godzinę na zapoznanie się z samouczkiem http://www.gnu.org/software/parallel/parallel_tutorial.html Twoje polecenie linia cię za to pokocha.
źródło
export SHELL=/bin/bash
przed uruchomieniem równoległym. W przeciwnym razie pojawi się błąd:Unknown command 'myfunc arg'
Równoległe wykonywanie w maksymalnej liczbie równoległych procesów N
źródło
Naprawdę podoba mi się odpowiedź @lev, ponieważ zapewnia kontrolę nad maksymalną liczbą procesów w bardzo prosty sposób. Jednak jak opisano w instrukcji , sem nie działa z nawiasami.
Wykonuje pracę.
źródło
W moim przypadku nie mogę używać semaforów (jestem w git-bash na Windowsie), więc wymyśliłem ogólny sposób podziału zadania na N pracowników, zanim zaczną.
Działa dobrze, jeśli zadania zajmują mniej więcej tyle samo czasu. Wadą jest to, że jeśli jeden z pracowników zajmuje dużo czasu na wykonanie swojej części pracy, inni, którzy już skończyli, nie pomogą.
Podział pracy na N pracowników (1 na rdzeń)
źródło
Miałem problem z
@PSkocik
rozwiązaniem. Mój system nie ma GNU Parallel dostępnego jako pakiet isem
zgłosił wyjątek, kiedy go zbudowałem i uruchomiłem ręcznie. Następnie spróbowałem również przykładu semafora FIFO, który również rzucił kilka innych błędów dotyczących komunikacji.@eyeApps
zasugerowałem xargs, ale nie wiedziałem, jak sprawić, by działał z moim złożonym przypadkiem użycia (przykłady byłyby mile widziane).Oto moje rozwiązanie dla zadań równoległych przetwarzających do
N
zadań jednocześnie skonfigurowanych przez_jobs_set_max_parallel
:_lib_jobs.sh:
Przykładowe użycie:
źródło