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

Серебряков И.А.

Отчет ПИН-12М
Лабораторная работа №1

Основы работы с технологией CUDA. Гибридное программирование. Работа с


глобальной памятью

Цель: изучить модель программирования в CUDA, иерархию памяти в CUDA и


основные особенности работы с глобальной памятью.

Лабораторные задания (№ варианта = № студента в списке %2)

Вариант = 13 % 2 = 1

Задание 1. В MS Visual Studio создать проект CUDA VS Wizard. Ознакомиться и


запустить программу «Hello world». Получить информацию об устройстве. Измерить
время выполнения программы. Результаты занести в отчёт.

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
 
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
 
#define N (1024 * 1024)
 
__global__ void kernel(float *data) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
float x = 2.0f * 3.1415926f * (float)idx / (float)N;
data[idx] = sinf(sqrtf(x));
}
 
void hello_world() {
float *a = (float *)malloc(N * sizeof(float));
float *dev = NULL;
 
cudaMalloc((void **)&dev, N * sizeof(float));
 
kernel<<<dim3(N / 512, 1), dim3(512, 1)>>>(dev);
 
cudaMemcpy(a, dev, N * sizeof(float), cudaMemcpyDeviceToHost);
cudaFree(dev);
 
for (int idx = 0; idx < N; idx++)
printf("a[%d] = %.5f\n", idx, a[idx]);
 
free(a);
}
 
void print_gpu_info() {
int device_count = 0;
cudaDeviceProp device_info;
 
cudaGetDeviceCount (&device_count);
printf("Found %d devices\n", device_count);
 
for (int device = 0; device < device_count; ++device)
{
cudaGetDeviceProperties(&device_info, device);
printf("Device %d\n", device);
printf("Compute capability : %d.%d\n", device_info.major,
device_info.minor);
printf("Name : %s\n", device_info.name);
printf("Total Global Memory : %u\n", device_info.totalGlobalMem);
printf("Shared memory per block: %d\n", device_info.sharedMemPerBlock);
Серебряков И.А. Отчет ПИН-12М
printf("Registers per block : %d\n", device_info.regsPerBlock);
printf("Warp size : %d\n", device_info.warpSize);
printf("Max threads per block : %d\n", device_info.maxThreadsPerBlock);
printf("Total constant memory : %d\n", device_info.totalConstMem);
}
}
 
float mesuare_gpu_execution_time(void (*function)(void)) {
cudaEvent_t start;
cudaEvent_t stop;
 
cudaEventCreate(&start);
cudaEventCreate(&stop);
 
float gpu_execution_time = 0.0;
 
cudaEventRecord(start, 0);
function();
cudaEventRecord(stop, 0);
 
cudaEventSynchronize(stop);
cudaEventElapsedTime(&gpu_execution_time, start, stop);
 
cudaEventDestroy(start);
cudaEventDestroy(stop);
 
return gpu_execution_time;
}
 
int main(int argc, char *argv[])
{
float hello_world_time = mesuare_gpu_execution_time(hello_world);
printf("CUDA \'Hello, World\' execution time: %.5f\n", hello_world_time);
 
print_gpu_info();
 
return 0
}

ЗДЕСЬ ДОЛЖЕН БЫТЬ ВЫВОД ПРОГРАММЫ!

Задание 2. Написать программу на Cи с использованием CUDA runtime API в


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

Вариант Задание

1 Даны два вектора А и В из N натуральных (ненулевых) элементов


(задаются случайно). Вектора расположены в глобальной памяти.

Написать программу, выполняющую поэлементное умножение двух


векторов на GPU.

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
 
#include <stdio.h>
#include <math.h>
Серебряков И.А. Отчет ПИН-12М
#include <time.h>
#include <string.h>
 
#define LIMIT 10
 
__global__ void mult_kernel(int *a, int *b, int *c) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
c[idx] = a[idx] * b[idx];
}
 
void cpu_mult_vectors(int *a, int *b, int *c, int N) {
for (int i = 0; i < N; ++i) {
c[i] = a[i] * b[i];
}
}
 
bool equal_vectors(int *lhs, int *rhs, int N) {
for (int i = 0; i < N; ++i) {
if (lhs[i] != rhs[i]) {
printf("lhs[%d] != rhs[%d]: %d != %d\n", i, i, lhs[i], rhs[i]);
return false;
}
}
 
return true;
}
 
void array_init(int *arr, size_t arr_size) {
srand(time(NULL));
 
for (int i = 0; i < arr_size; ++i) {
arr[i] = rand() % 10;
}
}
 
