I am learning how to program in opencl and I made a simple program that simply takes an array and adds 1 to every element. I want to run it many times (this is just so that i can benchmark how it does against my cpu, I understand it is a dumb application).
I feel like the way I am doing it right now is inefficient because i seem to be instructing the gpu to do each iteration one by one instead of telling it from the start that it has to do it many times.
Here is my code (Please look for the comment "RELEVANT PART STARTS HERE":
#include <iostream>
#include <CL/cl.hpp>
int main(){
//get all platforms (drivers)
std::vector<cl::Platform> all_platforms;
cl::Platform::get(&all_platforms);
if(all_platforms.size()==0){
std::cout<<" No platforms found. Check OpenCL installation!\n";
exit(1);
}
cl::Platform default_platform=all_platforms[0];
std::cout << "Using platform: "<<default_platform.getInfo<CL_PLATFORM_NAME>()<<"\n";
//get default device of the default platform
std::vector<cl::Device> all_devices;
default_platform.getDevices(CL_DEVICE_TYPE_ALL, &all_devices);
if(all_devices.size()==0){
std::cout<<" No devices found. Check OpenCL installation!\n";
exit(1);
}
cl::Device default_device=all_devices[0];
std::cout<< "Using device: "<<default_device.getInfo<CL_DEVICE_NAME>()<<"\n";
cl::Context context({default_device});
cl::Program::Sources sources;
// kernel calculates for each element C=A+B
std::string kernel_code=
" void kernel simple_add(global int* A){ "
" A[get_global_id(0)]=A[get_global_id(0)]+1; "
" } ";
sources.push_back({kernel_code.c_str(),kernel_code.length()});
cl::Program program(context,sources);
if(program.build({default_device})!=CL_SUCCESS){
std::cout<<" Error building: "<<program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(default_device)<<"\n";
exit(1);
}
const int N = 1e5 ;
// create buffers on the device
cl::Buffer buffer_A(context,CL_MEM_READ_WRITE,sizeof(int)*N);
int A[N] ;
for(int i = 0;i<N;i++){
A[i] = i;
}
//create queue to which we will push commands for the device.
cl::CommandQueue queue(context,default_device);
queue.enqueueWriteBuffer(buffer_A,CL_TRUE,0,sizeof(int)*N,A);
int C = 1e5;
// RELEVANT PART STARTS HERE !!!
for(int i = 0;i<C;i++){
cl::Kernel kernel_add=cl::Kernel(program,"simple_add");
kernel_add.setArg(0,buffer_A);
queue.enqueueNDRangeKernel(kernel_add,cl::NullRange,cl::NDRange(N),cl::NullRange);
queue.finish();
}
// RELEVANT PART ENDS HERE !!!
queue.enqueueReadBuffer(buffer_A,CL_TRUE,0,sizeof(int)*N,A);
printf("%d\n",A[N-4]);
return 0;
}