Memory management 使用clCreateBuffer+创建缓冲区对象有什么区别;CL_MEM_COPY_HOST_PTR与clCreateBuffer+;克伦奎布瑞特布弗?

Memory management 使用clCreateBuffer+创建缓冲区对象有什么区别;CL_MEM_COPY_HOST_PTR与clCreateBuffer+;克伦奎布瑞特布弗?,memory-management,opencl,Memory Management,Opencl,我在教程中看到了这两个版本,但我无法找出它们的优缺点。哪一个是合适的 cl_mem input = clCreateBuffer(context,CL_MEM_READ_ONLY,sizeof(float) * DATA_SIZE, NULL, NULL); clEnqueueWriteBuffer(command_queue, input, CL_TRUE, 0, sizeof(float) * DATA_SIZE, inputdata, 0, NULL, NULL); vs 谢谢 [更新]

我在教程中看到了这两个版本,但我无法找出它们的优缺点。哪一个是合适的

cl_mem input = clCreateBuffer(context,CL_MEM_READ_ONLY,sizeof(float) * DATA_SIZE, NULL, NULL);
clEnqueueWriteBuffer(command_queue, input, CL_TRUE, 0, sizeof(float) * DATA_SIZE, inputdata, 0, NULL, NULL);
vs

谢谢

[更新]


我在第二个示例中添加了
CL\u MEM\u COPY\u HOST\u PTR,
,以使其正确。

这两个示例之间的主要区别在于,第一个示例在设备上分配内存,然后将数据复制到该内存。第二个只分配


或者你的意思是
clCreateBuffer(上下文,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,sizeof(float)*数据大小,inputdata,NULL)

我假设inputdata不为空

在这种情况下,第二种方法根本不起作用,因为规范规定,如果出现以下情况,clCreateBuffer将返回NULL和错误:

如果主机PTR为空,并且在标志中设置了使用主机PTR或复制主机PTR,或者如果主机PTR不为空,但在标志中未设置复制主机PTR或使用主机PTR,则CLU无效主机PTR

你是说两者都有

clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,sizeof(float) * DATA_SIZE, inputdata, NULL);

第一种方法应该与您展示的第一种方法大致相同,而第二种方法实际上不会复制数据,而是使用提供的内存位置进行缓冲存储(将部分或全部缓存在设备内存中)。这两者中哪一个更好显然取决于使用场景


就个人而言,我更喜欢使用两步方法,首先分配缓冲区,然后用writeToBuffer填充缓冲区,因为我发现更容易看到发生了什么(当然一步可能更快(或者可能没有,这只是猜测))

我遇到的一个主要区别是:

cl_mem input=clCreateBuffer(上下文,cl_mem_只读,sizeof(float)*数据大小,NULL,NULL);
clEnqueueWriteBuffer(命令队列,输入,CL\u真,0,sizeof(float)*数据大小,输入数据,0,NULL,NULL)

这第一组命令将创建一个空缓冲区,并将命令排入命令队列以填充缓冲区

cl_mem input = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, ,sizeof(float) * DATA_SIZE, inputdata, NULL)
第二个命令将创建缓冲区并立即填充它。请注意,此参数列表中没有命令队列,因此它使用当前输入数据的内容


如果您已经在运行CL代码,并且源指针依赖于命令队列中的前一个命令完成(例如,前一个输出缓冲区的排队读取),那么您肯定要使用第1个方法。如果您试图在一个命令中创建并填充缓冲区,最终会出现竞争条件,在这种情况下,缓冲区内容将无法正确地等待之前的缓冲区读取完成。

第一种方法的优点是,“clEnqueueWriteBuffer”允许您将事件分配给缓冲区的副本。因此,假设您想测量使用GPU配置选项将数据复制到GPU所需的时间,您可以使用第一种方法,但不能使用第二种方法


第二种方法更紧凑、更易于阅读,并且需要更少的代码行。

在我使用OpenCL的过程中,我发现了两者之间的一个非常重要的区别

cl_mem CT = clCreateImage3DContext, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR , Volume_format, X, Y, Z, rowPitch, slicePitch, sourceData, &error);

对于第一种方法,OpenCL将复制主机指针,而不是直接指向GPU。首先,它将在主机上分配第二个临时缓冲区,如果您将CT之类的大数据加载到GPU,这可能会导致问题。在短时间内,所需的内存是CT大小的两倍。此外,此功能期间不会复制数据。它在参数设置期间复制到使用3D图像对象的内核函数


第二种方法直接将数据复制到GPU。OpenCL没有额外的分配。我认为这可能与普通缓冲区对象相同。

您好,stevenhb,您是对的。我忘了CL_MEM_COPY_HOST_PTR。那么它们现在有什么区别呢?我认为它们没有区别,除了Grizzly提到的异步传输能力。嗨,Grizzly,你是对的。我忘了CL_MEM_COPY_HOST_PTR。因此,没有确凿的事实可以说明这一点或那一点?至少从规范来看,不应该这样。当然,性能可能会(也可能不会)发生变化,但这取决于实现,并且可能会发生变化,因此我无论如何都不会指望它(如果性能对内存传输至关重要,那么研究异步内存传输可能很有意思(使用CL_FALSE作为clEnqueueWriteToBuffer的阻塞参数)。同样,它的速度是否更快取决于实现,对于CPU来说,最快的应该是使用CL_USE_HOST_PTR。一般来说,我会确保memtransfertime没有那么重要,并做到这一点。多亏了,性能并不是那么重要,这更像是一个学术问题。
cl_mem input = clCreateBuffer(context,CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, ,sizeof(float) * DATA_SIZE, inputdata, NULL)
cl_mem CT = clCreateImage3DContext, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR , Volume_format, X, Y, Z, rowPitch, slicePitch, sourceData, &error);
cl_mem CT = clCreateImage3D(Context, CL_MEM_READ_ONLY , Volume_format, X, Y, Z, 0, 0, 0, &error);
error = clEnqueueWriteImage(CommandQue, CT, CL_TRUE, origin, region, rowPitch, slicePitch, sourceData, 0, 0, 0);