float gpu_mult_vectors(int *a, int *b, int *c, int N) {
int *dev_a = NULL;
int *dev_b = NULL;
int *dev_c = NULL;
 
cudaMalloc((void **)&dev_a, N * N * sizeof(int));
cudaMalloc((void **)&dev_b, N * N * sizeof(int));
cudaMalloc((void **)&dev_c, N * N * sizeof(int));
 
cudaEvent_t start;
cudaEvent_t stop;
 
cudaEventCreate(&start);
cudaEventCreate(&stop);
 
float gpu_execution_time = 0.0;
 
cudaEventRecord(start, 0);
mult_kernel<<<dim3(N, 1), dim3(N, 1)>>>(dev_a, dev_b, dev_c);
cudaEventRecord(stop, 0);
 
cudaEventSynchronize(stop);
cudaEventElapsedTime(&gpu_execution_time, start, stop);
 
cudaEventDestroy(start);
cudaEventDestroy(stop);
 
cudaMemcpy(c, dev_c, N * N * sizeof(int), cudaMemcpyDeviceToHost);
 
cudaFree(dev_a);
cudaFree(dev_b);
cudaFree(dev_c);
 
return gpu_execution_time;
}
 
Серебряков И.А. Отчет ПИН-12М
int main(int argc, char *argv[]) {
float execution_times[LIMIT];
 
for (int i = 0; i < LIMIT; ++i) {
// 1. Generate random vectors
int *a = (int *)malloc(N * N * sizeof(int));
int *b = (int *)malloc(N * N * sizeof(int));
int *c_cpu = (int *)malloc(N * N * sizeof(int));
int *c_gpu = (int *)malloc(N * N * sizeof(int));
 
int n = (int)pow(2.0, (double)i);
 
array_init(a, n);
array_init(b, n);
 
// 2. Execute mult in CPU (valid programm)
cpu_mult_vectors(a, b, c_cpu, n);
 
// 3. Execute mult in GPU and mesuare execution time
float execution_time = gpu_mult_vectors(a, b, c, n);
execution_times[i] = execution_time;
 
// 4. Check mult results
const string check_result = equal(c_cpu, c_gpu, N * N) ?
"Results are equal :)" :
"Results are not equal :(";
printf("%s\n", check_result);
 
free(a);
free(b);
free(c_cpu);
free(c_gpu);
}
 
for (int i = 0; i < LIMIT; ++i) {
int n = (int)pow(2.0, (double)i);
 
printf("Execution time for N = %d: %.5f\n", n, execution_times[i]);
}
 
return 0;
}

ЗДЕСЬ ДОЛЖЕН БЫТЬ ВЫВОД ПРОГРАММЫ! + ГРАФИК

Задание 3. Написать программу на Cи с использованием библиотеки Thrust [3] из


CUDA toolkit, выполняющая задачу из задания 2. Сравнить результаты. Результаты
занести в отчёт в графическом виде.

#include "cuda.h"
#include "cuda_runtime.h"
#include "cuda_runtime.h"
#include "device_launch_parameters.h"
 
#include <time.h>
#include <stdio.h>
 
#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
 
#define N 10
 
float mult_with_thrust(int N) {
thrust::device_vector<int> a(N);
thrust::device_vector<int> b(N);
thrust::device_vector<int> c(N);
Серебряков И.А. Отчет ПИН-12М
 
srand(time(NULL));
for (int i = 0; i < N; ++i)
{
a[i] = rand() % 10;
b[i] = rand() % 10;
}
 
cudaEvent_t start, stop;
cudaEventCreate(&start);
cudaEventCreate(&stop);
 
cudaEventRecord(start, 0);
thrust::transform(X.begin(), X.end(),
Y.begin(),
Z.begin(),
thrust::multiplies<int>());
cudaEventRecord(stop, 0);
 
cudaEventSynchronize(stop);
 
float execution_time;
cudaEventElapsedTime(&execution_time, start, stop);
 
cudaEventDestroy(start);
cudaEventDestroy(stop);
 
return execution_time;
}
 
int main()
{
float execution_times[LIMIT];
 
for (int i = 0; i < LIMIT; ++i) {
int n = (int)pow(2.0, (double)i);
 
float execution_time = mult_with_thrust(n);
execution_times[i] = execution_time;
}
 
for (int i = 0; i < LIMIT; ++i) {
int n = (int)pow(2.0, (double)i);
 
printf("Execution time with thrust for N = %d: %.5f\n", n,
execution_times[i]);
}
 
return 0;
}

ЗДЕСЬ ДОЛЖЕН БЫТЬ ВЫВОД ПРОГРАММЫ! + ГРАФИК

Вам также может понравиться