Программирование графических процессоров

Автор работы: Пользователь скрыл имя, 05 Марта 2015 в 17:12, курсовая работа

Описание работы

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

Содержание работы

Введение

Постановка задачи

Реализация

Результат

Сравнение производительности приложения на CPU и GPU

Выводы

Список литературы

Файлы: 1 файл

CUDA Course.doc

— 158.50 Кб (Скачать файл)

Московский Авиационный Институт

(Национальный Исследовательский  Университет)

 

 

 

 

 

 

 

 

 

Курсовая работа

 

Программирование графических процессоров

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Выполнил студент

 

 

 

Проверил

 

 

 

 

 

 

 

Москва 2014

 

 

СОДЕРЖАНИЕ

 

 

  1. Введение

 

  1. Постановка задачи

 

  1. Реализация

 

  1. Результат

 

  1. Сравнение производительности приложения на CPU и GPU

 

  1. Выводы

 

  1. Список литературы

 

 

  1. Введение

 

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

Таким образом, столкнувшись с очевидной проблемой повышения быстродействия, производители начали предлагать процессоры с несколькими вычислительными ядрами вместо одного. Но и многоядерные процессоры, если все сводится к размещению большего числа классических простых ядер на одной подложке, нельзя воспринимать как решение всех проблем. Их чрезвычайно сложно программировать, и они могут быть эффективны только на приложениях, обладающих естественной многопоточностью. Кроме того, если все ядра подключены к общей шине, каждый процессор должен «видеть» целый и корректный образ памяти, что неизбежно ведет к необходимости для каждого процессора отслеживать обращения к памяти всех остальных процессоров для поддержания актуальности своих кешей. Подобная задача имеет квадратичную сложность от числа процессоров.

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

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

 

 

  1. Постановка задачи

 

Написать программу, которая должна выполнять вычисления для массива данных, и произвести оценку производительности работы программы при вычислениях на CPU и GPU.

Программа 1: инвертировать массив.

Программа 2: вычислить квадраты элементов массива.

Программа 3: вычислить функцию экспоненты.

Вычисление по каждой программе будет включать следующие последовательные этапы:

  • Определение массива
  • Выделение памяти на GPU
  • Копирование данных из памяти CPU в выделенную память GPU
  • Осуществление запуска ядра (вычисление функции на GPU)
  • Копирование результатов вычислений в память на CPU
  • Вычисление функции на CPU
  • Освобождение памяти, выделенной GPU
  • Вывод результатов работы программы на CPU и GPU

 

 

 

 

3. Реализация

 

Ниже для заданий представлены функции GPU

Инвертирование массива

__global__ void invArray(int* a, int* b, int count)

{

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

  if (id < count)

  {

    b[id] = a[count-1-id];

  }

}

 

Вычисление квадратов элементов массива

__global__ void multArray(float* a, float*b,  int count)

{

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

  if (id < count)

  {

    b[id] = a[id]*a[id];

  }

}

 

Вычисление функции экспоненты

__global__ void expArray(float* a, float*b,  int count)

{

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

  if (id < count)

  {

    b[id] = exp(a[id]);

  }

}

 

4. Результат

Программа инвертирования массива

#include "cuda_runtime.h"

#include "device_launch_parameters.h"

#include <iostream>

#include <helper_timer.h>

#include <fstream>

#include <string>

#include <stdio.h>

using namespace std;

 

__global__ void invArray(int* a, int* b, int count)

{

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

  if (id < count)

  {

    b[id] = a[count-1-id];

  }

}

 

void invarrayCPU(int* datainput, int* dataoutput, int count )

{

  for (int i = 0; i < count; i++)

  {

    dataoutput [i] = datainput [count-1-i];

  }

}

 

int main()

