opencl - OpenCL 缓冲区创建
问题描述
我对 OpenCL 还很陌生,虽然到目前为止我已经理解了所有内容,但是我无法理解缓冲区对象的工作原理。
我不明白缓冲区对象的存储位置。在这个StackOverflow 问题中指出:
如果您只有一台设备,可能 (99.99%) 将在设备中。(在极少数情况下,如果设备暂时没有足够的内存,它可能在主机中)
对我来说,这意味着缓冲区对象存储在设备内存中。但是,正如StackOverflow 问题中所述,如果在 中使用该标志,则CL_MEM_ALLOC_HOST_PTR
使用clCreateBuffer
的内存很可能是固定内存。我的理解是,当内存被固定时,它不会被换出。这意味着固定内存必须位于 RAM 中,而不是设备内存中。
那么实际发生了什么?
我想知道标志是什么:
CL_MEM_USE_HOST_PTR
CL_MEM_COPY_HOST_PTR
CL_MEM_ALLOC_HOST_PTR
暗示缓冲区的位置。
谢谢
解决方案
我们先来看看clCreateBuffer的签名:
cl_mem clCreateBuffer(
cl_context context,
cl_mem_flags flags,
size_t size,
void *host_ptr,
cl_int *errcode_ret)
这里没有任何参数可以为 OpenCL 运行时提供一个确切的设备,缓冲区应该被放置到其内存中,因为一个上下文可以有多个设备。运行时仅在我们使用缓冲区对象时才知道,例如从/向其读取/写入,因为这些操作需要连接到特定设备的命令队列。
每个内存对象都驻留在主机内存或上下文设备的内存之一中,运行时可能会根据需要迁移它。所以一般来说,每个内存对象都可能在 OpenCL 运行时中有一块内部主机内存。运行时实际上所做的是依赖于实现的,所以我们不能不做太多假设而得不到可移植的保证。这意味着关于 pinning 等的一切都是依赖于实现的,你只能希望最好,但避免使用肯定会阻止使用 pinned memory 的模式。
为什么我们需要固定内存? 固定内存意味着,我们进程地址空间中内存页面的虚拟地址具有固定转换为 RAM 的物理内存地址。这可以在 GPU 的设备内存和使用 PCIe 的 CPU 内存之间实现 DMA(直接内存访问)传输(对物理地址进行操作)。DMA 降低了 CPU 负载并可能提高了复制速度。所以我们希望我们的 OpenCL 内存对象的内部主机存储被固定,以提高内部主机存储和 OpenCL 内存对象的设备内存之间的数据传输性能。
作为一个基本的经验法则:如果您的运行时分配主机内存,它可能会被固定。如果你在你的应用程序代码中分配它,运行时会悲观地假设它没有被固定——这通常是一个正确的假设。
CL_MEM_USE_HOST_PTR
允许我们为 OpenCL 实现提供内存,用于对象的内部主机存储。如果我们调用内核,这并不意味着内存对象不会迁移到设备内存中。由于该内存是用户提供的,因此运行时不能假定它是固定的。这可能会导致在设备传输之前在未固定的内部主机存储和固定的缓冲区之间进行额外的复制,以便为主机设备传输启用 DMA。
CL_MEM_ALLOC_HOST_PTR
我们告诉运行时为对象分配主机内存。它可以被固定。
CL_MEM_COPY_HOST_PTR
我们提供主机内存来复制初始化我们的缓冲区,而不是在内部使用它。我们也可以将它与CL_MEM_ALLOC_HOST_PTR
. 运行时将为内部主机存储分配内存。它可以被钉住。
希望有帮助。
推荐阅读
- oracle - Oracle dbms_aq 异常队列
- javascript - 异步/等待 - 在 MySQL 回调中将数据传递给 Puppeteer
- c# - c#中的休眠映射
- r - geom_line 中各个破折号的交替颜色
- wordpress - 将愿望清单添加到“我的帐户”页面 wooCommerce - 问题
- python - 对于 Python 套接字,有没有办法设置使用的本地接口?
- security - 使用外部身份验证提供程序将用户存储在我的数据库中
- c# - WCF 下 SOAP Web 服务的同时客户端证书和用户名身份验证
- eclipse - 如何在具有不同拱门的远程机器上分析特定线程?
- javascript - 变量被分配了一个值但从未使用过,除非它实际被使用