2011-09-23 4 views
6

Chcę zrozumieć, w jaki sposób tworzony jest kontekst cuda i który jest powiązany z aplikacjami jądra w aplikacjach Cunt Runtime API?Tworzenie kontekstu cuda i powiązanie zasobów w aplikacjach środowiska wykonawczego API

Wiem, że odbywa się pod maską przez API sterowników. Chciałbym jednak zrozumieć oś czasu stworzenia.

Na początek wiem, cudaRegisterFatBinary jest pierwszym wywołaniem cuda api, które rejestruje plik fatbin w środowisku wykonawczym. Następuje garstka funkcji API rejestracji funkcji cuda, które wywołują cuModuleLoad w warstwie sterownika. Ale jeśli moja aplikacja API środowiska wykonawczego Cuda wywoła cudaMalloc, to w jaki sposób wskaźnik jest przekazywany do tej funkcji powiązanej z kontekstem, który, jak sądzę, powinien zostać stworzony wcześniej. Jak uzyskać uchwyt do tego już utworzonego kontekstu i powiązać z nim przyszłe wywołania interfejsu API środowiska wykonawczego? Proszę wyjaśnić wewnętrzne działania.

Cytując dokumentacji NVIDIA na tej

CUDA Runtime API połączenia działają na CUDA Sterownik API CUcontext który jest zobowiązany do bieżącego wątku gospodarza.

Jeśli nie istnieje sterownik CUDA API CUcontext związany z bieżącym wątku w czasie z CUDA Runtime wywołanie API, które wymaga CUcontext wtedy CUDA Runtime niejawnie utworzyć nowy CUcontext przed wykonaniem połączenia.

Jeśli CUDA Runtime tworzy CUcontext wtedy CUcontext będzie tworzone przy użyciu parametrów określonych przez API CUDA Runtime funkcje cudaSetDevice, cudaSetValidDevices, cudaSetDeviceFlags, cudaGLSetGLDevice, cudaD3D9SetDirect3DDevice, cudaD3D10SetDirect3DDevice i cudaD3D11SetDirect3DDevice. Zauważ, że te funkcje zakończy się niepowodzeniem z cudaErrorSetOnActiveProcess, jeśli są one wywołane, gdy tekst CUcontext jest powiązany z bieżącym wątkiem hosta.

Żywotność CUcontext jest zarządzana przez mechanizm liczący zliczający . Licznik odwołań CUcontext jest początkowo ustawiony na 0, i jest zwiększany przez cuCtxAttach i zmniejszany przez cuCtxDetach.

Jeśli CUcontext jest tworzony przez CUDA Runtime, wówczas środowisko wykonawcze CUDA będzie zmniejszyć liczbę odwołań tego CUcontext w funkcji cudaThreadExit. Jeśli CUcontext jest tworzony przez CUDA Driver API (lub jest tworzony przez oddzielne wystąpienie biblioteki CUDA Runtime API), , wówczas środowisko wykonawcze CUDA nie zwiększy ani nie zmniejszy liczby referencyjnej o wartość CUcontext.

Cały stan API środowiska wykonawczego CUDA (np. Adresy zmiennych globalnych i wartości ) przemieszcza się wraz z podstawowym tekstem CUcontext. W szczególności, jeśli tekst CUcontext zostanie przeniesiony z jednego wątku do drugiego (przy użyciu cuCtxPopCurrent i cuCtxPushCurrent), wówczas cały stan API środowiska wykonawczego CUDA przeniesie się również do tego wątku do .

Ale nie rozumiem, w jaki sposób środowisko wykonawcze cuda tworzy kontekst? jakie wywołania API są używane do tego? Czy kompilator nvcc wstawia niektóre wywołania API, aby to zrobić w czasie kompilacji, czy jest to wykonywane całkowicie w czasie wykonywania? Jeśli pierwsza z nich jest prawdziwa, jakie interfejsy API używane w czasie wykonywania są używane do zarządzania kontekstem? Późniejsze jest prawdą, jak dokładnie zostało to zrobione?

Jeśli kontekst jest powiązany z wątkiem hosta, w jaki sposób uzyskujemy dostęp do tego kontekstu? Czy jest automatycznie kojarzony ze wszystkimi zmiennymi i referencjami do wskaźnika zajmowanymi przez wątek?

jak ostatecznie ładowanie modułu odbywa się w kontekście?

Odpowiedz

3

Środowisko wykonawcze CUDA zachowuje globalną listę modułów do załadowania i dodaje tę listę za każdym razem, gdy do procesu ładowana jest biblioteka DLL lub .so, która używa środowiska wykonawczego CUDA. Ale moduły nie są faktycznie ładowane dopóki urządzenie nie zostanie utworzone.

Tworzenie i inicjowanie kontekstów odbywa się "leniwie" przez środowisko wykonawcze CUDA - za każdym razem, gdy wywołujesz funkcję podobną do funkcji cudaMemcpy(), sprawdza, czy CUDA została zainicjowana, a jeśli nie, to tworzy kontekst (na urządzeniu określonym wcześniej przez cudaSetDevice() lub urządzenie domyślne, jeśli funkcja cudaSetDevice() nigdy nie była wywoływana) i ładuje wszystkie moduły. Kontekst jest związany z tym wątkiem CPU od tego momentu, dopóki nie zostanie zmieniony przez cudaSetDevice().

Możesz użyć funkcji zarządzania kontekstem/wątkami z interfejsu API sterownika, takich jak cuCtxPopCurrent()/cuCtxPushCurrent(), aby użyć kontekstu z innego wątku.

Możesz wywołać cudaFree (0); aby wymusić tę leniwą inicjalizację.

Zdecydowanie radzę zrobić to w czasie inicjowania aplikacji, aby uniknąć warunków wyścigu i niezdefiniowanych zachowań. Śmiało i wyliczyć i zainicjować urządzenia tak wcześnie, jak to możliwe w swojej aplikacji; kiedy już to zrobisz, w CUDA 4.0 możesz wywołać cudaSetDevice() z dowolnego wątku procesora i wybierze odpowiedni kontekst, który został utworzony przez twój kod inicjujący.

+0

Próbowałem użyć cudaFree (0). Ale wciąż nie dostałem kontekstu. CuCtxPop zwrócił wartość null. Dlaczego tak jest? – ash

+0

Zdecydowanie powinieneś mieć aktualny kontekst po udanym cudaFree (0). Czy sprawdziłeś wartość zwrotu? – ArchaeaSoftware

+0

Po przeanalizowaniu problemu stwierdziłem, że CudaFree (0) daje mi błąd nieprawidłowego uchwytu zasobu. Czy masz jakiś pomysł, dlaczego? – ash

Powiązane problemy