同时在所有 GPU 内核上为每个 GPU 内核运行一个程序实例

Posted

技术标签:

【中文标题】同时在所有 GPU 内核上为每个 GPU 内核运行一个程序实例【英文标题】:Running one instance of a program per GPU-core on all GPU-cores simultaneously 【发布时间】:2019-08-01 02:51:26 【问题描述】:

我们有数以百万计的小文件要由某些程序处理。

精确的程序并不重要,随着精确的任务而变化。然而,这些都是较小的 C++ 程序,我们有源代码,但它们本质上不是可并行化的。

使用单个平均 CPU 内核(Intel i7 系列)时,处理一个小文件大约需要 15 秒。在程序运行时,它需要大约 200 MB 的 RAM。

我们希望在 GPU 上并行化,并在每个 GPU 核心(例如 Cuda 核心)上运行一个程序实例。因此,如果 GPU 有 3000 个 CUDA 核心,那么我们希望并行运行 3000 个实例。如果可能,我们希望使用像 OpenCL 这样的通用框架(而不是 Cuda,但如果这种情况需要 Cuda,那将是可以接受的)。

现在我们正在尝试评估这是否可行(我们在 GPGPU 编程方面还没有太多经验)。我们想象的主要问题是内存。如果我们并行运行 3000 个实例,每个实例需要 200 MB VRAM,那么我们将需要 600 GB 内存。

我们主要想到的显卡是高端 Geforce 卡,通常有 8 GB 到 11 GB 的内存。我们有 GPU 工作站,每个机箱/主板有 4 张卡,我们一开始希望将其用于此目的(但后来可能也用于其他 GPU 系统,因此我们更喜欢像 OpenCL 这样的通用框架)。

有哪些方法可以解决这个问题?

【问题讨论】:

在 3-5 个实例之后,内存带宽/延迟不会成为瓶颈吗?您将需要内核内部的伪malloc,以便它仅从已经cuda-malloced的全局缓冲区中为所有请求线程(当时)返回一个“合并的”地址组。如果实例没有以某种方式进行排序以减少它们之间的分支,即使这也可能不起作用。更好的方法是并行化你的算法,只运行足够的实例来重叠数据传输、文件读取和计算。 GPU 无法提供您建议的粒度级别,因此您不能这样做。 @huseyintugrulbuyukisik,感谢您的评论。我无法回答你的问题,但其他人可能会。 @talonmies:如果你的意思是粒度一种以我们想要的方式执行并行化的机制,如果这里没有可以支持我们的模块/包,我们可以自己编写这样的代码。问题是,它是否可行,即内存问题是否可以解决。 您无法在单个 GPU 内核上运行完整的程序。最接近完全支持一个或多个执行线程的是 CUDA GPU SM,而不是核心。 【参考方案1】:

精确的程序并不重要

这是一厢情愿。您要解决的问题非常很重要;如果它像将 C++ 代码重新编译为 GPU 着色器二进制文件一样简单,那么几乎所有软件都会这样做以免费提高速度。

您通常无法将整个 C++ 程序 1:1 转换为 GPU 内核,即使您设法做到了,它的性能也会非常糟糕。您确实需要努力从 SIMD 类型的操作角度重新考虑您的问题,以便在 GPU 上取得任何进展。

特别是,您似乎认为每个 GPU“核心”都是独立的。情况并非如此,它们中的一些组步调一致地工作,因此如果您的代码是分支繁重的,那么您的利用率将非常低。它们还共享内存总线,因此如果每个线程访问不相关的内存区域,这将大大减慢执行速度,并且您将无法足够快地为 ALU/FPU 提供数据。

内存也是一个问题,但不仅仅是因为您指出的 VRAM 总量,还因为局部变量使用“私有”内存,这实际上是寄存器,并且是非常有限的资源(测量最多以千字节为单位)。

我建议查看所有主要 GPU 供应商发布的 OpenCL 优化指南。这将使您很好地了解哪些代码执行得好,哪些代码执行得不好,以及在决定将哪些代码卸载到 GPU 以及如何卸载时需要考虑哪些因素。

【讨论】:

非常感谢您的回答,非常有帮助。我已根据您的信息更正了我上面的问题(即划掉了程序不重要的声明)。关于您的陈述“如果它是......几乎所有软件都会这样做以免费提高速度”,也许应该在这里添加所有具有大量独立任务要执行的软件都可以做到这一点,但这大多数软件都不是这样。 @Jadzia 许多软件都可以适应 GPU 加速。但是,生成的代码通常看起来与原始代码完全不同,并且在许多情况下,必须从根本上重新考虑算法。因此,我不确定您的“大多数软件”声明;可能是大多数软件,但可能不是大多数受 CPU 限制的软件。 (你没有提供足够的细节来说明你正在做什么,我无法说明这是否适用于你的软件。即使是一些传统的串行工作负载,如压缩,如果给予足够的考虑,也经常可以从 GPU 加速中受益。)跨度>

以上是关于同时在所有 GPU 内核上为每个 GPU 内核运行一个程序实例的主要内容,如果未能解决你的问题,请参考以下文章

如何查找 Google COLAB GPU 中的内核数?

在 GPU 上运行操作系统内核级计算是不是有意义?

OpenCL 内核在 Nvidia GPU 上每个线程使用多少寄存器?

Cuda 内核代码驻留在英伟达 GPU 上的啥位置?

用GPU加速Linux Kernel?

为啥允许我运行块数超过 GPU 的 CUDA 核心数的 CUDA 内核?