Używam CUDA od kilku tygodni, ale mam pewne wątpliwości co do alokacji bloków / wypaczeń / wątków. Studiuję architekturę z dydaktycznego punktu widzenia (projekt uniwersytecki), więc osiągnięcie maksymalnej wydajności nie jest moim problemem.
Przede wszystkim chciałbym zrozumieć, czy dobrze zrozumiałem te fakty:
Programista pisze jądro i organizuje jego wykonanie w siatce bloków wątków.
Każdy blok jest przypisany do wieloprocesora strumieniowego (SM). Po przypisaniu nie można go migrować do innego SM.
Każda SM dzieli swoje własne bloki na Warps (obecnie o maksymalnym rozmiarze 32 wątków). Wszystkie wątki w warpie są wykonywane jednocześnie na zasobach SM.
Faktyczne wykonanie wątku jest wykonywane przez rdzenie CUDA zawarte w SM. Nie ma określonego mapowania między wątkami i rdzeniami.
Jeśli osnowa zawiera 20 wątków, ale obecnie dostępnych jest tylko 16 rdzeni, osnowa nie będzie działać.
Z drugiej strony, jeśli blok zawiera 48 wątków, zostanie podzielony na 2 wypaczenia i będą one wykonywane równolegle, pod warunkiem, że dostępna jest wystarczająca ilość pamięci.
Jeśli wątek zostanie uruchomiony na rdzeniu, zostanie zatrzymany w celu uzyskania dostępu do pamięci lub długiej operacji zmiennoprzecinkowej, jego wykonanie może zostać wznowione na innym rdzeniu.
Czy mają rację?
Teraz mam GeForce 560 Ti, więc zgodnie ze specyfikacją jest wyposażony w 8 SM, każdy zawierający 48 rdzeni CUDA (łącznie 384 rdzenie).
Moim celem jest upewnienie się, że każdy rdzeń architektury wykonuje SAME instrukcje. Zakładając, że mój kod nie będzie wymagał więcej rejestrów niż te dostępne w każdym SM, wyobrażałem sobie różne podejścia:
Tworzę 8 bloków po 48 wątków, więc każdy SM ma 1 blok do wykonania. Czy w takim przypadku 48 wątków będzie działać równolegle w SM (wykorzystując wszystkie 48 dostępnych dla nich rdzeni)?
Czy jest jakaś różnica, jeśli uruchomię 64 bloki po 6 wątków? (Zakładając, że zostaną one odwzorowane równomiernie między SM)
Jeśli "zanurzę" GPU w zaplanowanej pracy (na przykład tworząc 1024 bloki po 1024 wątki), to rozsądnie jest założyć, że wszystkie rdzenie zostaną użyte w pewnym momencie i wykonają te same obliczenia (zakładając, że wątki nigdy nie przeciągnij)?
Czy istnieje sposób, aby sprawdzić te sytuacje za pomocą profilera?
Czy jest jakieś odniesienie do tych rzeczy? Przeczytałem przewodnik programowania CUDA oraz rozdziały poświęcone architekturze sprzętowej w rozdziałach „Programowanie masowo równoległych procesorów” oraz „Projektowanie i tworzenie aplikacji CUDA”; ale nie mogłem uzyskać dokładnej odpowiedzi.