C++ OpenCL:当缓冲区超出范围时,子缓冲区会发生什么情况?
C++ OpenCL: what happens to a subbuffer when a buffer goes out of scope?
我一直找不到关于OpenCL的C++包装器如何处理内存释放的明确来源;任何指向此类引用的指针都会很棒。
我现在的特殊问题是,如果缓冲区在相应的子缓冲区之前超出范围会发生什么?假设,在这种情况下:
cl::Buffer *buf=new cl::Buffer;
*buf=cl::Buffer(context, CL_MEM_READ_WRITE, 1000);
cl_buffer_region reg={20, 50};
cl::Buffer sub=buf->createSubBuffer(CL_MEM_READ_WRITE, CL_BUFFER_CREATE_TYPE_REGION, ®);
delete buf;
分配的设备内存是否被解除分配,留下 buf 指向无效的内存地址,或者程序是否等待 sub 也被销毁?
OpenCL 的C++包装器使用本机 OpenCL API 提供的引用计数(有关参考,请参阅clRetainMemObject
和clReleaseMemObject
)来跟踪每个缓冲区。将它们视为实现如下内容可能是准确的:
class cl::Buffer {
cl_mem buffer;
public:
Buffer(/*...*/) { buffer = clCreateBuffer(/*...*/);} //Implicit Retain
Buffer(Buffer const& o) {buffer = o.buffer; clRetainMemObject(buffer);}
~Buffer() {clReleaseMemObject(buffer);}
/*...*/
};
这也适用于子缓冲区:它们使用与主缓冲区相同的内部引用计数机制(clCreateSubBuffer
声明在生成缓冲区的对象上隐式调用 keep),因此它也将被引用计数,并且只要拥有对象仍然存在,并且保持对原始缓冲区对象的引用。
此代码可能会有所帮助:
cl::Buffer do_stuff() {
cl::Buffer buffer{context, CL_MEM_READ_WRITE, 1000};
std::cout << "Ref Count: " << buffer.getInfo<CL_MEM_REFERENCE_COUNT>() << std::endl;
//Should print "Ref Count: 1" to console
cl::Buffer copy = buffer; //retain
std::cout << "Ref Count: " << buffer.getInfo<CL_MEM_REFERENCE_COUNT>() << std::endl;
//Should print "Ref Count: 2"
std::cout << "Ref Count: " << copy.getInfo<CL_MEM_REFERENCE_COUNT>() << std::endl;
//Should print "Ref Count: 2"
cl_buffer_region reg={20, 50};
cl::Buffer sub = buffer.createSubBuffer(CL_MEM_READ_WRITE, CL_BUFFER_CREATE_TYPE_REGION, ®); //retain
std::cout << "Ref Count: " << buffer.getInfo<CL_MEM_REFERENCE_COUNT>() << std::endl;
//Should print "Ref Count: 3"
std::cout << "Ref Count: " << sub.getInfo<CL_MEM_REFERENCE_COUNT>() << std::endl;
//I believe it prints "Ref Count: 1", but if it inherits the main buffer's reference count,
//then it'll print "Ref Count: 3" instead. Not sure what the actual specification is
return sub;
//release buffer
//release copy
}
void outer_code() {
cl::Buffer subBuffer = do_stuff();
//Should print "Ref Count: 1", "Ref Count: 2", "Ref Count: 2", "Ref Count: 3", "Ref Count: 1", in order
std::cout << "Ref Count: " << subBuffer.getInfo<CL_MEM_REFERENCE_COUNT>() << std::endl;
//Should print "Ref Count: 1"
//End of scope: release subBuffer
}
我们还可以确认,使用保留/释放语义,在子缓冲区也被删除之前,原始缓冲区不会被删除,因为规范是这样说的:
在
memobj
引用计数变为零并且命令排队等待在 使用memobj
的命令队列已完成,将删除内存对象。如果memobj
是缓冲区对象,则在删除与 memobj 关联的所有子缓冲区对象之前,无法删除memobj
。使用此函数释放不是通过创建对象或调用clRetainMemObject
获得的引用会导致未定义的行为—clReleaseMemObject,OpenCL2.0 规范,第 156 页
因此,假设 C++ OpenCL 包装器已正确实现,那么可以肯定地说,在您删除原始缓冲区对象的所有者后,子缓冲区将保留,因为将使用保留/释放语义删除原始缓冲区,从而一直保持到子缓冲区被删除。
- 将指针分配给另一个指针时会发生什么情况?
- 在什么情况下,两个堆栈分配的结构对象的 this 点指向同一个地址?
- 在什么情况下,我想在 C/C++ 代码中使用内联汇编代码
- 发生注入类名时会发生什么情况?(C++)
- 在什么情况下,需要共享智能指针而无法使用唯一指针?
- 重新分配向量时,向量中的内存会发生什么情况
- 如果结构中的字符串比使用的 p/调用签名长或短,会发生什么情况?
- 为什么或在什么情况下,你会将参数作为C++中的引用(或指针)传递给函数?
- 如果我向一个12字节的缓冲区写入的字节数少于12,会发生什么情况
- 删除对象(具有不同类型)的引用时会发生什么情况?
- libQGLViewer 如何在没有清除缓冲区的情况下绘制
- 如果我在 c++ 中以 new 的放置形式使用没有足够的内存,会发生什么情况?
- 使用 Google 基准测试时返回值会发生什么情况?
- 正在连接的等待条件变量的线程会发生什么情况?
- 如果未定义的C++行为符合 C 定义的行为,会发生什么情况?
- 在什么情况下,使用'const T*'输入参数比'const T&'更可取?
- 如果字符串在 C/C++ 中没有 NUL 字符(以防编译器允许它通过)会发生什么情况?
- 将虚拟方法定义为私有方法时会发生什么情况?
- DirectX:如果绑定索引缓冲区但不绑定顶点缓冲区,会发生什么情况
- C++ OpenCL:当缓冲区超出范围时,子缓冲区会发生什么情况?