如何解决CL_DEVICE_HOST_UNIFIED_MEMORY 是否会改变缓冲区的处理方式?
我正在学习 OpenCL,使用 PyOpenCL 和 Numpy。到目前为止,我已经了解到,将 Numpy 数组传递给内核时,您需要创建一个 pyopencl.Buffer
对象来表示设备上的数组,然后将 Numpy 数组中的一个副本排入队列 {{1 }} 到 Buffer
。
当设备是具有自己内存的显卡时,这是有道理的,但是当设备与主机共享内存时会发生什么?例如,我的 MacBook Pro 中的 M1 芯片具有统一的内存架构,设备显示 CommandQueue
为 1。在 OpenCL 1.2 规范中,此设备属性列为 host_unified_memory
并表示>
如果设备和主机具有统一的内存子系统,则为 CL_TRUE,否则为 CL_FALSE
这是否意味着我可以更改代码以避免在统一内存系统上复制缓冲区?还是 OpenCL 检测到内存是统一的,从而使入队副本成为空操作?
解决方法
我愿意。在大多数情况下,我倾向于在所有系统上统一使用 clEnqueueMapBuffer
,但也需要权衡利弊。这就是会发生的事情。
1.a) 在分配缓冲区时,要求驱动程序为您分配主机副本CL_MEM_ALLOC_HOST_PTR
。在集成/统一系统上,它可能会创建由 GPU 和 CPU 共享的固定内存。驱动程序还处理对齐规则等。
或
1.b) 使用与 CL_MEM_USE_HOST_PTR
充分对齐的指针。例如。旧的 Intel GPU 使用 even-cacheline (128 B)。我总是使用系统页面对齐。我不确定你的系统。如果您不需要拥有内存,请使用 1.a),因为它会更健壮。
任何一种方法都有效,并且会发生两种情况之一。
2.a) 在没有统一内存(例如离散部分)的系统上,缓冲区将导致驱动程序在主机上为您创建一个影子/暂存缓冲区副本,并在您完成后上传它介于 (clEnqueueUnmapMemObject
和使用它的 clEnqueueNDRangeKernel
之间)。你可以幸福地不知道这一点。它会起作用。当然,超大缓冲区可能效率不高,因为您要创建额外的缓冲区。
2.b) 在具有统一内存的系统上,映射操作将是零复制操作,这非常便宜。注意:即使它是固定内存(GPU 正在访问与 CPU 相同的物理页面,也可能是虚拟页面),请确保使用 OpenCL 规则仅访问入队映射和入队取消映射调用中的缓冲区。驱动程序可以出于多种原因改变主意,并像 2.a) 中那样创建临时副本。例如。如果您传递未对齐的 CL_MEM_USE_HOST_PTR
基数供驱动程序使用,它会在您身上制作临时副本。
在这两种情况下,事情都会“正常工作”。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。