2012-12-07 14 views
6

Nie jestem pewien, co to znaczy, że iteracje pętli równoległej są niezależne. Czy poniższy przykład dwóch poprawnych równoległych dla pętli? Piszą i odczytują tę samą macierz, ale indeksy macierzy są unikalne dla każdej iteracji.Czy pętla równoległa może pisać do wspólnej macierzy?

X = zeros(64); 
parfor i = 1:64^2 
    X(i) = i; 
end 
parfor i = 1:64 
    X(i,:) = X(i,:) .* randn(1,64); 
end 
+0

Matlab usuwa błąd, jeśli nie jest prawidłową pętlą równoległą. Musisz po prostu uruchomić to w programie Matlab, a otrzymasz odpowiedź natychmiast. – Oli

+2

Ten cytat z dokumentów wydaje się wskazywać, że Matlab nie zawsze ostrzega: "Uwaga Z powodu niezależności zamówienia iteracyjnego wykonanie parfor nie gwarantuje wyników deterministycznych." – Andreas

+1

To oznacza, że ​​można wykonać iterację w dowolnej kolejności. To nie ma wpływu na twoją sprawę. – Oli

Odpowiedz

4

ile parfor dotyczy trzy następujące instrukcje można uznać za równoważne:

1) iteracji parfor pętli musi być niezależne.

2) Brak iteracji pętli parfor może zależeć od wyniku jakiejkolwiek innej iteracji.

3) iteracje w parfor pętli musi być wykonywane w dowolnej kolejności (od @Oli)

Jak oświadczenia te porównania do zwykłej pętli? W typowej pętli od 1 do 8, czwarta iteracja, na przykład, może zależeć od iteracji 1, 2 i 3, ponieważ oprogramowanie może być pewne, że te iteracje już wystąpiły przed osiągnięciem liczby iteracyjnej 4. NIE zależą od iteracji 5, 6, 7 i 8, ponieważ oprogramowanie może być pewne, że te powtórzenia nie wystąpią.

W pętli parfor, jak stwierdza @Ali, pętle mogą występować w dowolnej kolejności. Mogą one występować w następującej kolejności, na przykład 7 3 4 1 2 5 8 6. Lub dowolnej permutacji tych 8 liczb. To implikuje coś bardzo ważnego: Nie można się dowiedzieć przed faktem, która iteracja wystąpi jako pierwsza. Aby to zobaczyć, po prostu przetrzyj fprintf('Up to iteration %d of %d\n', t, T) wewnątrz pętli parfor, gdzie t jest pętlą dolną, a T jest górną granicą pętli.

Powyższe stwierdzenie natychmiast implikuje następujący wniosek: Ponieważ jakakolwiek iteracja może wystąpić najpierw, ważne jest, aby żadna iteracja nie zależała od wyniku jakiejkolwiek innej iteracji. Będę zawrzeć odpowiedź z kilkoma przykładami:

X = ones(8, 8) 
parfor n = 1:8 
    X(:,n) = X(:,n) .* (3 * ones(8,1)); 
end 

W tym przykładzie (3 * ones(8,1)) wyraźnie nie zależy od jakiejkolwiek innej iteracji - jest stała w stosunku do licznika pętli. Podobnie X(:, n) nie zależy od żadnej innej iteracji niż nth. EDYCJA: Poprzednio używałem randn w powyższym przykładzie - zobacz dyskusję w komentarzach dostarczonych przez @AndrewJanke, dlaczego to był zły pomysł. Co z tą sytuacją:

X = ones(8, 8); 
parfor n = 1:8 
    X(:,n) = X(:,n) + (n + 1); 
end 

Jest to również całkowicie prawidłowe. Chociaż w wyrażeniu występuje wyrażenie n + 1, nie jest to to samo, co w przypadku numeru iteracji n + 1. Raczej jest to po prostu przypisanie wartości liczby całkowitej bieżącego numeru iteracji, plus 1, do X.

Wreszcie, należy rozważyć:

X = ones(8, 1); 
parfor n = 2:8 
    X(n, 1) = X(n-1, 1) + 1; 
end 

Byłoby idealnie ważne w zwykłej pętli, ponieważ liczba iteracji n-1 będzie zawsze występować przed iteracji n (zakładając mamy pętlę do przodu). Ale w pętli parfor spowoduje to błąd, ponieważ numer iteracji n może wystąpić przed numerem iteracji n-1.Lingo Matlab używa do opisania problemu, który nazywa się "krojeniem". Wyobraź sobie, że X ma zostać pocięte przez iteracje pętli. Następnie w n-tej iteracji możesz tylko odwołać się do n-tego wycinka X.

Ostatni punkt, jeśli kiedykolwiek mam wątpliwości co do pętli parfor, przeczytałem rozdział w dokumentacji zatytułowany: "Równolegle dla pętli w Matlabie - omówienie" (przepraszam, nie mogę znaleźć odpowiedniej strony - nietypowe dla Matlaba dokumentacja) Opisuje wszystkie możliwe zmienne klasyfikacje wewnątrz pętli, a ograniczenia nakładają pętle na każdą klasyfikację. To, o czym mówiłem w tej odpowiedzi, to tak naprawdę tylko wierzchołek góry lodowej. Na przykład instrukcje takie jak n = n + 1 są również nieprawidłowe w pętli parfor, ponieważ n jest zmienną pętli, a przypisania do zmiennej pętli są niedozwolone.

+1

Hmmm. Wiesz, 'randn' może być złym tego przykładem, ponieważ ma on uboczny wpływ na globalny stan Matlaba. Jest to PRNG, a każda sesja Matlaba zaczyna się od tego samego losowego nasienia; każde wywołanie 'randn' przesuwa je dalej. Więc jego wyjście zależy od poprzednich iteracji pętli; wyjście 'randn' jest funkcją tego, ile razy zostało wywołane w tej sesji. Każdy pracownik jest sesją, więc wyniki tego kodu zależą bezpośrednio od tego, ilu pracowników istnieje, w jakiej kolejności działają pętle i co jeszcze wpłynęło na stan "rng" tych sesji. –

+1

To znaczy, myślę, że używanie 'randn' narusza zasadę" jest krytyczna, że ​​żadna iteracja nie zależy od wyniku jakiejkolwiek innej iteracji ", ponieważ częścią wyniku iteracji, która nazywa' randn' jest to, że 'rng' jest zaawansowane , i to jest ukryty wkład do 'randn'. Jest to niedookreśloność, której nie można uchwycić przez kontrolę "parfor", więc ludzki programista musi albo unikać, albo upewnić się, że niedeterminizm "nie ma znaczenia". "Właściwą" rzeczą do zrobienia jest prawdopodobnie wygenerowanie całego bloku rodów przed 'parfor', a następnie podzielenie go na iteracje w pętli; wtedy będziesz miał odtwarzalność. –

+0

@AndrewJanke Nie pomyślałem o tym! Bardzo mądry! Poprawiłem odpowiedź, aby usunąć 'randn'. Sądzę, że byłoby to tylko mylące dla czytelnika, aby włączyć dyskusję o wrodzonym determinizmie większości losowych generatorów liczb do powyższej odpowiedzi. –

Powiązane problemy