'Delete cl::buffer from Device in OpenCL C++
I am trying to set up memory management in my program as I noticed that my GPU's VRAM slowly fills up. I tried with clReleaseMemObject
but it gives me the
No suitable conversion from cl::Buffer to cl_mem exists
error. I tried to put all of my buffers in a vector and .clear() it but the memory still fills up. Is there something else to clear the buffers that I loaded with queue.enqueueWriteBuffer()
? Here's the code that I currently have. What else can I do to clear the memory after running the function? I am a complete beginner in OpenCL so I don't know much. Currently I am trying to write an API that generates everything for you because I need it for a project that would benefit running things on GPU. I am not trying to optimize everything 100% but I don't want it to fill up my gpu so fast. My API works but the memory management is still not working.
class CL_Helper
{
public:
std::vector<cl::Platform> platforms;
std::vector<cl::Device> devices;
cl::Device device;
std::vector<std::vector<double>> vectorOfIntVectors;
std::vector<cl::Buffer> clbuffer_vector;
cl::Program::Sources sources;
std::string kernel_code;
std::string readFile(std::string fileName)
{
std::ifstream t(fileName);
std::string str((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
return str;
}
void addAsInput(std::vector<double> inputVector)
{
vectorOfIntVectors.push_back(inputVector);
}
void startup(std::string inputFile)
{
cl::Platform::get(&platforms);
kernel_code = readFile(inputFile);
if (platforms.size() == 0)
{
std::cout << "No OpenCL platforms found" << std::endl;//This means you do not have an OpenCL compatible platform on your system.
exit(1);
}
platforms[0].getDevices(CL_DEVICE_TYPE_ALL, &devices);
device = devices[0];
std::cout << "Using device: " << device.getInfo<CL_DEVICE_NAME>() << std::endl;
std::cout << "Using platform: " << platforms[0].getInfo<CL_PLATFORM_NAME>() << std::endl;
sources.push_back({ kernel_code.c_str(),kernel_code.length() });
}
std::vector<double> input_vectors;
int mainRunner(std::string inputFile, double returnVector[], int sizeOfVectors)
{
startup(inputFile);
cl::Context context(device);
cl::Buffer buffer_C(context, CL_MEM_READ_WRITE, sizeof(double) * sizeOfVectors);
for (size_t i = 0; i < vectorOfIntVectors.size(); i++)
{
cl::Buffer newBuffer(context, CL_MEM_READ_WRITE, sizeof(double) * sizeOfVectors);
clbuffer_vector.push_back(newBuffer);
}
cl::Program program(context, sources);
if (program.build({ device }) != CL_SUCCESS)
{
std::cout << " Error building: " << program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(device) << std::endl;//print the build log to find any issues with your source
exit(1);
}
cl::CommandQueue queue(context, device, 0, NULL);
//Write our buffers that we are adding to our OpenCL device
for (size_t index = 0; index < 2; index++)
{
queue.enqueueWriteBuffer(clbuffer_vector[index], CL_TRUE, 0, sizeof(double) * sizeOfVectors, vectorOfIntVectors.at(index).data());
}
queue.enqueueWriteBuffer(buffer_C, CL_TRUE, 0, sizeof(double) * sizeOfVectors, returnVector);
cl::Kernel simple_add(program, "simple_add");
for (size_t i = 0; i < 2; i++)
{
std::cout << i << std::endl;
simple_add.setArg(i, clbuffer_vector.at(i));
}
simple_add.setArg(vectorOfIntVectors.size(), buffer_C);
queue.finish();
cl::Event e;
queue.enqueueNDRangeKernel(simple_add, cl::NullRange, cl::NDRange(sizeOfVectors), cl::NullRange, 0, &e);
e.wait();
queue.enqueueReadBuffer(buffer_C, CL_TRUE, 0, sizeof(double) * sizeOfVectors, returnVector);
clbuffer_vector.clear();
vectorOfIntVectors.clear();
devices.clear();
platforms.clear();
clReleaseDevice(0);
return 0;
}
};
Solution 1:[1]
cl::Buffer
objects are deleted automnatically once they go out of scope.
// no VRAM allocated yet
{
cl::Buffer cl_buffer(device.get_cl_context(), CL_MEM_READ_WRITE, capacity(), nullptr, &error);
// cl_buffer exists and occupies VRAM
}
// cl_buffer is out of scope, VRAM is freed
To manually delete a buffer that is still in scope, you can do this: cl_buffer = nullptr;
As a general tip, if you use multiple buffers of the same size sequentially, allocate only one buffer once at initialization and reuse it over and over again. If you need various buffers of different size sequentially, it is also faster to allocate one buffer of the largest possible size only once and reuse it.
For a much easier way to deal with OpenCL memory management, consider this OpenCL-Wrapper. This gives you one Memory
object for both host and device buffers (or only either one), so you don't need any duplicate code or keep track of buffer length or data type. The wrapper also automatically keeps track of global memory usage of the device and tells you if you run out of memory. Memory is freed on both host and device automatically if a Memory
object goes out of scope, or if you call memory.delete_buffers();
or memory.delete_host_buffer()
/memory.delete_device_buffer()
.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | ProjectPhysX |