C ++

GPU програмиране с C ++

GPU програмиране с C ++

Общ преглед

В това ръководство ще изследваме силата на GPU програмирането с C++. Разработчиците могат да очакват невероятна производителност с C ++, а достъпът до феноменалната мощ на графичния процесор с език на ниско ниво може да доведе до някои от най-бързите изчисления, налични в момента.

Изисквания

Въпреки че всяка машина, способна да изпълнява модерна версия на Linux, може да поддържа компилатор на C ++, ще ви е необходим графичен процесор, базиран на NVIDIA, който да следва заедно с това упражнение. Ако нямате графичен процесор, можете да завъртите екземпляр, задвижван от графичен процесор, в Amazon Web Services или друг доставчик на облак по ваш избор.

Ако изберете физическа машина, моля, уверете се, че имате инсталирани собствени драйвери на NVIDIA. Можете да намерите инструкции за това тук: https: // linuxhint.com / install-nvidia-drivers-linux /

В допълнение към драйвера ще ви е необходим инструментариумът CUDA. В този пример ще използваме Ubuntu 16.04 LTS, но има налични изтегляния за повечето основни дистрибуции на следния URL: https: // разработчик.nvidia.com / cuda-downloads

За Ubuntu бихте избрали .изтегляне на базата на deb. Изтегленият файл няма да има .deb разширение по подразбиране, затова препоръчвам да го преименувате, за да има .деб в края. След това можете да инсталирате с:

sudo dpkg -i име на пакета.деб

Вероятно ще бъдете подканени да инсталирате GPG ключ и ако е така, следвайте предоставените инструкции за това.

След като направите това, актуализирайте своите хранилища:

sudo apt-get update
sudo apt-get install cuda -y

След като приключите, препоръчвам да рестартирате, за да сте сигурни, че всичко е заредено правилно.

Ползите от развитието на GPU

Процесорите се справят с много различни входове и изходи и съдържат голям набор от функции за не само справяне с широк асортимент от програмни нужди, но и за управление на различни хардуерни конфигурации. Те също така се справят с паметта, кеширането, системната шина, сегментирането и IO функционалността, което ги прави вале за всички сделки.

Графичните процесори са обратното - те съдържат много отделни процесори, които са фокусирани върху много прости математически функции. Поради това те обработват задачите многократно по-бързо от процесорите. Като се специализират в скаларни функции (функция, която приема един или повече входове, но връща само един изход), те постигат изключителна производителност за сметка на екстремната специализация.

Примерен код

В примерния код добавяме вектори заедно. Добавих версия на CPU и GPU на кода за сравнение на скоростта.
gpu-пример.cpp съдържание по-долу:

#include "cuda_runtime.ч "
#include
#include
#include
#include
#include
typedef std :: chrono :: high_resolution_clock Clock;
#define ITER 65535
// CPU версия на функцията за добавяне на вектор
void vector_add_cpu (int * a, int * b, int * c, int n)
int i;
// Добавяне на векторните елементи a и b към вектора c
за (i = 0; i < n; ++i)
c [i] = a [i] + b [i];


// GPU версия на функцията за добавяне на вектор
__global__ void vector_add_gpu (int * gpu_a, int * gpu_b, int * gpu_c, int n)
int i = threadIdx.х;
// Не е необходим цикъл, защото изпълнението на CUDA
// ще преведе това ITER пъти
gpu_c [i] = gpu_a [i] + gpu_b [i];

int main ()
int * a, * b, * c;
int * gpu_a, * gpu_b, * gpu_c;
a = (int *) malloc (ITER * sizeof (int));
b = (int *) malloc (ITER * sizeof (int));
c = (int *) malloc (ITER * sizeof (int));
// Нуждаем се от променливи, достъпни за графичния процесор,
// така че cudaMallocManaged ги предоставя
cudaMallocManaged (& gpu_a, ITER * sizeof (int));
cudaMallocManaged (& gpu_b, ITER * sizeof (int));
cudaMallocManaged (& gpu_c, ITER * sizeof (int));
за (int i = 0; i < ITER; ++i)
a [i] = i;
b [i] = i;
c [i] = i;

// Извикайте функцията на процесора и я определете по време
auto cpu_start = Clock :: now ();
vector_add_cpu (a, b, c, ITER);
auto cpu_end = Clock :: now ();
std :: cout << "vector_add_cpu: "
<< std::chrono::duration_cast(cpu_end - cpu_start).броя()
<< " nanoseconds.\n";
// Обадете се на функцията GPU и я измервайте по време
// Тройните ъглови скоби са разширение за изпълнение на CUDA, което позволява
// параметри на извикване на ядрото CUDA, което трябва да бъде предадено.
// В този пример предаваме един блок от нишки с ITER нишки.
auto gpu_start = Clock :: now ();
vector_add_gpu <<<1, ITER>>> (gpu_a, gpu_b, gpu_c, ITER);
cudaDeviceSynchronize ();
auto gpu_end = Clock :: now ();
std :: cout << "vector_add_gpu: "
<< std::chrono::duration_cast(gpu_end - gpu_start).броя()
<< " nanoseconds.\n";
// Освобождаване на разпределението на паметта въз основа на GPU-функция
cudaFree (а);
cudaFree (b);
cudaFree (c);
// Освободете разпределението на паметта въз основа на CPU-функцията
безплатно (а);
безплатно (б);
безплатно (c);
връщане 0;

Makefile съдържание по-долу:

INC = -I / usr / local / cuda / включва
NVCC = / usr / local / cuda / bin / nvcc
NVCC_OPT = -std = c ++ 11
всичко:
$ (NVCC) $ (NVCC_OPT) gpu-пример.cpp -o gpu-пример
чисто:
-rm -f gpu-пример

За да стартирате примера, компилирайте го:

направи

След това стартирайте програмата:

./ gpu-пример

Както можете да видите, версията на процесора (vector_add_cpu) работи значително по-бавно от версията на графичния процесор (vector_add_gpu).

Ако не, може да се наложи да коригирате дефиницията на ITER в gpu-пример.cu на по-голямо число. Това се дължи на това, че времето за настройка на графичния процесор е по-дълго от някои по-малки цикли, интензивни за процесора. Установих, че 65535 работи добре на моята машина, но пробегът ви може да варира. След като изчистите този праг, GPU е драстично по-бърз от CPU.

Заключение

Надявам се да сте научили много от въвеждането ни в GPU програмирането с C++. Примерът по-горе не постига много, но демонстрираните концепции осигуряват рамка, която можете да използвате, за да включите идеите си, за да разгърнете мощта на вашия графичен процесор.

Как да използвам AutoKey за автоматизиране на Linux игри
AutoKey е програма за автоматизация на настолни компютри за Linux и X11, програмирана в Python 3, GTK и Qt. Използвайки неговата функционалност за скр...
Как да покажа брояч на FPS в игрите на Linux
Linux игрите получиха голям тласък, когато Valve обяви поддръжка на Linux за Steam клиент и техните игри през 2012 г. Оттогава много AAA и независими ...
Как да изтеглите и пуснете Civilization VI на Сид Майер на Linux
Въведение в играта Civilization 6 е модерен поглед върху класическата концепция, въведена в поредицата от игрите Age of Empires. Идеята беше доста про...