Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
курсак.doc
Скачиваний:
3
Добавлен:
07.12.2018
Размер:
787.97 Кб
Скачать

4. Тестувальний розділ

4.1 Тестування програми

Рис.4.1. Результати операцій над векторами і матрицями.

На Рис.4.1. показано, що операції виконував графічний процесор, перший вивід це додавання матриці, другий віднімання, третій най триваліший це добуток матриць. Нижче наведені такі ж дії але з векторами.

5. Висновок

Завдання курсової роботи було виконано, але програма була написана на графічному процесорі Nvidia gts 450 gddr3, тому що в результаті роботи 4850 не витримала навантаження. В ході роботи було реалізовано наступні алгоритми:

1. Додавання векторів(двох одномірних масивів) на мові openCL C.

2. Віднімання векторів(двох одномірних масивів) на мові openCL C.

3. Множення вектора на вектор(двох одномірних масивів)в результаті одне число на мові openCL C.

4. Множення вектора на скаляр(одного одномірного вектору на число) на мові openCL C.

5. Додавання матриць(двовимірних масивів) на мові openCL C.

6. Віднімання матриць(двовимірних масивів) на мові openCL C.

7. Множення матриць(двовимірних масивів) на мові openCL C.

В результаті виконаної роботи можна зробити висновок, що за допомогою GPGPU процесорів з підтримкою OpenCL, обробка досить великих об’ємів математичних даних є набагато швидшою ніж на CPU процесорі. Такої швидкості нам вдалося досягти завдяки паралельній обробці даних, що використовується на GPU процесорі.

6. Список літератури

1. http://www.khronos.org/opencl.html

2. http://www.cmsoft.com.br.html

3. Т. Бадд Об'єктно - орієнтоване програмування в дії - СПб.: Пітер 1997. – 464с.

4. http://opengl.gamedev.ru.html

5. М. Ласло Обчіслювальна Геометрія та комп'ютерна Графіка на С - М.: БІНОМ, 1997. – 304с

6. http://www.nvidia.ru/object/cuda_opencl_new_ru.html

7. Стівен Прата Язик програмування С. Лекції і вправи - Київ: DiaSoft, 2000.

8. Джефф Элджер. C++: Библиотека программиста. – Пітер, 2000.

9. Т.А. Павловська Програмування на мові високого рівня C / С - Москва, Санкт - Петербург, Мінськ, Київ 2002. – 450 ст.

10. Г. Шилт Теорія і практика С – СПб.: BHV, 1996. – 416 с.

