2

我正在使用 Cuda API: cudaMemcpyAsync ( void* dst, const void* src, size_t count, cudaMemcpyKind kind, cudaStream_t stream = 0 )

从 CPU 内存中复制 GPU 内存中的数据。如果使用 memcpy() 将数据从 CPU 内存复制到持久内存,我们需要显式调用刷新操作(例如 clflush())以确保从 CPU 缓存中刷新数据。使用 cudaMemcpyAsync() 从 GPU 内存复制到持久内存时是否需要调用刷新操作?

4

2 回答 2

2

使用 cudaMemcpyAsync() 从 GPU 内存复制到持久内存时是否需要调用刷新操作?

不。

但是,您正在调用潜在的异步 API,因此您可能需要使用同步 API(流或设备范围)之一,以确保可能重叠并需要访问同一内存区域的操作之间的数据一致性。

于 2022-01-08T09:05:59.047 回答
2

从 Sandy Bridge 开始,采用服务器非核心设计的英特尔处理器支持默认启用的 Data Direct I/O (DDIO)。使用 DDIO,针对 WB 类型的系统内存位置的入站 PCIe 写入是分配写入事务。

对于完整写入(写入整个高速缓存行),IIO 首先通过使一致性域中的所有副本无效来获得目标高速缓存行的所有权,但在与原始设备连接的同一 NUMA 节点中存在的 L3 中除外. 如果目标 L3 中不存在该行,则分配一个 L3 条目,这可能需要驱逐另一行以腾出空间。写入在 L3 中执行,线路的一致性状态变为 M。这意味着数据不会发送到其地址映射到的内存控制器。部分写入在 IIO(位于一致性域中)中缓冲,直到最终被逐出以写入 LLC(分配或更新)。在 DDIO 中,读取永远不会分配。

即使禁用了 DDIO,也可以在 DDIO 中缓冲 PCIe 写入。当cudaMemcpyAsync甚至cudaMemcpy返回时,无法保证所有写入都已到达英特尔处理器上的持久性域(除非您拥有整个系统持久性)。此外,内存副本不能保证是持久原子的,也不能保证字节从 IIO 移动到目标内存控制器的顺序。您需要一个标志来告诉您是否保留了整个数据。

您可以使用屏障(cudaStreamSynchronize()cudaDeviceSynchronize())在主机上等待,直到数据复制操作完成,然后刷新每个缓存行,然后按该顺序写入标志。

于 2022-01-11T22:21:03.070 回答