{

  int count = 1000;

  int* data = new int [count];

  int* res = new int[count];

  int* dataGPU;

  int* resGPU;

 

  float time_gpu = 0, time_cpu = 0;

  cudaEvent_t start, stop;

 

  cudaEventCreate(&start);

  cudaEventCreate(&stop);

 

  for(int i = 0; i < count; ++i)

  {

    data[i]=i;

  }

 

//GPU

  cudaMalloc((void**)&dataGPU, count*sizeof(int));

  cudaMalloc((void**)&resGPU, count*sizeof(int));

  cudaMemcpy(dataGPU, data, count*sizeof(int), cudaMemcpyHostToDevice);

 

  cudaEventRecord(start, 0);

 

  invArray<<<1024, 1024>>>(dataGPU, resGPU, count);

 

  cudaEventRecord(stop, 0);

  cudaEventSynchronize(stop);

  cudaEventElapsedTime(&time_gpu, start, stop);

 

  cudaMemcpy(res, resGPU, count*sizeof(float), cudaMemcpyDeviceToHost);

 

  cudaFree(dataGPU);

  cudaFree(resGPU);

 

  int* res1 = new int[count];

 

  StopWatchInterface *timer = NULL;

  sdkCreateTimer(&timer);

  sdkStartTimer(&timer);

 

  invarrayCPU(data, res1, count);

 

  sdkStopTimer(&timer);

 

  time_cpu=sdkGetTimerValue(&timer);

 

  std::cout<<"\n\ntime_cpu = "<<time_cpu<<"\ntime_gpu = "<<time_gpu<<'\n';

 

  cin.get();

  cudaDeviceReset();

  return 0;

}

 

Программа вычисления квадратов элементов массива

#include "cuda_runtime.h"

#include "device_launch_parameters.h"

#include <iostream>

#include <helper_timer.h>

#include <fstream>

#include <string>

#include <stdio.h>

 

using namespace std;

 

__global__ void multArray(float* a, float*b,  int count)

{

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

  if (id < count)

  {

    b[id] = a[id]*a[id];

  }

}

 

void multarrayCPU(float* datainput, float *dataoutput, int count )

{

  for (int i = 0; i < count; i++)

  {

   dataoutput [i] = datainput [i] * datainput[i];

  }

}

 

int main()

{

  int count = 10;

  float* data = new float [count];

  float* res = new float[count];

  float* dataGPU;

  float* resGPU;

 

  float time_gpu = 0, time_cpu = 0;

  cudaEvent_t start, stop;

  cudaEventCreate(&start);

  cudaEventCreate(&stop);

 

  for(int i = 0; i < count; i++)

  {

    data[i]=float(i)*0.01f;

  }

 

//GPU

  cudaMalloc((void**)&dataGPU, count*sizeof(float));

  cudaMalloc((void**)&resGPU, count*sizeof(float));

  cudaMemcpy(dataGPU, data, count*sizeof(float), cudaMemcpyHostToDevice);

  cudaEventRecord(start, 0);

 

  multArray<<<1024,1024>>>(dataGPU, resGPU, count);

 

  cudaEventRecord(stop, 0);

  cudaEventSynchronize(stop);

  cudaEventElapsedTime(&time_gpu, start, stop);

  cudaMemcpy(res, resGPU, count*sizeof(float), cudaMemcpyDeviceToHost);

  cudaFree(dataGPU); 

 

  float* res1 = new float[count];

 

  StopWatchInterface *timer = NULL;

  sdkCreateTimer(&timer);

  sdkStartTimer(&timer);

 

  multarrayCPU(data, res1, count);

  sdkStopTimer(&timer);

 

  time_cpu=sdkGetTimerValue(&timer);

 

  std::cout<<"\n\ntime_cpu = "<<time_cpu<<"\ntime_gpu = "<<time_gpu<<'\n';

 

  cin.get();

  cudaDeviceReset();

  return 0;

}

 

Программа вычисления функции экспоненты

#include "cuda_runtime.h"

#include "device_launch_parameters.h"

#include <iostream>

#include <helper_timer.h>

#include <fstream>

#include <string>

#include <stdio.h>

 

using namespace std;

 

__global__ void expArray(float* a, float*b,  int count)

{

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

  if (id < count)

  {

    b[id] = exp(a[id]);

  }

}

 

void exparrayCPU(float* datainput, float *dataoutput, int count )

{

  for (int i = 0; i < count; i++)

  {

    dataoutput [i] = exp(datainput[i]);

  }

}

 

int main()

