假设我有一台具有多核处理器和 GPU 的计算机。我想编写一个在平台的所有核心上运行的 OpenCL 程序。这是可能的还是我需要选择一个运行内核的设备?
4 回答
不,您不能自动跨越 CPU 和 GPU 上的内核,它要么是一个,要么是另一个。
您可以这样做,但这将涉及手动创建和管理两个命令队列(每个设备一个)。
理论上是的,你可以,CL API允许它。但是平台/实现必须支持它,我认为大多数 CL 实现都不支持。
为此,请获取 CPU 设备和 GPU 设备的 cl_device_id,并使用 clCreateContext 为这两个设备创建一个上下文。
一个上下文只能用于一个平台。如果您的多设备代码需要跨平台工作(例如,英特尔平台 CPU OpenCL 和 NVidia GPU),那么您需要单独的上下文。
但是,如果 GPU 和 CPU 碰巧在同一个平台上,那么是的,您可以使用一个上下文。
如果您在同一平台上使用多个设备(两个相同的 GPU,或来自同一制造商的两个 GPU),那么您可以共享上下文 - 只要它们都来自单个 clGetDeviceIDs 调用。
编辑:我应该补充一点,GPU+CPU 上下文并不意味着任何自动管理的 CPU+GPU 执行。通常,最佳实践是让驱动程序分配一个可由 GPU 进行 DMA 处理的内存缓冲区,以获得最佳性能。如果 CPU 和 GPU 在同一上下文中,则可以在两个设备之间共享这些缓冲区。
You still have to split the workload up yourself. My favorite load balancing technique is using events. Every n work items, attach an event object to a command (or enqueue a marker), and wait for the event that you set n workitems ago (the prior one). If you didn't have to wait, then you need to increase n on that device, if you did have to wait, then you should decrease n. This will limit the queue depth, n will hover around the perfect depth to keep the device busy. You need to do it anyway to avoid causing GUI render starvation. Just keep n commands in each command queue (where the CPU and GPU have separate n) and it will divide perfectly.
您不能将内核跨越到多个设备。但是,如果您正在运行的代码不依赖于其他结果(即:处理 16kB 的数据块,需要大量处理),您可以在 GPU 和 CPU 上启动相同的内核。并将一些块放在 GPU 上,一些放在 CPU 上。
这样它应该会提高性能。
您可以这样做,为 CPU 和 GPU 创建一个共享的 clContext,以及 2 个命令队列。
这不适用于所有内核。有时,内核代码适用于所有输入数据,并且无法分成部分或块。