Skip to content

Instantly share code, notes, and snippets.

@blrB
Last active April 25, 2017 18:51
Show Gist options
  • Save blrB/bcaf4bc80feae6c75d114c718b011545 to your computer and use it in GitHub Desktop.
Save blrB/bcaf4bc80feae6c75d114c718b011545 to your computer and use it in GitHub Desktop.
open cl
// 25. Посчитать массив общих элементов двух отсортированных массивов (13)
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <CL/opencl.h>
#define PROCESS_ERROR(msg,stateCondition) if (stateCondition != CL_SUCCESS) { \
printf(msg, stateCondition); \
return stateCondition; \
}
using namespace std;
void serialRelease(int pA[], int pB[], const int countA, const int countB)
{
int *pC = new int[countB];
clock_t startP = clock();
for (int i = 0; i < countB; i++){
pC[i] = -1;
for (int j = 0; j < countA; j++){
if (pB[i] == pA[j]) pC[i] = pB[i];
}
}
cout << " - > " << clock() - startP << endl;
for (int i = 0; i < countB; i++){
cout << pC[i] << " ";
}
cout << endl << endl;
}
void init(int pV[], const int cnDimention){
int i;
for (i = 0; i < cnDimention; i++){
cout << "Введите элемент " << i << " ";
cin >> pV[i];
}
cout << endl;
}
void initT(int pV[], const int cnDimention){
int i;
for (i = 0; i < cnDimention; i++){
pV[i] = i;
}
cout << endl;
}
void dump(int pV[], const int cnDimention) {
for (int i = 0; i < cnDimention; i++) {
cout << pV[i]<< " ";
}
cout << endl;
}
int main() {
const char * sProgramSource[] = {"\
__kernel void intersection (__global const int * a, __global const int * b, __global int * c, __global int * countA)\
{\
int nIndex = get_global_id(0);\
c[nIndex] = -1;\
for (int i = 0 ; i < *countA ;i++)\
{\
if (b[nIndex] == a[i]) c[nIndex] = b[nIndex];\
}\
}"
};
int countA;
int countB;
cout << "Введите количество элементов в первом массиве : ";
cin >> countA;
int *pA = new int[countA];
init(pA,countA);
cout << "Введите количество элементов во втором массиве : ";
cin >> countB;
int *pB = new int[countB];
init(pB,countB);
cout << "Массив общих элементов :" << endl;
cout << "Последовательный алгоритм :" << endl;
serialRelease(pA, pB, countA, countB);
// Выбор платформы ---------------------------------------------------------------------------------------------------
cl_int stateCondition;
cl_uint numberOfPlatforms;
cl_platform_id platform;
stateCondition = clGetPlatformIDs(0, NULL, &numberOfPlatforms); // нахождение количества платформ
if (stateCondition == CL_SUCCESS) { // проверка на успешность подсчета кол-ва платформ
cl_platform_id* platforms = new cl_platform_id[numberOfPlatforms]; // выделяется память для объектов платформы
stateCondition = clGetPlatformIDs(numberOfPlatforms, platforms, NULL); // получения объектов платформы
if (stateCondition == CL_SUCCESS) { // проверка на успешность выбора платформы
platform = platforms[0]; // взятие (первой попавшейся) платформы из массива
}
PROCESS_ERROR("Platform detection faults. Error Code: %d.", stateCondition);
}
PROCESS_ERROR("Platform detection faults. Error Code: %d.", stateCondition);
// Выбор устройств ---------------------------------------------------------------------------------------------------
cl_device_id device_id;
cl_uint numberOfDevices;
stateCondition = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 0, NULL, &numberOfDevices); // определяет число устройств
PROCESS_ERROR("Device detection faults. Error Code: %d.", stateCondition);
stateCondition = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, numberOfDevices, &device_id, NULL); // обнаруживает объекты устройств
PROCESS_ERROR("Device detection faults. Error Code: %d.", stateCondition);
// Контекст ----------------------------------------------------------------------------------------------------------
cl_context context;
context = clCreateContext(NULL, numberOfDevices, &device_id, NULL, NULL, &stateCondition); // создаёт контекст
PROCESS_ERROR("Context creation faults. Error Code: %d.", stateCondition);
// Очереди команд ----------------------------------------------------------------------------------------------------
cl_command_queue commandQueue;
commandQueue = clCreateCommandQueue(context, device_id, 0, 0); // очереди команд связывают контекст с устройством
// Создание буферов --------------------------------------------------------------------------------------------------
int *pC = new int[countB];
cl_mem deviceMemoryA;
cl_mem deviceMemoryB;
cl_mem deviceMemoryC;
cl_mem deviceCountA;
deviceMemoryA = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, countA * sizeof(cl_int), pA, NULL);
deviceMemoryB = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, countB * sizeof(cl_int), pB, NULL);
deviceMemoryC = clCreateBuffer(context, CL_MEM_WRITE_ONLY, countB * sizeof(cl_int), NULL, NULL);
deviceCountA = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(cl_int), &countA, NULL);
// Создание программ -------------------------------------------------------------------------------------------------
cl_program hProgram;
hProgram = clCreateProgramWithSource(context, 1, sProgramSource, 0, 0); // создаёт программный объект из строк исходного кода
stateCondition = clBuildProgram(hProgram, 0, 0, 0, 0, 0); // компилирует исполняемый файл для каждого устройства
PROCESS_ERROR("Program building faults. Error Code: %d.", stateCondition);
// Создания ядра -----------------------------------------------------------------------------------------------------
cl_kernel kernel;
kernel = clCreateKernel(hProgram, "intersection", 0); // создаёт ядро из заданной программы
// Установка аргументов ядра -----------------------------------------------------------------------------------------
stateCondition = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&deviceMemoryA);
PROCESS_ERROR("First argument failure. Error Code: %d.",stateCondition);
stateCondition = clSetKernelArg(kernel, 1, sizeof(cl_mem), (void *)&deviceMemoryB);
PROCESS_ERROR("Second argument failure. Error Code: %d.",stateCondition);
stateCondition = clSetKernelArg(kernel, 2, sizeof(cl_mem), (void *)&deviceMemoryC);
PROCESS_ERROR("Third argument failure. Error Code: %d.",stateCondition);
stateCondition = clSetKernelArg(kernel, 3, sizeof(cl_mem), (void *)&deviceCountA);
PROCESS_ERROR("Fourth argument failure. Error Code: %d.",stateCondition);
size_t co = countB;
clock_t startP = clock();
// Говорим устройству, связанному с очередью команд, начать исполнение указанного ядра
stateCondition = clEnqueueNDRangeKernel(commandQueue, kernel, 1, NULL, &co, NULL, 0, 0, 0);
PROCESS_ERROR("clEnqueueNDRangeKernel failure. Error Code: %d.", stateCondition);
cout << " - > " << clock() - startP << endl;
// Копирование данных с устройства на хост
stateCondition = clEnqueueReadBuffer(commandQueue, deviceMemoryC, CL_TRUE, 0, countB * sizeof(cl_int), pC, 0, 0, 0);
PROCESS_ERROR("clEnqueueReadBuffer failure. Error Code: %d.", stateCondition);
cout << "Параллельный алгоритм :" << endl;
dump(pC, countB);
// Очистка памяти ----------------------------------------------------------------------------------------------------
delete[] pA;
delete[] pB;
delete[] pC;
stateCondition = clReleaseMemObject(deviceMemoryA);
PROCESS_ERROR("Release failure. Error Code: %d.", stateCondition);
stateCondition = clReleaseMemObject(deviceMemoryB);
PROCESS_ERROR("Release failure. Error Code: %d.", stateCondition);
stateCondition = clReleaseMemObject(deviceMemoryC);
PROCESS_ERROR("Release failure. Error Code: %d.", stateCondition);
stateCondition = clReleaseKernel(kernel);
PROCESS_ERROR("Release failure. Error Code: %d.", stateCondition);
stateCondition = clReleaseProgram(hProgram);
PROCESS_ERROR("Release failure. Error Code: %d.", stateCondition);
stateCondition = clReleaseCommandQueue(commandQueue);
PROCESS_ERROR("Release failure. Error Code: %d.", stateCondition);
stateCondition = clReleaseContext(context);
PROCESS_ERROR("Release failure. Error Code: %d.", stateCondition);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment