Updated on 2 kwietnia, 2018
OpenCL tutorial – część 2 – listowanie dostępnych urządzeń
Przed nami druga część wprowadzenia do OpenCL. W tej części pokażę jak sprawdzić czy nasz sprzęt obsługuje OpenCL.
Naszym zadaniem jest wypisanie wszystkich urządzeń zainstalowanych w naszym komputerze, które wspierają OpenCL.
Na początek pobierzemy liczbę platform:
1 2 3 4 5 6 |
cl_int error = CL_SUCCESS; // Get platform number. cl_uint platformNumber = 0; error = clGetPlatformIDs(0, NULL, &platformNumber); |
Zmienna platformNumber powinna przechowywać liczbę dostępnych platform, które obsługują OpenCL. Zmienna error zawiera 0 (CL_SUCCESS), jeżeli operacja wykonała się poprawnie lub liczbę różną od zera, jeżeli wystąpił błąd.
Funkcja clGetPlatformIDs ma dwa zastosowania. Pierwsze już znamy, czyli pobieranie liczby dostępnych platform, a drugie to pobieranie listy identyfikatorów dostępnych platform.
Najpierw alokujemy pamięć, a następnie pobieramy identyfikatory:
1 2 3 4 |
// Get platform identifiers. cl_platform_id* platformIds = new cl_platform_id[platformNumber]; error = clGetPlatformIDs(platformNumber, platformIds, NULL); |
Skoro znamy już identyfikatory platform, to wykorzystajmy je do pobrania bardziej szczegółowych informacji na temat platform. Dzięki funkcji clGetPlatformInfo możemy poznać takie dane jak nazwa czy producent platformy:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// Get platform info. for (cl_uint i = 0; i < platformNumber; ++i) { char name[1024] = { '\0' }; std::cout << "Platform:\t" << i << std::endl; error = clGetPlatformInfo(platformIds[i], CL_PLATFORM_NAME, 1024, &name, NULL); std::cout << "Name:\t\t" << name << std::endl; error = clGetPlatformInfo(platformIds[i], CL_PLATFORM_VENDOR, 1024, &name, NULL); std::cout << "Vendor:\t\t" << name << std::endl; std::cout << std::endl; } |
Wiemy już na jakich platformach możemy operować, czas na pobranie informacji o konkretnych urządzeniach, które wspierają OpenCL.
Pobieranie informacji na temat urządzeń jest bardzo podobne do pobierania informacji na temat platform. Najpierw pobieramy liczbę urządzeń, następnie alokujemy pamięć na ich identyfikatory, a na końcu pobieramy szczegółowe informacje na temat urządzenia takie jak nazwa czy wersja.
Poniższy kod umieszczamy w pętli, dzięki czemu pobierzemy informacje na temat wszystkich urządzeń we wszystkich platformach:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
// Get device count. cl_uint deviceNumber; error = clGetDeviceIDs(platformIds[i], CL_DEVICE_TYPE_GPU, 0, NULL, &deviceNumber); if (0 == deviceNumber) { std::cout << "No OpenCL devices found on platform " << i << "." << std::endl; } // Get device identifiers. cl_device_id* deviceIds = new cl_device_id[deviceNumber]; error = clGetDeviceIDs(platformIds[i], CL_DEVICE_TYPE_GPU, deviceNumber, deviceIds, &deviceNumber); // Get device info. for (cl_uint i = 0; i < deviceNumber; ++i) { char name[1024] = { '\0' }; std::cout << "Device:\t\t" << i << std::endl; error = clGetDeviceInfo(deviceIds[i], CL_DEVICE_NAME, 1024, &name, NULL); std::cout << "Name:\t\t" << name << std::endl; error = clGetDeviceInfo(deviceIds[i], CL_DEVICE_VENDOR, 1024, &name, NULL); std::cout << "Vendor:\t\t" << name << std::endl; error = clGetDeviceInfo(deviceIds[i], CL_DEVICE_VERSION, 1024, &name, NULL); std::cout << "Version:\t" << name << std::endl; } std::cout << std::endl; // Free memory. delete[] deviceIds; |
Kompilujemy i uruchamiamy nasz program.
Kod programu
Cały kod powinien wyglądać tak:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
#include #include #include <CL/cl.h> int main() { cl_int error = 0; // Get platform number. cl_uint platformNumber = 0; error = clGetPlatformIDs(0, NULL, &platformNumber); if (0 == platformNumber) { std::cout << "No OpenCL platforms found." << std::endl; return 0; } // Get platform identifiers. cl_platform_id* platformIds = new cl_platform_id[platformNumber]; error = clGetPlatformIDs(platformNumber, platformIds, NULL); // Get platform info. for (cl_uint i = 0; i < platformNumber; ++i) { char name[1024] = { '\0' }; std::cout << "Platform:\t" << i << std::endl; error = clGetPlatformInfo(platformIds[i], CL_PLATFORM_NAME, 1024, &name, NULL); std::cout << "Name:\t\t" << name << std::endl; error = clGetPlatformInfo(platformIds[i], CL_PLATFORM_VENDOR, 1024, &name, NULL); std::cout << "Vendor:\t\t" << name << std::endl; std::cout << std::endl; // Get device count. cl_uint deviceNumber; error = clGetDeviceIDs(platformIds[i], CL_DEVICE_TYPE_GPU, 0, NULL, &deviceNumber); if (0 == deviceNumber) { std::cout << "No OpenCL devices found on platform " << i << "." << std::endl; } // Get device identifiers. cl_device_id* deviceIds = new cl_device_id[deviceNumber]; error = clGetDeviceIDs(platformIds[i], CL_DEVICE_TYPE_GPU, deviceNumber, deviceIds, &deviceNumber); // Get device info. for (cl_uint i = 0; i < deviceNumber; ++i) { char name[1024] = { '\0' }; std::cout << "Device:\t\t" << i << std::endl; error = clGetDeviceInfo(deviceIds[i], CL_DEVICE_NAME, 1024, &name, NULL); std::cout << "Name:\t\t" << name << std::endl; error = clGetDeviceInfo(deviceIds[i], CL_DEVICE_VENDOR, 1024, &name, NULL); std::cout << "Vendor:\t\t" << name << std::endl; error = clGetDeviceInfo(deviceIds[i], CL_DEVICE_VERSION, 1024, &name, NULL); std::cout << "Version:\t" << name << std::endl; } std::cout << std::endl; // Free memory. delete[] deviceIds; } // Free memory. delete[] platformIds; // Press Enter, to quit application. std::cin.get(); return 0; } |
Wyniki
Program po uruchomieniu powinien dać wynik podobny do poniższego:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
Platform: 0 Name: Intel(R) OpenCL Vendor: Intel(R) Corporation Device: 0 Name: Intel(R) HD Graphics 4000 Vendor: Intel(R) Corporation Version: OpenCL 1.1 Platform: 1 Name: NVIDIA CUDA Vendor: NVIDIA Corporation Device: 0 Name: GeForce GT 650M Vendor: NVIDIA Corporation Version: OpenCL 1.1 CUDA |
Widzimy wszystkie platformy oraz urządzenia, które obsługują OpenCL. W moim przypadku jest to zintegrowana karta graficzna Intel HD Graphics 4000 oraz GeForce GT 650M.
Źródła w serwisie GitLab.
W następnej części kursu wykonamy i uruchomimy pierwszy program OpenCL.
dzięki za tutorial, właśnie czegoś takiego szukałem.
aczkolwiek czepiłbym się jednego zdania, a mianowicie „Cały kod powinien wyglądać tak” (przed kodem)…
wydaje mi się, że twórca Czystego Kodu polemizowałby czy ten kod rzeczywiście powinien tak wyglądać :P
Proszę o konkrety, bo sposobów tworzenia i formatowania kodu jest więcej niż samych programistów.
Kod w tutorialu ma być prosty i skupiać się na tłumaczonym zagadnieniu. Każdy zrozumie dwie pętlę i kilka coutów. Gdybym miał pisać zgodnie ze wszystkimi „dobrymi praktykami tworzenia kodu”, to tutorial byłby 10x dłuższy ;)
wow, szybka odpowiedź.
Rozumiem, że to dlatego, że to tutorial. Po prostu akurat to zdanie mnie „uderzyło” bo ostatnio mam zajęcia, na których wykładowca bardzo czepia się takich rzeczy :P
To dobrze, że się czepia, bo takich rzeczy należy uczyć się od początku. Tutaj mamy do czynienia z kursem dotyczącym wybranego zagadnienia, a nie ogólnie programowania. Po pierwsze, w tym przypadku stosowanie tych wszystkich dobrych praktyk i zasad pisania czystego i ładnego kodu tylko utrudniałoby zrozumienie kodu. Po drugie, zawartości książek takich jak „Czysty kod” to tylko porady i wskazówki, a nie nakazy. Te zasady należy dostosować do tworzonego projektu, zespołu, klienta itd. oraz stosować wtedy, gdy naprawdę odniesiemy z nich jakieś korzyści, a nie zawsze i wszędzie, bo autor twierdzi, że tak jest lepiej.