OpenCL-主内核填充缓冲区并在子内核上运行

OpenCL-主内核填充缓冲区并在子内核上运行,opencl,kernel,Opencl,Kernel,作为OpenCL的新手,我想知道以下场景是否可行 内存中创建了10个长度为10000的缓冲区,或者一个10xN的图像缓冲区作为缓存 第一个内核是填充缓存中的一行,并查询另一个内核对该行执行一些工作。当第二个内核完成时,第一个内核可以计算一个新行并替换旧行,相同的过程将继续,直到第一个内核不再有任务为止 这个场景有意义吗?它可以在GPU编程中实现吗?OpenCL不允许内核调用其他内核。但你有一些选择 让第一个内核调用另一个非内核函数。工作项之间的工作分配在这里不会改变——因此,如果有10个并行工作

作为OpenCL的新手,我想知道以下场景是否可行

内存中创建了10个长度为10000的缓冲区,或者一个10xN的图像缓冲区作为缓存

第一个内核是填充缓存中的一行,并查询另一个内核对该行执行一些工作。当第二个内核完成时,第一个内核可以计算一个新行并替换旧行,相同的过程将继续,直到第一个内核不再有任务为止


这个场景有意义吗?它可以在GPU编程中实现吗?

OpenCL不允许内核调用其他内核。但你有一些选择

  • 让第一个内核调用另一个非内核函数。工作项之间的工作分配在这里不会改变——因此,如果有10个并行工作项(线程)正在执行,每行一个,那么每个线程将在非内核函数中的相同数据上操作

  • 多个内核可以一个接一个地排队,但这是由主机协调的。这确实允许在线程之间重新分配工作,但可能比选项1更复杂

  • 创建快速OpenCL代码的关键之一是将您的工作拆分为多个工作项,通常越多越好。如果填充该行的第一个内核只能拆分为10个工作项,但对该行进行处理的第二个内核可以拆分为1000个工作项,那么您肯定希望使用选项2,因为第二个部分可以在具有大量内核的设备(如现代GPU)上更有效地拆分。少量工作项(如10项)只能使用此可用处理能力的一小部分

    (增补)

    在GPU上执行的OpenCL内核是数据并行的,这意味着一次只能执行一个内核,但每个线程使用不同的数据段。也许有必要重新考虑您的算法以适应此模型

    从您在评论中所写的内容来看,由于内存限制,您似乎希望一次运行10个项目。但是请注意,OpenCL中没有动态内存分配。所有缓冲区都预先声明。因此,主机应该确定可用内存中可以容纳多少任务,并运行工作项的批处理(使用适当的缓冲区传输)


    缓冲区是如何填充的?从档案中?OpenCL内核无法读取文件、网络等。因此,如果原始数据是这样加载的,则必须在主机上执行。但是,如果这些图像缓冲区是从其他源创建的(例如,通过算法或从另一个内存中的源创建的),那么应该可以正常工作(尽管您也需要将任何其他内存中的源复制到GPU)。

    这正是我的情况。上述第一项和第二项任务的工作项比率为1:2000。因此,选项2是我问题的答案。我在示例中提到了10行,因为我需要一些缓冲区来保存第二个任务的数据,如果它刚刚开始执行所有任务,那么内存需求将非常大。因此,如果第一个内核有N个任务,是否可以告诉您,在同一时间只运行10个工作项,并且在第二个任务完成时只继续一个新的工作项?我还考虑将第一个任务保留在主机上,将输入数据写入gpu并将第二个任务排入队列,然后在完成后读取结果并将一组新的输入写入gpu并排入队列再一次。但是如果第一个任务也可以在gpu上完成,我就不需要从主机到gpu写那么多。@s093294不同的gpu硬件将有不同的性能。将第一个任务保留在主机上可能会更快,这取决于将内存从主机复制到设备所需的时间,这取决于设备、主机和需要复制的内存量。您可能希望同时尝试这两种方法,并选择一种最快的硬件。因此,如果第一个内核有N个任务,是否可以告诉它只同时运行10个工作项,并且在第二个任务完成时只继续一个新的工作项?这个工作组有关系吗。如果我将本地大小设置为32,这是否意味着它运行32个线程,并且只有在其他线程完成时才启动一次新线程。然后,我可以添加一个记忆体或者其他东西让它等待第二个任务吗?@s093294为答案添加了更多细节