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: // developer.nvidia.com / cuda-downloads

Для Ubuntu вы должны выбрать .загрузка на основе deb. Загруженный файл не будет иметь .deb по умолчанию, поэтому я рекомендую переименовать его, чтобы он имел .деб в конце. Затем вы можете установить с помощью:

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

Скорее всего, вам будет предложено установить ключ GPG, и если это так, следуйте инструкциям, чтобы сделать это.

Как только вы это сделаете, обновите свои репозитории:

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

После этого я рекомендую перезагрузиться, чтобы убедиться, что все правильно загружено.

Преимущества разработки на GPU

ЦП обрабатывают множество различных входов и выходов и содержат большой набор функций не только для работы с широким ассортиментом программных потребностей, но и для управления различными конфигурациями оборудования. Они также обрабатывают память, кеширование, системную шину, сегментирование и функции ввода-вывода, что делает их мастером на все руки.

Графические процессоры наоборот - они содержат множество отдельных процессоров, которые ориентированы на очень простые математические функции. Из-за этого они обрабатывают задачи во много раз быстрее, чем процессоры. Специализируясь на скалярных функциях (функция, которая принимает один или несколько входных данных, но возвращает только один выход), они достигают исключительной производительности за счет экстремальной специализации.

Пример кода

В примере кода мы складываем векторы вместе. Я добавил версию кода для CPU и GPU для сравнения скорости.
gpu-example.cpp содержание ниже:

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


// Версия функции добавления вектора для графического процессора
__global__ void vector_add_gpu (int * gpu_a, int * gpu_b, int * gpu_c, int n)
int i = threadIdx.Икс;
// Цикл for не нужен, потому что среда выполнения CUDA
// потянем этот ИТЭР раз
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));
// Нам нужны переменные, доступные для GPU,
// поэтому cudaMallocManaged предоставляет эти
cudaMallocManaged (& gpu_a, ITER * sizeof (int));
cudaMallocManaged (& gpu_b, ИТЭР * sizeof (int));
cudaMallocManaged (& gpu_c, ITER * sizeof (int));
для (int i = 0; i < ITER; ++i)
а [я] = я;
б [я] = я;
с [я] = я;

// Вызов функции ЦП и время ее выполнения
auto cpu_start = Часы :: сейчас ();
vector_add_cpu (а, б, в, ИТЭР);
auto cpu_end = Часы :: сейчас ();
std :: cout << "vector_add_cpu: "
<< std::chrono::duration_cast(cpu_end - cpu_start).считать()
<< " nanoseconds.\n";
// Вызов функции графического процессора и время ее выполнения
// Скобки с тройным углом - это расширение среды выполнения CUDA, которое позволяет
// параметры вызова ядра CUDA для передачи.
// В этом примере мы передаем один блок потока с потоками ITER.
auto gpu_start = Часы :: сейчас ();
vector_add_gpu <<<1, ITER>>> (gpu_a, gpu_b, gpu_c, ИТЭР);
cudaDeviceSynchronize ();
auto gpu_end = Часы :: сейчас ();
std :: cout << "vector_add_gpu: "
<< std::chrono::duration_cast(gpu_end - gpu_start).считать()
<< " nanoseconds.\n";
// Освобождаем выделение памяти на основе функций графического процессора
cudaFree (а);
cudaFree (б);
cudaFree (c);
// Освобождаем выделение памяти на основе функций ЦП
бесплатно (а);
бесплатно (б);
бесплатно (c);
возврат 0;

Makefile содержание ниже:

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

Чтобы запустить пример, скомпилируйте его:

делать

Затем запустите программу:

./ gpu-example

Как видите, версия CPU (vector_add_cpu) работает значительно медленнее, чем версия GPU (vector_add_gpu).

В противном случае вам может потребоваться настроить определение ИТЭР в gpu-example.у.е. на большее число. Это связано с тем, что время настройки графического процессора больше, чем в некоторых меньших циклах, интенсивно использующих ЦП. Я обнаружил, что 65535 хорошо работает на моей машине, но ваш пробег может отличаться. Однако, как только вы очистите этот порог, графический процессор станет значительно быстрее, чем процессор.

Заключение

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

Как установить League Of Legends на Ubuntu 14.04
Если вы поклонник League of Legends, то это возможность для вас протестировать League of Legends. Обратите внимание, что LOL поддерживается в PlayOnLi...
Установите последнюю версию игры OpenRA Strategy в Ubuntu Linux
OpenRA - это игровой движок Libre / Free Real Time Strategy, воссоздающий ранние игры Westwood, такие как классическая Command & Conquer: Red Alert. Р...
Установите последнюю версию эмулятора Dolphin для Gamecube и Wii в Linux
Эмулятор Dolphin позволяет вам играть в выбранные вами игры Gamecube и Wii на персональных компьютерах (ПК) Linux. Являясь свободно доступным игровым...