我在学校做一个小项目。我已经在 CUDA 中完成了我的代码实现,并使用实际值进行了一些性能测量,即使用不同数量的线程运行程序,改变问题的大小,改变两者等等。
(time, speedup) 的结果看起来非常好。但后来我被要求对算法进行一些理论分析,特别是预测随着线程数量的增加,我的实现运行所需的时间。问题是我收到了一些文档,他们使用“时序图”来尝试对此进行建模,但这种方法适用于使用 MPI 解决的问题,并且我被要求使用完全相同的东西来为 CUDA 创建预测模型。是否有可能做到这一点?
当我增加用于计算的线程数时,如何预测给定的 CUDA 程序(内核)将如何运行?假设我的 GPU 有 240 个 cuda 内核,现在为了简单起见,我认为如果我启动一个带有一个线程的内核,那么内核将只使用 1 个内核,如果我启动 4 个线程,它将使用 4 个内核,上限为240 在这种情况下,当我启动 500 个线程时,使用的内核不会超过 240 个。这很可能在某种程度上是错误的,但这是开始的。
你能给我一些想法来绘制这个预测模型吗?因此,我真的很头疼,我无法得出一个简单的预测模型。
更新
第一个问题是如何在 CUDA 中模拟 GPU 上的顺序运行。如前所述,我所做的是启动一个只有一个块和一个线程的内核,结果是我所期望的,因为事实证明内核运行得更慢。然后增加启动的线程数量减少了运行时间,因此我从 GPU 的并行架构中受益。现在,关键问题是在 CUDA 中启动 K 线程,我可以确定 GPU 中使用的内核数等于 K 线程数吗?不知何故,这是真的,因为我之前说过。
现在继续前进,我必须根据时序图制作一个预测模型。所以首先时序图的草图是

我的图表显示(或至少试图显示)是应用程序运行的关键路径取决于
- 将数据从 CPU 发送到 GPU
- CUDA 初始化和内核启动配置
- 最后一个warp执行的时间
- 将数据从 GPU 发送到 CPU
(1) 和 (4) 的时间可以直接计算:我知道 GPU 通过 PCI-Express 2nd gen 连接到 CPU,并且知道问题的大小,我可以知道传输的实际时间。好的 :)
(2) 的时间取决于硬件,但对于我一直在阅读的内容,大约需要 60 到 65 毫秒。
最后(3)最难预测的部分是计算的实际运行时间(给定线程数的内核运行时间)。我建模的方式是Tprocessing = Tcomputation + Tmemory
Tcomputation :一个线程计算集合中 1 个像素的周期数。这里的关键问题是如何计算周期数?我天真地计算了求和和乘法的数量,然后根据 GPU 的架构将其乘以它们每个所花费的周期。我对此完全不确定。
Tmemory :一个线程进入全局内存进行读/写所需的周期数。从各种参考资料(包括 GPU 上的 Udacity 课程)来看,平均 500 个周期没有。
然后我们知道 GPU 时钟的工作频率,并将所有我得到的程序运行时间的上限相加。
所以基本上一切都基于这样的想法:如果我运行一个线程,则只使用一个 CUDA 核心,如果我运行十个线程,则使用十个 CUDA 核心。然后我可以预测如果我们有一个具有 2048 个 CUDA 核心的 GPU 作为 GTX Titan 会发生什么。
我用 Mandelbrot Set 测试了我的模型,而且我的时间比实际的要大得多,所以缺少一些东西。