我正在使用Cuda API:cudaMemcpyAsync ( void* dst, const void* src, size_t count, cudaMemcpyKind kind, cudaStream_t stream = 0 )
以从CPU存储器复制来自GPU存储器的数据。如果使用memcpy((将数据从CPU内存复制到Persistent memory,我们需要显式调用flush操作(例如clflush(((以确保数据从CPU缓存中刷新。使用cudaMemcpyAsync((从GPU内存复制到持久内存时,是否需要调用刷新操作;
使用cudaMemcpyAsync((从GPU内存复制到持久内存时,是否需要调用刷新操作;
否。
但是,您正在调用一个潜在的异步API,因此您可能需要使用其中一个同步API(流或设备范围(,以确保可能重叠并需要访问相同内存区域的操作之间的数据一致性。
采用服务器非核心设计的英特尔处理器,从Sandy Bridge开始,支持默认启用的数据直接I/O(DDIO(。对于DDIO,WB类型的入站PCIe写入目标系统内存位置是一个分配写入事务。
对于完全写入(写入整个高速缓存行(,IIO首先通过使一致性域中的所有副本无效来获得目标高速缓存行的所有权,除了存在于始发设备所连接的同一NUMA节点中的L3中的副本。如果该行在目标L3中不存在,则分配一个L3条目,这可能需要驱逐另一行以腾出空间。在L3中执行写入,并且线的一致性状态变为M。这意味着数据不被发送到其地址被映射到的存储器控制器。部分写入被缓冲在IIO(在一致性域中(中,直到它们最终被逐出以写入LLC(分配或更新(。在DDIO中,读取从不进行分配。
即使DDIO被禁用,PCIe写入也可以在DDIO中缓冲。当cudaMemcpyAsync
甚至cudaMemcpy
返回时,不能保证所有写入都已到达英特尔处理器上的持久性域(除非您具有"全系统持久性"(。此外,不能保证内存拷贝是持久的原子拷贝,也不能保证字节将以何种顺序从IIO移动到目标内存控制器。您需要一个标志来告诉您整个数据是否被持久化。
您可以使用屏障(cudaStreamSynchronize()
或cudaDeviceSynchronize()
(在主机上等待,直到数据复制操作完成,然后按顺序刷新每个缓存行,然后写入一个标志。