Skip to content

Instantly share code, notes, and snippets.

@PontiacGTX
Last active June 23, 2019 19:44
Show Gist options
  • Save PontiacGTX/745b4942acab0c7213dee1fede6a8e35 to your computer and use it in GitHub Desktop.
Save PontiacGTX/745b4942acab0c7213dee1fede6a8e35 to your computer and use it in GitHub Desktop.
#define CL_USE_DEPRECATED_OPENCL_2_0_APIS
#include <iostream>
#include "ApplicationCL.h"
unsigned long int sizeArr = 256;
std::vector<cl_uchar> vChars(sizeArr);
std::vector<char> fileBytes;
std::vector<cl_uchar*> compressedBytes;
std::vector<cl_ulong> indexByte;
float limit;
unsigned long filebyteCount = 0;
cl_ulong compressedByteCount = 0;
#define NELEMS(x) (sizeof(x) / sizeof((x)[0]))
void GetPlatformInfo(const cl_uint& numPlatforms, cl_platform_id* platforms, std::string& details)
{
std::string attributeNames[] = { "Name", "Vendor", "Version", "Profile", "Extensions" };
const cl_platform_info attributeTypes[5] = { CL_PLATFORM_NAME,CL_PLATFORM_VENDOR,CL_PLATFORM_VERSION,CL_PLATFORM_PROFILE,
CL_PLATFORM_EXTENSIONS };
size_t infoSize;
int numAttributes = NELEMS(attributeTypes);
char* info;
std::string infoContent = "";
for (size_t i = 0; i < numPlatforms; i++)
{
for (size_t j = 0; j < numAttributes; j++)
{
clGetPlatformInfo(platforms[i], attributeTypes[j], 0, NULL, &infoSize);
info = new char[infoSize];
// get platform attribute value
clGetPlatformInfo(platforms[i], attributeTypes[j], infoSize, info, NULL);
infoContent.assign(info, info + strlen(info));
details += attributeNames[j] + " " + infoContent + '\n';
}
std::cout << details << std::endl;
}
}
void ReadBytes(std::vector<char>* bytes,const std::string& pathDecode,unsigned long& fileSize)
{
std::ifstream* file = new std::ifstream(pathDecode, std::ios::binary);
file->unsetf(std::ios::skipws);
file->seekg(0, std::ios::end);
fileSize = file->tellg();
file->seekg(0, std::ios::beg);
bytes->reserve(fileSize);
bytes->insert(bytes->begin(), std::istream_iterator<char>(*file), std::istream_iterator<char>());
delete file;
}
int Program::ParseFile(std::string& content, const std::string& filename)
{
std::ifstream* openFile = new std::ifstream(filename, std::ios::binary);
size_t fileSize = 0;
if (openFile->is_open())
{
openFile->seekg(0, std::fstream::end);
fileSize = openFile->tellg();
openFile->seekg(0, std::fstream::beg);
}
content.reserve(fileSize);
content.insert(content.begin(), std::istreambuf_iterator<char>(*openFile), std::istreambuf_iterator<char>());
delete openFile;
if (content.size() <= 1)
return 1;
return 0;
}
void GetMessageError(cl_int status, cl_program program, cl_device_id device)
{
size_t length = 0;
status = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &length);
size_t total = length * sizeof(char);
char* buffer = new char[total];
status = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, length, buffer, NULL);
std::string message(buffer, total);
if (!message.empty())
std::cout << message << std::endl;
else
std::cout << "Error: " << status << std::endl;
delete[] buffer;
}
void CheckErrorCode(cl_int status, cl_program& program, cl_device_id& devices, const std::string& message)
{
if (status != 0)
{
std::cout << message << std::endl;
GetMessageError(status, program, devices);
}
}
void Program::GetPlatform(cl_platform_id& platform,cl_uint& numberPlatforms,cl_platform_id* platforms)
{
cl_int status = clGetPlatformIDs(0, NULL, &numberPlatforms);
if (status == 1)
{
std::cout << "Failed Platforms not found" << std::endl;
}
if (numberPlatforms > 0)
{
platforms = new cl_platform_id[numberPlatforms * sizeof(cl_platform_id)];
status = clGetPlatformIDs(numberPlatforms, &platforms[0], &numberPlatforms);
platform = platforms[0];
if (platform == nullptr)
{
std::cout << "Error Obtaining platformId" << std::endl;
}
//std::string temp = "";
//GetPlatformInfo(numberPlatforms,platforms,1,temp);
delete[] platforms;
}
}
void Program::GetDeviceIDs(cl_device_id*& devices, const cl_platform_id& platform)
{
cl_uint deviceCount = 0;
cl_int status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 0, NULL, &deviceCount);
if (deviceCount == 0)
{
std::cout << "No GPU device available." << std::endl;
std::cout << "Choose CPU as default device." << std::endl;
status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_CPU, 0, NULL, &deviceCount);
devices = new cl_device_id[deviceCount * sizeof(cl_device_id)];
status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_CPU, deviceCount, devices, NULL);
}
else
{
devices = new cl_device_id[(deviceCount * sizeof(cl_device_id))];
status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, deviceCount, devices, NULL);
}
}
void Program::GetContext(cl_context& context, const cl_platform_id& platform, cl_device_id*& devices)
{
cl_context_properties contextProperties[] = { CL_CONTEXT_PLATFORM,reinterpret_cast<cl_context_properties>(platform), 0 };
cl_int status = 0;
context = clCreateContext(contextProperties, 1, devices, NULL, NULL, &status);
if (status != 0)
{
std::cout << "Error creating context for device" << std::endl;
}
}
void Program::GetCommandQueue(cl_command_queue& commandQueue, const cl_context& context, cl_device_id*& devices)
{
commandQueue = clCreateCommandQueue(context, devices[0], 0, NULL);
}
template<size_t size>
void Program::CreateProgramWithSource(const char*& filePath, std::string& SourceStr, size_t(&sourceSize)[size], cl_context& context, cl_program& program)
{
bool parsedFile = ParseFile(SourceStr, filePath);
if (parsedFile == 0)
{
std::cout << "File Parsed" << std::endl;
}
const char* Source = SourceStr.c_str();
sourceSize[0] = { strlen(Source) };
program = clCreateProgramWithSource(context, 1, &Source, sourceSize, NULL);
}
void Program::BuildProgram(cl_program& program, const cl_uint& deviceCount, cl_device_id*& devices,const char* oclVersion)
{
status = clBuildProgram(program, 1, devices, oclVersion, NULL, NULL);
if (status != 0)
{
std::cout << "Program couldnt be built" << std::endl;
GetMessageError(status, program, devices[0]);
}
}
int main()
{
Program p1;
cl_uint numPlatf = 0;
p1.GetPlatform(p1.platform,numPlatf,p1.platforms);
p1.GetDeviceIDs(p1.devices,p1.platform);
p1.GetContext(p1.context,p1.platform,p1.devices);
p1.GetCommandQueue(p1.commandQueue,p1.context,p1.devices);
p1.CreateProgramWithSource(p1.filePath,p1.strSource,p1.sourceSize,p1.context,p1.program);
p1.BuildProgram(p1.program,1,p1.devices,"-cl-std=CL2.0");
std::string s;
GetPlatformInfo(numPlatf, &p1.platform,s);
limit=256.0f;
vChars.resize(sizeArr);
cl_mem outputBuffer = clCreateBuffer(p1.context, CL_MEM_WRITE_ONLY, sizeArr/*+ 1)*/*sizeof(cl_uchar), NULL, &p1.status);
/*cl_mem cbuff = clCreateBuffer(p1.context, CL_MEM_WRITE_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(float), (void*)& c, NULL);*/
//create kernel
cl_kernel kernelAdd = clCreateKernel(p1.program, "Add", &p1.status);
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed Creating Kernel");
//create kernel argument
p1.status = clSetKernelArg(kernelAdd, 0, sizeof(cl_float), (void*)& limit);
CheckErrorCode(p1.status,p1.program,p1.devices[0], "Failed adding Argument 0");
p1.status = clSetKernelArg(kernelAdd, 1, sizeof(cl_mem), (void*)& outputBuffer);
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed adding Argument 1");
//array of work_dim unsigned values that describe the number of global work - items in work_dim dimensions
//that will execute the kernel function.The total number of global work - items is computed as global_work_size[0] * … * global_work_size[work_dim – 1].
/****************************************/
size_t globalWorkSize[1] = { sizeArr };
//enqueues a command to execute a kernel on a device
/****************************************/
size_t localWorkSize = 64;
p1.status = clEnqueueNDRangeKernel(p1.commandQueue, kernelAdd, 1, NULL, globalWorkSize,&localWorkSize , 0, NULL, NULL);
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed EnqueueNDRangeKernel 0");
//enqueue the buffer for read
p1.status = clEnqueueReadBuffer(p1.commandQueue, outputBuffer, CL_TRUE, 0, sizeof(cl_uchar)*sizeArr, vChars.data(), 0, NULL, NULL); //call request that the device send data to the host,(sends the output result)
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed clEnqueueReadBuffer 0");
///
///output[sizeInput] = '\0'; //Add the terminal character to the end of output.
///
for (int i = 0; i < vChars.size(); i++)
{
std::cout << vChars[i] << std::endl;
}
const char* path = "C:\\Users\\PontiacGTX\\Desktop\\opencl.txt";
ReadBytes(&fileBytes, path, filebyteCount);
indexByte.resize(filebyteCount);
compressedBytes.resize(filebyteCount);
compressedByteCount = globalWorkSize[0] = filebyteCount;
/*ReadBytes(&fileBytes,path, filebyteCount);
fileBytes.shrink_to_fit();
filebyteCount = fileBytes.size();
indexByte.resize(filebyteCount);
compressedBytes.resize(filebyteCount);
globalWorkSize[0] = filebyteCount;*/
cl_kernel kernelCopyBytes = clCreateKernel(p1.program, "CopyBytes", &p1.status);
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed Creating kernel 1");
cl_mem fileBytesBuffer = clCreateBuffer(p1.context, CL_MEM_READ_ONLY| CL_MEM_USE_HOST_PTR, filebyteCount * sizeof(cl_uchar),fileBytes.data(),&p1.status);
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed Creating buffer 0");
/*cl_mem bufferSize = clCreateBuffer(p1.context, CL_MEM_READ_ONLY | CL_MEM_USE_HOST_PTR, sizeof(cl_ulong), &filebyteCount, &p1.status);
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed Creating buffer 1");*/
cl_mem compressedBytesbuffer = clCreateBuffer(p1.context, CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, filebyteCount * sizeof(cl_uchar),compressedBytes.data(), &p1.status);
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed Creating buffer 2");
int flags = CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER| CL_DEVICE_SVM_COARSE_GRAIN_BUFFER;
void* bufferCompressedBytes= clSVMAlloc(p1.context, CL_MEM_READ_WRITE | CL_MEM_SVM_FINE_GRAIN_BUFFER | CL_MEM_SVM_ATOMICS, filebyteCount * sizeof(cl_uchar),0);
cl_mem indexByteBuffer = clCreateBuffer(p1.context, CL_MEM_WRITE_ONLY | CL_MEM_USE_HOST_PTR, filebyteCount * sizeof(cl_ulong), indexByte.data(), &p1.status);
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed Creating buffer 3");
p1.status = clEnqueueWriteBuffer(p1.commandQueue, fileBytesBuffer, CL_TRUE, 0, filebyteCount * sizeof(cl_uchar), fileBytes.data(), 0, NULL, NULL);
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed EnqueueReadBuffer 1");
p1.status = clSetKernelArg(kernelCopyBytes,0,sizeof(fileBytesBuffer),(void*)&fileBytesBuffer);
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed Adding Argument 0");
p1.status = clSetKernelArg(kernelCopyBytes, 1, sizeof(cl_ulong), (void*)& compressedByteCount);
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed Adding Argument 1");
p1.status = clSetKernelArg(kernelCopyBytes, 2, sizeof(compressedBytesbuffer), &compressedBytesbuffer);//compressedBytesbuffer
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed Adding Argument 2");
p1.status = clSetKernelArg(kernelCopyBytes,3, sizeof(indexByteBuffer), (void*)& indexByteBuffer);
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed Adding Argument 3");
p1.status = clEnqueueNDRangeKernel(p1.commandQueue, kernelCopyBytes, 1, NULL, globalWorkSize, &localWorkSize, 0, NULL, NULL);
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed EnqueueNDRangeKernel 1");
//enqueue the buffer for read
p1.status = clEnqueueReadBuffer(p1.commandQueue, compressedBytesbuffer, CL_TRUE, 0, filebyteCount * sizeof(cl_uchar*),(void*) compressedBytes.data(), 0, NULL, NULL);
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed EnqueueReadBuffer 1");
p1.status = clEnqueueReadBuffer(p1.commandQueue, indexByteBuffer, CL_TRUE, 0, filebyteCount * sizeof(cl_ulong), (void*)indexByte.data(), 0, NULL, NULL);
CheckErrorCode(p1.status, p1.program, p1.devices[0], "Failed EnqueueReadBuffer 2");
if (compressedBytes[0] != (char)NULL)
{
std::cout << "File bytes passed to compressBytes array" << std::endl;
}
compressedBytes.shrink_to_fit();
auto total = compressedBytes.size();
for (auto i=0;i<total;i++)
{
std::cout << compressedBytes[i] << std::endl;
}
//Step 12: Clean the resources.
/******************************/
//Release kernel.
p1.status = clReleaseKernel(kernelAdd);
//Release the program object.
p1.status = clReleaseProgram(p1.program);
//Release mem object.
/****************************/
//status = clReleaseMemObject(inputBuffer);
p1.status = clReleaseMemObject(outputBuffer);
//Release Command queue.
p1.status = clReleaseCommandQueue(p1.commandQueue);
//Release Command queue.
p1.status = clReleaseContext(p1.context);
/*if (output != NULL)
{
free(output);
output = NULL;
}*/
if (p1.devices != NULL)
{
free(p1.devices);
p1.devices = NULL;
}
std::cout << "Passed!\n";
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment