Вы находитесь на странице: 1из 5

Зайцев Д.А.

Грид-технологии и облачные вычисления

Лабораторная работа № 4

Разработка массово-параллельных программ для графических процессорных устройств


(GPU) в системе CUDA

Краткая информация

Специализированные графические процессоры появились как средство ускоренной обработки


графической информации, в особенности в режиме реального времени в симуляторах,
использующих трёхмерную виртуальную реальность. В последнее время грфический процессор
стал неотъемлемой частью персонального компьютера. В отсутствие задач работы с графикой
устройство простаивало, что открыло возможности его использования как сопроцессора для
массово-параллельной обработки информации. В настоящее время набор мощных графических
процессоров является неотъемлемой частью современных суперкомпьютеров. Доминирующее
положение на рынке GPU занимает компания NVIDIA, предоставляя для своих устройств
инструментальное программное обеспечение CUDA для программирования GPU.

Задание

1. Выполнить компииляцию и запуск примеров программ в системе CUDA на удалённом


сервере.

2. Установить систему CUDA на своём компьютере и протестировать её, используя примеры


программ пункта 1; сравнить производительность, указать характеристики компьютеров.

3. Разработать параллельные программы с использованием средств CUDA в соответствии с


вариантом задания.

4. Выполнить сравнительное тестирование производительности программ на своём и удалённом


компьютерах.

5. Сравнить производительность последовательных программ и параллельных программ,


использующих средства OpenMP и MPI (ЛР 3), CUDA.

Содержание отчёта

1. Протокол (листинг) команд и результатов их выполнения (сокращённо) .


2. Файлы параллельных программ с использованием средств CUDA в соответствии с вариантом
задания.
3. Проверка результатов работы программ.
4. Таблицы тестирования производительности для последовательной программы и при
использовании различных средств параллельного и распределенного программирования на
нескольких компьютерах (видеокартах).
5. Выводы
Порядок выполнения работы

I. Выполнить компииляцию и запуск примеров программ в системе CUDA на удалённом


сервере.

1. Установить ssh-клиент на своём устройстве. Предустановлен по умолчанию в Linux. Имеется


практически для всех платформ, включая мобильные устройства различных компаний.

2. Войти на удалённый сервер в соответствии с указанным преподавателем IP-адресом и


паролем

ssh student@<ip-address>

3. Перейти в каталог cuda

cd cuda

4. Откомпилировать и запустить примеры программ: cuda-hello.cu (Приложение П.1) и


sumArraysOnGPU-timer.cu (ядро в Приложении П.2)

nvcc cuda-hello.cu -o cuda-hello


./cuda-hello

nvcc sumArraysOnGPU-timer.cu -o sumArraysOnGPU-timer


./sumArraysOnGPU-timer

5. Скопировать программы на свой компьютер, для этого открыть терминальное окно на своём
компьютере и ввести

rcp student@<ip-address>:cuda/cuda-hello.cu .

и аналогично для программы sumArraysOnGPU-timer.cu

6. Модифицировать программу, например, добавить в программу cuda-hello.cu печать


собственного имени и фамилии, сохранив её с именем cuda-hello-<fio>.cu Скопировать
программу на удалённый сервер

rcp cuda-hello-<fio>.cu student@<ip-address>:cuda

откомпилировать и запустить откорректированную программу.

II. Установить систему CUDA на своём компьютере и протестировать её, используя


примеры программ пункта 1; сравнить производительность, указать характеристики
компьютеров.

1. Перейти на сайт https://developer.nvidia.com/cuda-downloads


2. Выбрать и загрузить установочный файл в соответствии с используемой платформой,
например cuda_11.1.1_455.32.00_linux.run
3. Запустить загруженный файл

sudo ./cuda_11.1.1_455.32.00_linux.run

4. Следовать диалогу с установочной программой

5. Выполнить тестирование CUDA и видеокарты, компилируя и запуская ранее изученные


примеры.

III. Разработать параллельные программы с использованием средств CUDA в


соответствии с вариантом задания.

Реализовать программу в соответствии с вариантом задания, используя в качестве прототипа


программу сложения векторов sumArraysOnGPU-timer.cu (ядро в Приложении П.2) и ядро для
умножения матриц (Приложение П.3). Допускается, для получения оценок кроме отличных,
рассчитать на GPU только показатель степени матрицы, а возведение в степень (умножение)
матриц выполнить на центральном процессоре.

В Приложении П.3 показано ядро умножения матриц с использованием двумерной решётки


двумерных блоков. Возможно использование других схем, например одномерная решётка и
одномерный блок.

IV. Выполнить сравнительное тестирование производительности программ на своём и


удалённом компьютерах.

В процессе тестирования производительности (бенчмарк) использовать достаточно большие


исходные данные и различные комбинации размера решётки и блока. Заполнить таблицу.
Рекомендовано графическое представление результатов тестирования.

V. Сравнить производительность последовательных программ и параллельных программ,


использующих средства OpenMP и MPI (ЛР 3), CUDA.

Результаты сравнения представить в табличной и/или графической формах.

Варианты задания (совпадают с вариантами ЛР 3):

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.

где и - целочисленные векторы длиной , - вещественная матрица размером ;


заполнить векторы и матрицу случайными числами.

Приложения:

П1. Программа печати сообщений:

#include <stdio.h>

__global__ void helloFromGPU (void)


{
printf("Hello Word from GPU\n");
}

int main (void)


{
printf("Hello Word from Central Processor\n");

helloFromGPU <<<1, 10>>>();


cudaDeviceReset();
return 0;
}

П2. Ядро для сложения векторов:

__global__ void sumArraysOnGPU(float *A, float *B, float *C, const int N)
{
int i = blockIdx.x * blockDim.x + threadIdx.x;

if (i < N) C[i] = A[i] + B[i];


}

Описание грида и блока:

int iLen = 512;


dim3 block (iLen);
dim3 grid ((nElem + block.x - 1) / block.x);

П3. Ядро для умножения матриц:


__global__ void matrixMultiplicationKernel(float* A, float* B, float* C, int N) {

int ROW = blockIdx.y*blockDim.y+threadIdx.y;


int COL = blockIdx.x*blockDim.x+threadIdx.x;

float tmpSum = 0;

if (ROW < N && COL < N) {


// each thread computes one element of the block sub-matrix
for (int i = 0; i < N; i++) {
tmpSum += A[ROW * N + i] * B[i * N + COL];
}
}
C[ROW * N + COL] = tmpSum;
}

Описание грида и блока:

#define BLOCK_SIZE 16
dim3 threadsPerBlock (BLOCK_SIZE, BLOCK_SIZE)
int n_blocks = ceil(N/BLOCK_SIZE);
dim3 blocksPerGrid (n_blocks, n_blocks)
dim3 threadsPerBlock (BLOCK_SIZE, BLOCK_SIZE)
---