Rozważ następujący scenariusz. Mam dwa programy A i B. Program A wyprowadza na standardowe linie ciągów, a program B na linie standardowe ze standardowego wejścia. Oczywiście sposobem na użycie tych dwóch programów jest:
foo @ bar: ~ $ A | b
Teraz zauważyłem, że zjada to tylko jeden rdzeń; stąd zastanawiam się:
Czy programy A i B współużytkują te same zasoby obliczeniowe? Jeśli tak, to czy istnieje sposób na jednoczesne uruchomienie A i B?
Inną rzeczą, którą zauważyłem, jest to, że A działa znacznie szybciej niż B, dlatego zastanawiam się, czy mógłby jakoś uruchomić więcej programów B i pozwolić im przetwarzać linie, które A wyprowadza równolegle.
Oznacza to, że A wypisuje swoje wiersze i byłoby N instancji programów B, które czytałyby te wiersze (ktokolwiek je czyta jako pierwszy) przetwarzałyby je i wypisywały na standardowym wyjściu.
Więc moje ostatnie pytanie brzmi:
Czy istnieje sposób na skierowanie wyjścia do A pomiędzy kilkoma procesami B bez konieczności dbania o warunki wyścigu i inne niespójności, które mogą wystąpić?
źródło
A | B | C
jest równoległy, jak w oddzielnych procesach, ze względu na charakter rur (B musi czekać na wyjście A, C musi czekać na wyjście B), w niektórych przypadkach może być liniowy. Zależy to całkowicie od rodzaju produkcji, jaką wytwarzają. Nie ma wielu przypadków, w których uruchomienie wieluB
pomógłoby bardzo, jest całkiem możliwe, że przykład równoległego wc jest wolniejszy niż normalny,wc
ponieważ dzielenie może zająć więcej zasobów niż normalne liczenie linii. Używaj ostrożnie.Odpowiedzi:
Problem
split --filter
polega na tym, że dane wyjściowe mogą być pomieszane, więc otrzymujesz pół linii z procesu 1, a następnie pół linii z procesu 2.GNU Parallel gwarantuje, że nie będzie pomieszania.
Załóż więc, że chcesz:
Ale to B jest strasznie wolne i dlatego chcesz to zrównoważyć. Następnie możesz zrobić:
GNU Parallel domyślnie dzieli \ n i wielkość bloku 1 MB. Można to zmienić za pomocą --recend i --block.
Możesz znaleźć więcej informacji na temat GNU Parallel na: http://www.gnu.org/s/parallel/
Możesz zainstalować GNU Parallel w zaledwie 10 sekund za pomocą:
Obejrzyj film wprowadzający na stronie http://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
źródło
--block-size
będzie zależeć od ilości pamięci RAM i tego, jak szybko można rozpocząć nowąB
. W twojej sytuacji skorzystam--block 100M
i zobaczę, jak to działa.sh
- jest świetna. Problem polega na przekazaniu go do sh: pobieranie i uruchamianie kodu wykonywalnego z witryny . Pamiętaj, może po prostu jestem zbyt paranoikiem, ponieważ można sprzeciwić się, że niestandardowe RPM lub DEB to w zasadzie to samo, a nawet opublikowanie kodu na stronie do skopiowania i wklejenia spowoduje, że ludzie zrobią to na ślepo tak czy siak.Kiedy piszesz
A | B
, oba procesy działają już równolegle. Jeśli widzisz, że używają tylko jednego rdzenia, prawdopodobnie wynika to z jednego z ustawień koligacji procesora (być może istnieje jakieś narzędzie do odrodzenia procesu o innym powinowactwie) lub dlatego, że jeden proces nie wystarcza do utrzymania całego rdzenia, a system „ woli „nie rozpowszechniać informatyki.Aby uruchomić kilka B z jednym A, potrzebujesz narzędzia takiego jak
split
z--filter
opcją:Może to jednak popsuć kolejność linii na wyjściu, ponieważ zadania B nie będą działały z tą samą prędkością. Jeśli jest to problem, może być konieczne przekierowanie wyjścia B i-tego do pliku pośredniego i połączenie ich na końcu za pomocą
cat
. To z kolei może wymagać znacznego miejsca na dysku.Istnieją inne opcje (np można ograniczyć każdą instancję B do jednego wyjścia liniowego buforowane, poczekaj, aż cała „okrągły” z B zakończy, uruchom odpowiednik zmniejszyć do
split
„s mapę icat
wyjście tymczasowe razem), o różnym poziomie wydajności. Opisana na przykład opcja „round” będzie czekać na zakończenie najwolniejszej instancji B , więc będzie w dużym stopniu zależna od dostępnego buforowania dla B;[m]buffer
może pomóc lub nie, w zależności od operacji.Przykłady
Wygeneruj pierwsze 1000 liczb i policz linie równolegle:
Gdybyśmy „oznaczyli” linie, zobaczylibyśmy, że każda pierwsza linia jest wysyłana do przetwarzania nr 1, każda piąta linia do przetwarzania nr 5 i tak dalej. Co więcej, w czasie potrzebnym
split
na odrodzenie drugiego procesu, pierwszy jest już dobrym sposobem na przydzielenie limitu:Podczas wykonywania na maszynie 2-rdzeniowej
seq
,split
awc
procesy współużytkują rdzenie; ale patrząc bliżej, system pozostawia pierwsze dwa procesy na CPU0 i dzieli CPU1 na procesy robocze:Zwróć uwagę, że
split
zjada znaczną ilość procesora. Zmniejszy się proporcjonalnie do potrzeb A; tj. jeśli A jest procesem cięższym niżseq
, względny narzutsplit
zmniejszy się. Ale jeśli A jest bardzo lekkim procesem, a B jest dość szybki (tak że nie potrzebujesz więcej niż 2-3 B, aby zachować zgodność z A), wówczas równoległe stosowaniesplit
(lub ogólnie rur) może nie być tego warte.źródło
split
--filter
brakuje Ci opcji? Na moim Ubuntu 12.04-LTS („wheezy / sid”) jest tam i moje przykłady działają. Czy mógłbyś zainstalować innysplit
niż ten w jądrach GNU?