【问题标题】:Performance optimization in CUDA - Which of these algorithms should I use?CUDA 中的性能优化 - 我应该使用哪些算法?
【发布时间】:2012-08-27 08:09:09
【问题描述】:

我有一个包含两个主要任务的算法。这两个任务令人尴尬地并行。所以我可以通过以下方式之一将这个算法移植到CUDA上。

>Kernel<<<
Block,Threads>>>()  \\\For task1  
cudaThreadSynchronize();  
>Kerne2<<<
Block,Threads>>>()  \\\For task2

或者我可以做以下事情。

>Kernel<<<
Block,Threads>>>()  
{  
    1.Threads work on task 1.  
    2.syncronizes across device.  
    3.Start for task 2.  
}

可以注意到,在第一种方法中,我们必须回到 CPU,而在第二种趋势中,我们必须在 CUDA 中的所有块之间使用同步。 IPDPS 10 中的论文说,第二种方法,在适当的照顾下可以表现得更好。但是一般应该遵循哪种方法呢?

【问题讨论】:

  • 我得到的结果支持第一种方法,有时支持第二种方法。文献推荐什么?
  • 在这种情况下,请确保第二种方法很好地跟随纸张,看它是否占据边缘。如果两者仍然相对相同(这是您将使用的真实数据),请保留您想要的任何一个。尽量让您可以随时切换它们,这样您就可以随时进行测试。
  • 你为什么不想使用流呢? Fermi 支持并发内核执行,因此您可以同时启动两个内核(当然,如果它们不相互依赖)。否则,在我看来,块间同步是一件非常讨厌的事情:在您提到的那篇论文中,它仅在线程块到多处理器的一对一映射时才有效。我不会诚实地使用它..
  • 坦率地说,纸上谈兵的想法在现实中是行不通的。在某些情况下,它会花费太多时间,因此驱动程序正在终止内核执行。我想到了流,但在我的情况下,task2 依赖于 task1,所以只有 2 个解决方案..要么回到 CPU,要么设法实现跨块同步(无论如何)。块数较少的情况下块间同步很好,但如果我们有大量块,则不可靠,这很明显,因为块间同步机制中的while循环会消磨时间。
  • 作为一种经典的优化模式,您还可以考虑将数据拆分为在内核调用期间不相互依赖的块。然后可以在单独的流中处理每个块,从而在内核执行中提供一些部分重叠

标签: performance cuda


【解决方案1】:

目前在 CUDA 编程模型中,没有任何官方支持的方法可以通过单个内核执行跨线程块进行同步。以我的经验,这样做的方法会导致代码脆弱,在不断变化的环境下可能会导致不正确的行为,例如在不同的硬件上运行、更改驱动程序和 CUDA 发布版本等。

仅仅因为某些东西在学术出版物上发表并不意味着它是生产代码的安全想法。

我建议你坚持你的方法 1,我问你这个问题:你确定将你的计算分成两个独立的内核真的会导致性能问题吗?第二次内核启动的成本肯定是瓶颈吗?

【讨论】:

  • “你确定将你的计算分成两个独立的内核真的会导致性能问题吗?” --不完全是,但是在我的应用程序中回到 CPU 的想法并不好,我想为一组任务启动 N 个线程并从 CPU 端忘记(以便 CPU 线程可以做一些其他有用的工作)。所以我是想知道是否可以在设备上的所有线程之间进行同步,但如果同步成本很高,那么我必须使用“智能”的东西,这样我的应用程序在执行期间就不需要占用 CPU。
  • at harrism:我已经阅读了您在 GPU gems 3 中关于前缀和的章节,但我还没有看到源代码。在那个实现中,您使用上述哪种方法?
  • 对于您的第一条评论,您可能对即将推出的 Kepler GK110 GPU 中提供的 CUDA 动态并行性感兴趣——它使内核能够启动其他内核(除其他外)。对于您的第二条评论:我总是使用方法 1:在我看来,阻止同步的唯一安全方法是启动另一个内核。
  • GK110有售吗?
  • 还没有。因此“即将”。但是 CUDA 5.0 候选版本已经发布,因此您可以阅读文档...
猜你喜欢
  • 2016-08-04
  • 1970-01-01
  • 2021-08-10
  • 2011-11-05
  • 1970-01-01
  • 1970-01-01
  • 2012-01-31
  • 1970-01-01
  • 2012-10-12
相关资源
最近更新 更多