Ta odpowiedź składa się z dwóch części (napisałem ją). Jedna część jest łatwa do oszacowania, druga jest bardziej empiryczna.
Ograniczenia sprzętowe:
To jest łatwa do oszacowania część. Dodatek F aktualnego przewodnika programowania CUDA zawiera listę twardych ograniczeń, które ograniczają liczbę wątków na blok, które może mieć uruchomienie jądra. Jeśli przekroczysz którąkolwiek z tych wartości, twoje jądro nigdy nie będzie działać. Można je z grubsza podsumować jako:
- Każdy blok nie może mieć łącznie więcej niż 512/1024 wątków (odpowiednio Compute Capability 1.x lub 2.xi nowsze)
- Maksymalne wymiary każdego bloku są ograniczone do [512,512,64] / [1024,1024,64] (Oblicz 1.x / 2.x lub nowszy)
- Każdy blok nie może zużywać więcej niż 8k / 16k / 32k / 64k / 32k / 64k / 32k / 64k / 32k / 64k łącznie rejestrów (Compute 1.0, 1.1 / 1.2, 1.3 / 2.x- / 3.0 / 3.2 / 3.5-5.2 / 5,3 / 6–6,1 / 6,2 / 7,0)
- Każdy blok nie może zużywać więcej niż 16 kb / 48 kb / 96 kb pamięci współdzielonej (Compute 1.x / 2.x-6.2 / 7.0)
Jeśli pozostaniesz w tych granicach, każde jądro, które uda Ci się pomyślnie skompilować, uruchomi się bez błędów.
Podnoszenie wydajności:
To jest część empiryczna. Liczba wątków na blok, którą wybierzesz w ramach ograniczeń sprzętowych opisanych powyżej, może wpływać i wpływa na wydajność kodu działającego na sprzęcie. Zachowanie każdego kodu będzie inne, a jedynym prawdziwym sposobem jego ilościowego określenia jest staranna analiza porównawcza i profilowanie. Ale znowu, bardzo z grubsza podsumowując:
- Liczba wątków na blok powinna być zaokrągloną wielokrotnością rozmiaru osnowy, który wynosi 32 na całym obecnym sprzęcie.
- Każda jednostka wieloprocesorowa do przesyłania strumieniowego w GPU musi mieć wystarczającą liczbę aktywnych wypaczeń, aby w wystarczającym stopniu ukryć całą różną pamięć i opóźnienia potoku instrukcji architektury i osiągnąć maksymalną przepustowość. Ortodoksyjne podejście polega tutaj na próbie uzyskania optymalnego wykorzystania sprzętu (do czego odnosi się odpowiedź Rogera Dahla ).
Druga kwestia to obszerny temat, w którym wątpię, aby ktokolwiek spróbował ująć go w jednej odpowiedzi StackOverflow. Są ludzie, którzy piszą prace doktorskie wokół ilościowej analizy aspektów problemu (zob. Prezentację Wasilija Wołkowa z UC Berkley i ten artykuł Henry'ego Wonga z University of Toronto, gdzie znajdują się przykłady tego, jak skomplikowane jest to pytanie).
Na poziomie początkowym powinieneś być świadomy, że wybrany rozmiar bloku (w zakresie dozwolonych rozmiarów bloków zdefiniowanych przez powyższe ograniczenia) może i ma wpływ na szybkość działania kodu, ale zależy to od sprzętu masz i kod, który uruchamiasz. Porównując testy porównawcze, prawdopodobnie okaże się, że większość nietrywialnych kodów ma „słodki punkt” w zakresie 128-512 wątków na blok, ale będzie to wymagało pewnej analizy z Twojej strony, aby znaleźć to, gdzie to jest. Dobra wiadomość jest taka, że ponieważ pracujesz z wielokrotnościami rozmiaru warp, przestrzeń wyszukiwania jest bardzo ograniczona, a najlepsza konfiguracja dla danego fragmentu kodu jest stosunkowo łatwa do znalezienia.
Powyższe odpowiedzi wskazują, jak rozmiar bloku może wpływać na wydajność i sugerują typową heurystykę jej wyboru opartą na maksymalizacji obłożenia. Nie chcąc zapewnić kryterium wyboru rozmiaru bloku, warto byłoby wspomnieć, że CUDA 6.5 (obecnie w wersji Release Candidate) zawiera kilka nowych funkcji, aby pomóc w czasie wykonywania obliczeń obłożenia i konfiguracji startu, patrz
Wskazówka CUDA Pro: API Occupancy upraszcza konfigurację uruchamiania
Jedną z przydatnych funkcji jest
cudaOccupancyMaxPotentialBlockSize
heurystyczna kalkulacja rozmiaru bloku, który zapewnia maksymalną liczbę osób. Wartości dostarczane przez tę funkcję można następnie wykorzystać jako punkt wyjścia do ręcznej optymalizacji parametrów uruchamiania. Poniżej znajduje się mały przykład.EDYTOWAĆ
Element
cudaOccupancyMaxPotentialBlockSize
jest zdefiniowany wcuda_runtime.h
pliku i jest zdefiniowany w następujący sposób:Znaczenie parametrów jest następujące
Zauważ, że od CUDA 6.5, trzeba obliczyć własne wymiary bloku 2D / 3D z rozmiaru bloku 1D sugerowanego przez API.
Należy również zauważyć, że interfejs API sterownika CUDA zawiera funkcjonalnie równoważne interfejsy API do obliczania zajętości, więc możliwe jest użycie
cuOccupancyMaxPotentialBlockSize
w kodzie interfejsu API sterownika w taki sam sposób, jak pokazano w przypadku interfejsu API środowiska wykonawczego w powyższym przykładzie.źródło
Rozmiar bloku jest zwykle wybierany w celu maksymalizacji „zajętości”. Wyszukaj w CUDA Occupancy, aby uzyskać więcej informacji. W szczególności zobacz arkusz kalkulacyjny kalkulatora CUDA Occupancy Calculator.
źródło