cl_int CLFW::get(cl::Program::Sources &sources, std::vector<std::string> &files) { sources.clear(); cl_int error = 0; if (files.size() == 0) return CL_INVALID_VALUE; for (int i = 0; i < files.size(); ++i) { Print("adding " + files[i] + " to sources.", infoFG, infoBG); long length = 0; char *source = 0; error|=loadFile(files[i].c_str(), &source, &length); sources.push_back({ source, length }); } return error; }
cl_int CLFW::get(cl::Program::Sources &sources) { sources.clear(); char* text = 0; long temp; loadFile("./opencl_sources.txt", &text, &temp); char* file = strtok(text, "\n\r\n\0"); do { Print("adding " + std::string(file) + " to sources.", infoFG, infoBG); long length = 0; char *source = 0; loadFile(file, &source, &length); sources.push_back({ source, length }); file = strtok(NULL, "\n\r\n\0"); } while (file != NULL); return CL_SUCCESS; }
int main(int argc, char *argv[]) { cl_int err = CL_SUCCESS; cl::Event evt; std::vector<cl::Platform> platforms; cl::Platform::get(&platforms); if (platforms.size() == 0) { return false; } platform_ = platforms[0]; cl_context_properties properties[] = { CL_CONTEXT_PLATFORM, (cl_context_properties)(platforms[0])(), 0}; context_ = cl::Context(CL_DEVICE_TYPE_GPU, properties, NULL, NULL, &err); CHECK_CL_ERROR(err, "cl::Context"); std::vector<cl::Device> devices = context_.getInfo<CL_CONTEXT_DEVICES>(); if (devices.size() == 0) { return false; } device_ = devices[0]; sources_.push_back(std::make_pair(source_str.c_str(), source_str.size())); program_ = cl::Program(context_, sources_); err = program_.build(devices); if (err != CL_SUCCESS) { std::string log = program_.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devices[0]); std::cout << "program.build() ERROR: " << log.c_str() << std::endl; return false; } kernel_ = cl::Kernel(program_, "hello", &err); CHECK_CL_ERROR(err, "cl::Kernel"); buf_ = cl::Buffer(context_, CL_MEM_READ_ONLY, 1024, NULL, &err); queue_ = cl::CommandQueue(context_, device_, 0, &err); CHECK_CL_ERROR(err, "cl::CommandQueue"); kernel_.setArg(0, buf_); err = queue_.enqueueNDRangeKernel(kernel_, cl::NullRange, cl::NDRange(10, 10), cl::NullRange, NULL, &evt); evt.wait(); CHECK_CL_ERROR(err, "queue.enqueueNDRangeKernel()"); return 0; }
CL_helper(const char *kernelFileName, std::vector<std::string> kernelNames, bool loadBinary, bool writeBinary, bool usePreProcArgs = false, std::map<std::string, std::string> preProcArgs = std::map<std::string, std::string>()){ cl::Platform::get(&platforms); if(platforms.size()==0) throw std::runtime_error("No OpenCL platforms found.\n"); int selectedPlatform=0; platform=platforms.at(selectedPlatform); platform.getDevices(CL_DEVICE_TYPE_ALL, &devices); if(devices.size()==0) throw std::runtime_error("No opencl devices found.\n"); int selectedDevice=0; device=devices.at(selectedDevice); context = cl::Context(devices); try{ if(loadBinary){ std::string vendor=platform.getInfo<CL_PLATFORM_VENDOR>(); size_t found = vendor.find("NVIDIA"); if(found != std::string::npos){ FILE* fp; fp = fopen("src/kernels/julia_filter.ptx", "r"); if (!fp) { std::cerr << "Error loading kernel binary" << std::endl; std::cerr << "Building kernel from .cl file" << std::endl; loadBinary = false; } else { fseek(fp, 0, SEEK_END); size_t kernel_sz = ftell(fp); rewind(fp); char* kernel_str = (char*)malloc(kernel_sz); unsigned bytes = fread(kernel_str, 1, kernel_sz, fp); fclose(fp); binaries.push_back(std::make_pair((void*)kernel_str,kernel_sz+1)); program = cl::Program(context, devices, binaries); program.build(devices); } } else{ std::cerr << "Vendor not NVIDIA, cannot load .ptx binary" << std::endl; std::cerr << "Building kernel from .cl file" << std::endl; loadBinary = false; } } if(!loadBinary){ std::string kernelSource=CL_helper::LoadSource(kernelFileName); sources.push_back(std::make_pair(kernelSource.c_str(), kernelSource.size()+1)); program = cl::Program(context, sources); if(usePreProcArgs && !preProcArgs.empty()){ std::string preProcArgsString; for(auto& arg : preProcArgs) { preProcArgsString += "-D" + arg.first + "=" + arg.second + " "; } program.build(devices, preProcArgsString.c_str()); } else { //std::string params = "-cl-unsafe-math-optimizations"; program.build(devices); } } }catch (cl::Error er) { for(unsigned i=0;i<devices.size();i++){ std::cerr <<"Log for device " << devices[i].getInfo<CL_DEVICE_NAME>().c_str()<<std::endl; std::cerr << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devices[i]).c_str() <<std::endl; } std::cerr << "ERROR:" << er.what() << " Code " << er.err()<<std::endl; throw; } for(unsigned i=0; i<kernelNames.size();i++){ kernels.push_back( cl::Kernel(program, kernelNames.at(i).c_str()) ); } queue = cl::CommandQueue(context, device); if(writeBinary){ size_t bin_sz; program.getInfo( CL_PROGRAM_BINARY_SIZES, &bin_sz); unsigned char *bin = (unsigned char *)malloc(bin_sz); program.getInfo(CL_PROGRAM_BINARIES, &bin); FILE* fp = fopen("src/kernels/julia_filter.ptx", "wb"); fwrite(bin, sizeof(char), bin_sz, fp); fclose(fp); free(bin); } }