我对零拷贝的工作方式有点困惑。
1-想要确认以下内容对应于opencl中的零拷贝。
.......................
. . .
. . .
. . CPU .
. SYSTEM . .
. RAM . c3 X .
. <=====> .
...|...................
PCI-E / /
| / /
c2 |X /PCI-E, CPU directly accessing GPU memory
| / / copy c3, c2 is avoided, indicated by X.
...|...././................
. MEMORY<====> .
. OBJECT .c1 .
. . GPU .
. GPU RAM . .
. . .
...........................
.......................
. . .
. . .
. . CPU .
.SYSTEM RAM . .
. . .
. . c3 .
. MEMORY<====> .
...| OBJECT............
| \ \
PCI-E \ \PCI-E, GPU directly accessing System memory. copy c2, c1 is avoided
| \ \
C2 |X \ \
...|.........\..\...........
. | . .
. <=======> .
. GPU c1 X GPU .
. RAM . .
. . .
............................
GPU / CPU直接访问System / GPU-RAM,无需显式复制。
2 - 这有什么好处? PCI-e仍然限制了所有带宽。 或者唯一的好处是我们可以避免副本c2&amp; c1 / c3在上述情况下?
答案 0 :(得分:15)
您对零拷贝如何工作的理解是正确的。基本前提是您可以从设备访问主机内存,或从主机访问设备内存,而无需在中间执行中间缓冲步骤。
您可以通过使用以下标志创建缓冲区来执行零复制:
CL_MEM_AMD_PERSISTENT_MEM //Device-Resident Memory
CL_MEM_ALLOC_HOST_PTR // Host-Resident Memory
然后,可以使用内存映射语义访问缓冲区:
void* p = clEnqueueMapBuffer(queue, buffer, CL_TRUE, CL_MAP_WRITE, 0, size, 0, NULL, NULL, &err);
//Perform writes to the buffer p
err = clEnqueueUnmapMemObject(queue, buffer, p, 0, NULL, NULL);
使用零拷贝,您可以通过执行以下操作的实现来实现性能:
相反,你可以一步到位
在某些实现中,映射和取消映射的调用可以隐藏数据传输的成本。如在我们的例子中,
如果实现以这种方式执行,那么使用映射方法将没有任何好处。但是,AMD更新的OpenCL驱动程序允许直接写入数据,使得映射和取消映射的成本几乎为0.对于独立显卡,请求仍然通过PCIe总线进行,因此数据传输速度可能很慢。
然而,在APU架构的情况下,使用零拷贝语义的数据传输成本可以极大地提高由于APU独特架构而导致的传输速度(如下图所示)。在这种架构中,PCIe总线被统一的北桥(UNB)取代,可以实现更快的传输。
BE AWARE 当使用内存映射的零拷贝语义时,从主机读取设备端缓冲区时,您将看到绝对可怕的带宽。这些带宽大约为0.01 Gb / s,很容易成为代码的新瓶颈。
很抱歉,如果这是太多的信息。这是我的论文主题。