Memory OpenCL内存传输函数是如何工作的?

Memory OpenCL内存传输函数是如何工作的?,memory,opencl,dma,Memory,Opencl,Dma,我有几个问题,与OpenCL内存传递函数有关。我面临许多与此相关的问题,但没有一个得到进一步的回答。也许我们可以在这里收集总体答案 这是我目前对移动数据的三种方式的看法: 1) enqueueReadBuffer/enqueueWriteBuffer-这两个函数始终将在主机上创建的缓冲区内容复制到设备,并从设备复制。这里不使用固定内存和DMA机制 2) enqueueMigrateMemObjects—有时将其描述为enqueueRead/Write的替代方法,但在这种情况下,内存是在调用此函数

我有几个问题,与OpenCL内存传递函数有关。我面临许多与此相关的问题,但没有一个得到进一步的回答。也许我们可以在这里收集总体答案

这是我目前对移动数据的三种方式的看法:

1) enqueueReadBuffer/enqueueWriteBuffer-这两个函数始终将在主机上创建的缓冲区内容复制到设备,并从设备复制。这里不使用固定内存和DMA机制

2) enqueueMigrateMemObjects—有时将其描述为enqueueRead/Write的替代方法,但在这种情况下,内存是在调用此函数时复制的。这里不使用固定内存和DMA机制

3) enqueueMapBuffer/EnqueueUnmappBuffer-此处始终使用固定内存和DMA机制

此函数使用两种类型的缓冲区:使用CL_MEM_USE_HOST_PTR标志或CL_MEM_ALLOC_HOST_PTR标志创建的缓冲区。对于第一个,我们将在主机上创建的数组映射到在设备上创建的数组。使用时,在设备上分配第二个阵列,并将其映射到主机上新创建的阵列

这是我可以根据文档说明的内容。我运行了几个测试,但只看到迁移函数比读/写更快。 关于这三段,我有一些问题:

1) 如果这些函数只进行复制,那么为什么人们在这里谈论在读/写过程中固定/取消固定内存?这些函数在哪些条件下使用固定内存?或者这只是intel实现的功能,所有与内存传输相关的函数都使用固定内存和DMA

另外,这是否意味着,如果我使用固定内存,那么DMA机制将工作?反之亦然-如果我想让DMA工作,我需要固定内存

2) 这是迁移函数吗?在没有额外开销的情况下,enqueueRead/WriteBuffer函数内部到底发生了什么,这些enqueueRead/WriteBuffer函数提供了额外开销?它总是只是复制还是DMA传输

出于某些原因,某些来源在谈到DMA传输时,使用“复制”、“内存”、“迁移”字在两个缓冲区(主机和设备上)之间传输数据。但是,不可能有任何副本,我们只是直接写入缓冲区,而没有任何副本。在DMA期间,我应该如何处理此写操作

如果我使用带有缓冲区的EnqueueMigrateMojects,使用标志CL_MEM_use_HOST_PTR创建,会发生什么

3) 有了这两个功能,就完全混淆了。如果我使用:a)现有主机指针或b)新分配的主机指针,映射和读/写将如何发生

在这里,我也不能正确理解DMA是如何工作的。如果我将主机端的缓冲区映射到设备端的缓冲区,那么借助于哪些功能在它们之间传输内存?我应该总是在之后取消映射缓冲区吗

对此没有任何解释,例如:“当我们使用此标志创建一个新缓冲区并使用此内存函数传输时,数据以这种方式传输,并使用诸如…之类的功能。如果内存创建为只读,则会发生这种情况,如果内存为只读-此”

也许已经有了一个很好的指南,但是从OpenCL规范来看,我无法回答我的问题。

1)DMA用于所有数据传输命令,但它只适用于固定内存区域。否则操作系统只会将其分页并提供虚假数据

在enqueueReadBuffer/enqueueWriteBuffer中,数据首先进入已经固定的内部缓冲区(或者我不知道是否及时固定),然后进入使用DMA的GPU内存。因为GPU可以发送或接收大小为4096的整数倍、起始地址为4096的倍数等页面中的数据(取决于供应商的对齐规则)。ReadBuffer和WriteBuffer的速度可能较慢,因为它有两个拷贝,一个拷贝从主机阵列到内部阵列,然后从内部固定阵列到gpu缓冲区

在enqueueMapBuffer/EnqueueUnampbuffer中,它可以直接高效地进行DMA传输,因为它只刷新从主机端使用的页面(在主机端写入主机阵列,但由于它已映射,所以会上载到gpu缓冲区),因为它临时锁定该区域,仅一次


使用CL_MEM_ALLOC_HOST_PTR或CL_MEM_USE_HOST_PTR只能是一种优化,以跳过内部(固定)阵列复制步骤,但确保它们符合要求。不能保证总是固定阵列,它们是相当稀缺的资源。锁定意味着操作系统不会在任何时候将其分页。您也可以只“触摸”缓冲区页面(4kB?)区域的第一个字节,以伪造“固定”(在调用数据传输函数之前),但这是不合法的,可能并不总是有效。但我在OpenCL应用程序中观察到了加速,在使用主机PTR标记的缓冲区上只提供了良好的偏移量和良好的复制大小(如4k对齐和64k大小)。(仅在AMD、NVIDIA GPU和Intel IGPU上试用,但不能说明Xeon Phi设备)

您只需固定内存即可跳过额外的复制开销。您需要映射/取消映射以优化固定

2) 迁移功能将GPU缓冲区的所有权迁移到另一个GPU。若你们在同一个GPU上使用它,除了将自身复制到RAM中,然后再将自身复制回来之外,它不应该做任何有用的事情。如果使用
CL\u MIGRATE\u MEM\u OBJECT\u-CONTENT\u UNDEFINED
则不会复制数据。只需将所有权移动到其他设备。然后您可以自己复制数据(如果您的意思是想要的数据在主机上,而不是在源设备上)

有些实现直接通过pci-e复制数据(我不知道这是否使用GPU1 DMA到GPU2 DMA,但我想是的),有些实现通过RAM使用双DMA操作(但在某种程度上可以通过流水线进行优化?)

如果我使用Enqueue Migra,会发生什么