在CUDA内核中放置一个for循环

时间:2011-08-11 10:55:17

标签: c++ c cuda

在内核中放置for循环是个坏主意吗? 或者这是常见的事情吗?

4 个答案:

答案 0 :(得分:7)

将循环放入内核中是很常见的。这并不意味着它总是一个好主意,但它并不意味着它也不是。

确定如何有效地分配任务和数据并利用相关并行性的一般问题是一个非常困难且未解决的问题,尤其是涉及到CUDA时。正在进行积极的研究以有效地确定(即,不盲目地探索参数空间)如何为给定的内核实现最佳结果。

有时,将循环放入内核会很有意义。例如,对表现出强数据独立性的大型常规数据结构的许多元素的迭代计算非常适合于包含循环的内核。其他时候,您可以决定让每个线程处理许多数据点,例如,你没有足够的共享内存来为每个任务分配一个线程(当大量线程共享大量数据时这种情况并不少见,并且通过增加每个线程完成的工作量,你可以适应所有线程'在共享内存中共享数据。)

您最好的选择是根据需要进行有根据的猜测,测试,简介和修改。有很多空间可以使用优化...启动参数,全局与常量与共享内存,保持寄存器数量冷却,确保合并并避免内存库冲突等。如果您对性能感兴趣,你应该在CUDA 4.0文档页面上查看NVIDIA提供的“CUDA C最佳实践”和“CUDA占用计算器”(如果你还没有)。

答案 1 :(得分:4)

通常可以如果你对你的内存访问模式非常小心。如果for循环将随机访问内存,导致许多未合并的内存读取,则可能非常慢。

事实上,我曾经用CUDA运行一段代码,因为我天真地在内核中插入了一个for循环。但是,一旦我考虑了内存访问,例如通过一次将一个块加载到共享中,这样每个线程块可以同时从共享中执行for循环的一部分,它会更快。

答案 2 :(得分:1)

  • 处理大数据的基本模式是使用切片方法,其中输入数据被拆分并且每个线程在其数据块上工作,其中确定需要循环。
    示例1:如果输入数据是2D Matrix已知其行数超过其列数我将使用唯一网格块索引访问该行并使用平铺线程索引方法访问该列在瓷砖尺寸上循环。
    示例2:如果您的线程需要处理进一步计算所需的单个值。 (矢量规范化作为示例)您需要一个tile方法,因为只有块内线程才能有效地同步。

答案 3 :(得分:0)

只要它不在顶级,你应该可以。在顶层这样做会否定CUDA的所有优点。

正如Dan指出的那样,内存访问成为一个问题。解决此问题的一种方法是将引用的内存加载到共享内存或纹理内存中(如果它不适合共享)。原因是未合并的全局内存访问速度非常慢(约400个时钟周期,而不是共享内存的40个)。