{

  int count = 1000000;

  float* data = new float [count];

  float* res = new float[count];

  float* dataGPU;

  float* resGPU;

  float step = 0.01f;

 

  cudaDeviceProp devProp;

  cudaGetDeviceProperties(&devProp,0);

  size_t maxThreads = devProp.maxThreadsPerBlock;

 

  float time_gpu = 0, time_cpu = 0;

  cudaEvent_t start, stop;

 

  cudaEventCreate(&start);

  cudaEventCreate(&stop);

 

  for(int i = 0; i < count; i++)

  {

    data[i]=float(i)*step;

  }

 

//GPU

  cudaMalloc((void**)&dataGPU, count*sizeof(float));

  cudaMalloc((void**)&resGPU, count*sizeof(float));

  cudaMemcpy(dataGPU, data, count*sizeof(float), cudaMemcpyHostToDevice);

 

  cudaEventRecord(start, 0);

 

  expArray<<<1024,1024>>>(dataGPU, resGPU, count);

 

  cudaEventRecord(stop, 0);

  cudaEventSynchronize(stop);

  cudaEventElapsedTime(&time_gpu, start, stop);

 

  cudaMemcpy(res, resGPU, count*sizeof(float), cudaMemcpyDeviceToHost);

 

  cudaFree(dataGPU); 

 

  float* res1 = new float[count];

 

  StopWatchInterface *timer = NULL;

  sdkCreateTimer(&timer);

  sdkStartTimer(&timer);

 

  exparrayCPU(data, res1, count);

 

  sdkStopTimer(&timer);

 

  time_cpu=sdkGetTimerValue(&timer);

 

  std::cout<<"\n\ntime_cpu = "<<time_cpu<<"\ntime_gpu = "<<time_gpu<<'\n';

 

  std::cout << maxThreads << '\n';

  cin.get();

  cudaDeviceReset();

  return 0;

}

 

5. Сравнение производительности приложения на CPU и GPU

 

Вычисление осуществлялось на системах

CPU: IntelCore(TM) i7-3770 CPU @ 3.40 GHz, 16 GB

GPU: NVIDIA Quadro 4000, GDDR5, 2 GB

CPU: Intel(R) Xeon® CPU E5-2650.@ 2.00GHz, 128 GB

GPU: Tesla M2075 Dual-Slot GDDR5, 6GB

 

Ниже результаты производительности (в миллисекундах, в зависимости от размера массива):

для программы инвертирования массива

Количество элементов

CPU Intel i7

GPU NVIDIA Quadro

CPU Intel Xeon

GPU Tesla

10

0,000301858

0,182176

0

0,056352

1 000

0,00241487

0,181824

0,06

0,056672

10 000

0,0220357

0,179552

0,047

0,056352

100 000

0,221866

0,191424

0,495

0,059424

1 000 000

2,22953

0,2984

6,404

0,120224


 

 

 

для программы вычисления квадратов элементов массива

Количество элементов

CPU Intel i7

GPU NVIDIA Quadro

CPU Intel Xeon

GPU Tesla

10

0,000301858

0,18112

0,001

0,09072

1 000

0,00271673

0,181152

0,006

0,092512

10 000

0,0250542

0,181856

0,053

0,088992

100 000

0,246316

0,191616

0,557

0,060256

1 000 000

2,34212

0,31034

6,753

0,125312


 

 

для программы вычисления функции экспоненты

Количество элементов

CPU Intel i7

GPU NVIDIA Quadro

CPU Intel Xeon

GPU Tesla

10

0,00241487

0,213664

0,3

0,056704

1 000

0,0187152

0,211488

0,388

0,087232

10 000

0,330535

0,214656

3,309

0,09712

100 000

26,9412

0,265152

5,868

0,063424

1 000 000

59,4936

0,789152

33,24

0,139232


 

 

 

6. Выводы

 

Технология CUDA — это программно–аппаратная архитектура, которая позволяет производить вычисления с использованием графических процессоров NVIDIA. Данная технология основана на расширении языка С и дает возможность организовывать доступ к набору инструкций графического ускорителя и управлять его памятью, а также разработать на нем сложные параллельные вычисления.

Информация о работе Программирование графических процессоров