11. (http://www.nvidia.com/object/product-geforce-gts-450-us.html

12. http://opencl.ru/design.html

7. Додаток

#include <oclUtils.h>

#include <iostream>

#include <stdio.h>

#include <string.h>

#include <math.h>

#include <windows.h>

#include <conio.h>

using namespace std;

//----------------------------------------------------------------------

typedef struct

{

unsigned W; unsigned H; cl_mem E;

} matrix_t ;

int main ( int argc , char ** argv )

{

const unsigned L = 1234 , M = 567 , N = 8910;

const unsigned BLOCK_SIZE = 16;

cl_context cntx ;

cl_command_queue cq;

cl_device_id * ds; // пристрій

cl_program p;

cl_kernel k;

char * program_source = "..."; // ядра

size_t global_work_size [2] = {L, N};

size_t local_work_size [2] = { BLOCK_SIZE , BLOCK_SIZE };

size_t cb;

float mem_A [L][M], mem_B [M][N], mem_R [L][N];

matrix_t A, B, R;

int i = -1;

// ...

cntx = clCreateContextFromType (NULL , CL_DEVICE_TYPE_GPU , NULL , NULL , NULL );

clGetContextInfo (cntx , CL_CONTEXT_DEVICES , 0, NULL , &cb );

ds = malloc (cb );

clGetContextInfo (cntx , CL_CONTEXT_DEVICES , cb , ds , NULL );

cq = clCreateCommandQueue (cntx , ds [0] , 0, NULL );

free (ds );

p = clCreateProgramWithSource (cntx , 1, & program_source , NULL , NULL );

clBuildProgram (p, 0, NULL , NULL , NULL , NULL );

k = clCreateKernel (p, " matrix_multiply ", NULL );

A.H = L; A.W = M;

A.E = clCreateBuffer (cntx , CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR ,

A.H * A.W * sizeof ( cl_float ), mem_A , NULL );

B.H = M; B.W = N;

B.E = clCreateBuffer (cntx , CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR ,

B.H * B.W * sizeof ( cl_float ), mem_B , NULL );

R.H = L; R.W = N;

R.E = clCreateBuffer (cntx , CL_MEM_READ_WRITE ,

R.H * R.W * sizeof ( cl_float ), NULL , NULL );

clSetKernelArg (k, i += 1, sizeof ( unsigned ), &A.H);

clSetKernelArg (k, i += 1, sizeof ( unsigned ), &A.W);

clSetKernelArg (k, i += 1, sizeof ( cl_mem ), &A.E);

clSetKernelArg (k, i += 1, sizeof ( unsigned ), &B.H);

clSetKernelArg (k, i += 1, sizeof ( unsigned ), &B.W);

clSetKernelArg (k, i += 1, sizeof ( cl_mem ), &B.E);

clSetKernelArg (k, i += 1, sizeof ( unsigned ), &R.H);

clSetKernelArg (k, i += 1, sizeof ( unsigned ), &R.W);

clSetKernelArg (k, i += 1, sizeof ( cl_mem ), &R.E);

clEnqueueNDRangeKernel (cq , k, 2, NULL ,

global_work_size , local_work_size , 0, NULL , NULL );

clEnqueueReadBuffer (cq , R.E, CL_TRUE , 0,

R.W * R.H * sizeof ( cl_float ), mem_R , 0, NULL , NULL );

clReleaseMemObject (A.E);

clReleaseMemObject (B.E);

clReleaseMemObject (R.E);

clReleaseKernel (k);

clReleaseProgram (p);

clReleaseCommandQueue (cq );

clReleaseContext ( cntx );

// ...

return 0;

}

class VectorGPU {

private:

// OpenCL Vars

cl_context cxGPUContext; // OpenCL контекст

cl_command_queue cqCommandQueue;// OpenCL команди черги

cl_platform_id cpPlatform; // OpenCL платформа

cl_device_id cdDevice; // OpenCL пристрій

cl_program cpProgram; // OpenCL програма

cl_kernel ckKernel; // OpenCL ядро

cl_mem cmDevSrcA; // OpenCL пристрій вихідний буфер A

cl_mem cmDevSrcB; // OpenCL пристрій вихідний буфер B

cl_mem cmDevDst; //OpenCL буфера пристрою призначення

size_t szGlobalWorkSize;

size_t szLocalWorkSize;

size_t szParmDataBytes; // Байт розмір інформаційним контекстом

size_t szKernelLength; // Байт розмір коду ядра

cl_int ciErr1, ciErr2; // Код помилки var

char* cPathAndName;

char* cSourceCL; // Буфер для зберігання джерелом для складання

public:

int n;

void *srcA, *srcB, *dst; // Хост буферів для OpenCL тест

VectorGPU();

VectorGPU(int size);

~VectorGPU();

int ClInit();

int CLAllocMem (int iNumElements);

int ClCreateProg(char *funcname, int iNumElements);

int ClWriteDataGPU();

int ClCompute();

int ClReadDataGPU();

unsigned int VAdd();

unsigned int VSub();

unsigned int MulSc(float scalar);

};

VectorGPU::VectorGPU()

{

}

VectorGPU::VectorGPU(int size)

{

if (ClInit()==1)

{

if (CLAllocMem(size)==1)

{

}

}

}

VectorGPU::~VectorGPU()

{

}

unsigned int VectorGPU::VAdd()

{

unsigned int t1,t2;

if (ClCreateProg("VectorAdd",n)==1)

{

t1=GetTickCount();

if (ClWriteDataGPU()==1)

{

if (ClCompute()==1)

{

t2=GetTickCount();

}

if (ClReadDataGPU()==1)

{

}

}

}

return ((int)(t2-t1));

}

unsigned int VectorGPU::VSub()

{

unsigned int t1,t2;

if (ClCreateProg("VectorSub",n)==1)

{

t1=GetTickCount();

if (ClWriteDataGPU()==1)

{

if (ClCompute()==1)

{

t2=GetTickCount();

}

if (ClReadDataGPU()==1)

{

}

}

}

return ((int)(t2-t1));

}

unsigned int VectorGPU::MulSc(float scalar)

{

unsigned int t1,t2;

float *b=(float*) srcB;

b[0]=scalar;

if (ClCreateProg("VectorMulSc",n)==1)

{

t1=GetTickCount();

if (ClWriteDataGPU()==1)

{

if (ClCompute()==1)

{

t2=GetTickCount();

}

if (ClReadDataGPU()==1)

{

}

}

}

return ((int)(t2-t1));

}

int VectorGPU::ClInit()

{

//Отримати OpenCL платформи

ciErr1 = clGetPlatformIDs(1, &cpPlatform, NULL);

if (ciErr1 != CL_SUCCESS)

{

return 0;

}

//Отримати пристроїв

ciErr1 = clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, 1, &cdDevice, NULL);

if (ciErr1 != CL_SUCCESS)

{

return 0;

}

//Створення контексту

cxGPUContext = clCreateContext(0, 1, &cdDevice, NULL, NULL, &ciErr1);

if (ciErr1 != CL_SUCCESS)

{

return 0;

}

// Створити команду черги

cqCommandQueue = clCreateCommandQueue(cxGPUContext, cdDevice, 0, &ciErr1);

if (ciErr1 != CL_SUCCESS)

{

return 0;

}

return 1;

}

//----------------

int VectorGPU::CLAllocMem (int iNumElements)

