2011-07-31 13 views
41

W OpenCL rozumiem, że można użyć funkcji barrier() do synchronizowania wątków w grupie roboczej. Robię (ogólnie) rozumiem, do czego służą i kiedy z nich korzystać. Jestem również świadomy, że wszystkie wątki w grupie roboczej muszą trafić w barierę, w przeciwnym razie wystąpią problemy. Jednak za każdym razem, gdy próbowałem dotychczas korzystać z barier, wydaje mi się, że albo zawiesza się sterownik wideo, albo pojawia się komunikat o błędzie dostępu do nieprawidłowej pamięci. Widziałem to na 2 różnych kartach wideo (1 ATI, 1 NVIDIA).Bariery w OpenCL

Więc moje pytania to:

  1. Każdy pomysł, dlaczego tak się stało?
  2. Jaka jest różnica między barrier(CLK_LOCAL_MEM_FENCE) a barrier(CLK_GLOBAL_MEM_FENCE)? Czytałem dokumentację, ale nie było dla mnie jasne.
  3. Czy istnieje ogólna zasada dotycząca stosowania barrier(CLK_LOCAL_MEM_FENCE) kontra barrier(CLK_GLOBAL_MEM_FENCE)?
  4. Czy jest jakiś czas, że wywołanie barrier() z nieprawidłowym typem parametru może spowodować błąd?

Odpowiedz

30

Jak już stwierdzono, bariery mogą synchronizować tylko wątki w tej samej grupie roboczej. Nie ma sposobu, aby zsynchronizować różne grupy robocze w jądrze.

teraz, aby odpowiedzieć na pytanie, specyfikacja nie było dla mnie jasne, albo, ale wydaje mi się, że rozdział 6.11.9 zawiera odpowiedź:

CLK_LOCAL_MEM_FENCE - Funkcja bariera będzie albo zrzucającej zmiennych przechowywane w pamięci lokalnej lub w kolejce do pamięci, aby zapewnić prawidłowe porządkowanie operacji pamięci w pamięci lokalnej.

CLK_GLOBAL_MEM_FENCE - Funkcja bariery spowoduje umieszczenie w kolejce ogrodzenia pamięci , aby zapewnić poprawne porządkowanie operacji pamięci w pamięci globalnej. Może to być przydatne podczas pracy z obiektami, na przykład zapisywania do bufora lub obrazów obiektów pamięci obrazów, a następnie czytania zaktualizowanych danych.

Tak, w moim rozumieniu, należy użyć CLK_LOCAL_MEM_FENCE podczas pisania i czytania w przestrzeni __local pamięci i CLK_GLOBAL_MEM_FENCE pisząc i readin do przestrzeni __global pamięci.

nie testowałem, czy jest to wolniej, ale przez większość czasu, kiedy muszę barierę i mam wątpliwości, o których pamięć jest odbiło, po prostu użyć kombinacji tych dwóch, to znaczy:

barrier(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE); 

W ten sposób nie powinieneś mieć żadnego problemu z odczytaniem pamięci \ tak, jak masz pewność, że każdy wątek grupy przechodzi przez barierę, ale jesteś tego świadomy).

Mam nadzieję, że to pomaga.

+3

Oczywiście CLK_GLOBAL_MEM_FENCE często mniejsza niż CLK_LOCAL_MEM_FENCE. Powodem jest, że wszystkie wątki wewnątrz bloku będą musiały poczekać na zakończenie dostępu do pamięci. A oczekiwanie, że dostęp do pamięci globalnej zostanie zakończony, jest znacznie droższe niż dostęp do pamięci lokalnej. Oczywiście nie zawsze jest to prawdą, zależy to od wzorców dostępu (Fermi ma teraz pamięć podręczną, co oznacza, że ​​globalne dostępy mogą być buforowane na L1, które ma podobne opóźnienie z pamięcią wspólną), liczba globalnych/lokalnych dostępów do pamięci w jądrze obłożenie, konflikty bankowe, koalescencje itp. – Zk1001

31

Ożywiając starą nitkę tutaj. Sam miałem kłopoty z barierą().

Jeśli chodzi o problem z awarią, jedną z potencjalnych przyczyn może być sytuacja, w której bariera znajduje się w stanie.Czytam, że gdy używasz bariery, WSZYSTKIE elementy pracy w grupie muszą być w stanie dotrzeć do tej instrukcji, lub zawiesisz jądro - zwykle powodując awarię.

if(someCondition){ 
    //do stuff 
    barrier(CLK_LOCAL_MEM_FENCE); 
    //more stuff 
}else{ 
    //other stuff 
} 

moim rozumieniu jest to, że jeśli jeden lub więcej elementów pracy spełnia someCondition wszystkie elementy robocze muszą spełniać ten warunek, lub nie będzie pewne, że będzie przeskoczyć barierę. Bariery czekają, aż WSZYSTKIE elementy pracy osiągną ten punkt. Aby rozwiązać powyższy kod, muszę ją zrestrukturyzować trochę:

if(someCondition){ 
    //do stuff 
} 
barrier(CLK_LOCAL_MEM_FENCE); 
if(someCondition){ 
    //more stuff 
}else{ 
    //other stuff 
} 

Teraz wszystkie elementy robocze osiągnie barierę.

Nie wiem, w jakim stopniu dotyczy to pętli; jeśli element pracy zrywa z pętli for, czy uderza w bariery? Nie jestem pewien.

AKTUALIZACJA: Udało mi się rozbić kilka programów ocl z barierą w pętli for. Upewnij się, że wszystkie elementy pracy opuszczają pętlę for w tym samym czasie - lub jeszcze lepiej, umieść barierę poza pętlą.

(źródło: Heterogeniczne Komputer z OpenCL rozdział 5 p90-91)

+2

Dziękuję za komentarz. Nie jestem też pewien, ale podejrzewam, że wszystkie wątki w grupie roboczej muszą trafić w barierę, jeśli którykolwiek wątek z tej grupy roboczej. Tak więc, w przypadku pętli, jeśli wszystkie wątki w grupie roboczej ulegną zerwaniu przed uderzeniem w barierę, nie ma problemu. Ale jeśli przynajmniej jeden wątek z grupy roboczej uderza w barierę w danej iteracji pętli, to wszystkie wątki (z tej grupy roboczej) również muszą. –

+0

Innym przypadkiem, w którym dokumentacja wydaje się pomijać, jest również przypadek posiadania znaku if/else i wywoływania bariery w obu przypadkach. Nie wydaje się, aby to spowodowało awarię programu, ale wydaje się, że nie ma to żadnego wpływu. Odkryłem, że kod przykładowy AMD utrzymuje wszystkie wątki w pętlach for, nawet jeśli niektóre nie mają celu, ale uderzają w barierę. –