提问人:einpoklum 提问时间:1/9/2020 最后编辑:einpoklum 更新时间:1/14/2020 访问量:122
OpenCL 上下文间缓冲区别名
OpenCL inter-context buffer aliasing
问:
假设我的机器上有 2 个支持 OpenCL 的设备(不包括 CPU);假设我的一个邪恶的同事为他们每个人创造了一个不同的背景,我必须与之合作。
我知道我不能在上下文之间共享缓冲区 - 至少不是正确和正式的。但假设我创建了两个 OpenCL 缓冲区,每个上下文中一个,并使用标志将相同的主机内存区域传递给每个缓冲区。例如:CL_MEM_USE_HOST_PTR
enum { size = 1234 };
//...
context_1 = clCreateContext(NULL, 1, &some_device_id, NULL, NULL, NULL);
context_2 = clCreateContext(NULL, 1, &another_device_id, NULL, NULL, NULL);
void* host_mem = malloc(size);
assert(host_mem != NULL);
buff_1 = clCreateBuffer(context_1, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, size, host_mem, NULL);
buff_2 = clCreateBuffer(context_2, CL_MEM_READ_WRITE | CL_MEM_USE_HOST_PTR, size, host_mem, NULL);
我意识到,正式地,
对使用相同或重叠主机区域创建的多个缓冲区对象进行操作的 OpenCL 命令的结果被视为未定义。
host_ptr
但是,如果我从一个设备复制到这个缓冲区,再从这个缓冲区复制到另一个设备,实际上会发生什么?我对(相对较新的)AMD 和 NVIDIA GPU 的情况特别感兴趣。
答:
如果您的 OpenCL 实现的供应商保证某种超出标准的特定行为,那么请遵循它并确保遵循有关限制的任何说明。
如果没有,那么你必须假设标准是怎么说的。
评论
我知道我不能在上下文之间共享缓冲区
问题不在于上下文。这是平台。基本上有两种情况:
1) 您希望在同一平台的设备之间共享缓冲区。在这种情况下,只需使用所有设备创建一个单一的上下文,不要让您的生活复杂化,并让平台处理它。
2)您需要在不同平台的设备之间共享缓冲区。在这种情况下,你就要靠自己了。
等待“分配和处理拆分上下文错误报告”不会让你走到任何地方,因为如果它是来自同一平台的上下文,他们会告诉你我在 1 中所说的内容,如果是来自不同平台的上下文,他们会告诉你不可能以任何理智的方式支持。
“实际会发生什么”......取决于(取决于 gajillion 事情)。某些平台会尝试将内存指针(如果正确对齐,则用于“正确”的定义)到设备地址空间。某些平台只会静默地将其复制到设备内存中。一些平台还会在每个排队的命令后更新主机内存的内容(这可能意味着速度会大大减慢),而其他平台只会在某些特定的“同步点”更新它。
我的个人经验是避免CL_MEM_USE_HOST_PTR除非我知道我正在使用 iGPU 或 CPU 实现(并且有正确对齐的指针)。
如果您在同一台机器上有 AMD 和 NVIDIA GPU,我不知道它们可以有效地共享缓冲区的任何官方方式,这意味着您无论如何都必须通过主机内存......在这种情况下,我会避免使用CL_MEM_USE_HOST_PTR进行任何游戏,而只依靠 clMap/Unmap 或 clRead/Write。
评论