{

szLocalWorkSize = 256;

szGlobalWorkSize = shrRoundUp((int)szLocalWorkSize, iNumElements); // округлюється до найближчого числа, кратного LocalWorkSize

// Виділяють і ініціалізації хост масивів

srcA = (void *)malloc(sizeof(cl_float) * szGlobalWorkSize);

srcB = (void *)malloc(sizeof(cl_float) * szGlobalWorkSize);

dst = (void *)malloc(sizeof(cl_float) * szGlobalWorkSize);

Golden = (void *)malloc(sizeof(cl_float) * iNumElements);

shrFillArray((float*)srcA, iNumElements);

shrFillArray((float*)srcB, iNumElements);

// Виділяють OpenCL буферної пам'яті об'єктів для джерела і результат на пристрій GMEM

cmDevSrcA = clCreateBuffer(cxGPUContext, CL_MEM_READ_ONLY, sizeof(cl_float) * szGlobalWorkSize, NULL, &ciErr1);

cmDevSrcB = clCreateBuffer(cxGPUContext, CL_MEM_READ_ONLY, sizeof(cl_float) * szGlobalWorkSize, NULL, &ciErr2);

ciErr1 |= ciErr2;

cmDevDst = clCreateBuffer(cxGPUContext, CL_MEM_WRITE_ONLY, sizeof(cl_float) * szGlobalWorkSize, NULL, &ciErr2);

ciErr1 |= ciErr2;

if (ciErr1 != CL_SUCCESS)

{

return 0;

}

return 1;

}

//----------------

int VectorGPU::ClCreateProg(char *funcname, int iNumElements)

{

// Створення програми

cSourceCL = oclLoadProgSource("VectorAdd.cl", "", &szKernelLength);

cpProgram = clCreateProgramWithSource(cxGPUContext, 1, (const char **)&cSourceCL, &szKernelLength, &ciErr1);

if (ciErr1 != CL_SUCCESS)

{

return 0;

}

ciErr1 = clBuildProgram(cpProgram, 0, NULL, NULL, NULL, NULL);

if (ciErr1 != CL_SUCCESS)

{

return 0;

}

// Створення ядра

ckKernel = clCreateKernel(cpProgram, funcname, &ciErr1);

if (ciErr1 != CL_SUCCESS)

{

return 0;

}

// Встановити Аргумент значення

ciErr1 = clSetKernelArg(ckKernel, 0, sizeof(cl_mem), (void*)&cmDevSrcA);

ciErr1 |= clSetKernelArg(ckKernel, 1, sizeof(cl_mem), (void*)&cmDevSrcB);

ciErr1 |= clSetKernelArg(ckKernel, 2, sizeof(cl_mem), (void*)&cmDevDst);

ciErr1 |= clSetKernelArg(ckKernel, 3, sizeof(cl_int), (void*)&iNumElements);

if (ciErr1 != CL_SUCCESS)

{

return 0;

}

return 1;

}

//---------------

int VectorGPU::ClWriteDataGPU()

{

//Asynchronous запису даних на GPU пристрої

ciErr1 = clEnqueueWriteBuffer(cqCommandQueue, cmDevSrcA, CL_FALSE, 0, sizeof(cl_float) * szGlobalWorkSize, srcA, 0, NULL, NULL);

ciErr1 |= clEnqueueWriteBuffer(cqCommandQueue, cmDevSrcB, CL_FALSE, 0, sizeof(cl_float) * szGlobalWorkSize, srcB, 0, NULL, NULL);

if (ciErr1 != CL_SUCCESS)

{

return 0;

}

return 1;

}

//----------------

int VectorGPU::ClCompute()

{

// Початок kernel

ciErr1 = clEnqueueNDRangeKernel(cqCommandQueue, ckKernel, 1, NULL, &szGlobalWorkSize, &szLocalWorkSize, 0, NULL, NULL);

if (ciErr1 != CL_SUCCESS)

{

return 0;

}

return 1;

}

//----------------

int VectorGPU::ClReadDataGPU()

{

// Synchronous / блокування читання результатів, а також перевірити накопичені помилки

ciErr1 = clEnqueueReadBuffer(cqCommandQueue, cmDevDst, CL_TRUE, 0, sizeof(cl_float) * szGlobalWorkSize, dst, 0, NULL, NULL);

if (ciErr1 != CL_SUCCESS)

{

return 0;

}

return 1;

}

//----------------

void FillMasData(float *x,int n)

{

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

x[i]=i;

return;

}

//----------------

int main(int argc, char **argv)

{

int n;

unsigned int t1,t2;

n=20000000;

//---------------

VectorGPU v=VectorGPU(n);

//----------------

FillMasData((float*)v.srcA,n);

FillMasData((float*)v.srcB,n);

//----------------

printf("GPU:\nAdd - %d msec\nSub - %d msec\nMulSc - %d msec\n",v.VAdd(),v.VSub(),v.MulSc(10000.89));

//----------------

getch();

return 0;

}

39

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]