0

抱歉标题含糊。

我编写了一个内核来模拟 3D 热传递。我遇到的问题是在 8 核 Dell Studio XPS 上并行运行的程序版本超过了我的 GTS-240 GPU。我尝试了很多方法来让它运行得更快,但我得出的结论是,只是计算本身太大了。计算大约有 35 个 FLOP,我只是为模拟中的每个单元启动一个线程。尽管如此,我在 GPU 上只能获得大约 3340 万个单元/秒,而在 CPU 上只能获得 4040 万个/秒。据我了解,GPU 擅长于这样的任务,每个时间步有 170 万个单元,每个单元都需要对它们进行计算。

每次计算我也有 28 个数组访问,都在普通的 GPU 内存中。

这是计算。我不会发布真实的东西——这不是最高机密,只是没有必要。以“f”为前缀的变量是浮点数,“i”表示整数。

f_celldata[iA] =(-f_constA[iA-iB] * (f_mutA[iA] - f_mutA[iA-iB]) / f_constB[iA-1] + 
                  f_constA[iA]    * (f_mutA[iA+iB] - f_mutA[iA]) / f_constB[iA]) * (1.0 / f_constB[iA]) + 
                 (-f_constA[iA-iC] * (f_mutA[iA] - f_mutA[iA-iC]) / f_constB[iA-1] + 
                   f_mutA[iA] * (f_constA[iA+*iC] - kern_T_mat[linOffset]) / kern_dy_e[y]) * (1.0  /kern_dy_c[y]) + 
                  (-f_constA[iA-1] * (f_mutA[iA] - f_mutA[iA-1]) / f_constB[iA-1] + 
                    f_constA[iA] * (f_mutA[iA+1] - f_mutA[iA]) / f_constB[iA]) * (1.0 / f_constB[iA]);

显然,当我在这里写下这篇文章时,我有点草率。实际上,计算尽可能简单,还有更多变量,在这里,为了简单起见,我做了同样的计算。

我希望在 GPU 编程方面比我更有经验的人能给我一些建议。计算量是否太大而无法使用 GPU 进行?单独的单个计算(数组访问和 FLOP 一起)每个时间步需要 35 毫秒。这或多或少是典型的吗?我真的不明白我怎样才能让它更快。特斯拉的工作会更快吗?大约快多少?

谢谢你。

4

4 回答 4

2

不,GPU 在进行更大计算的能力方面不受限制。

没有看到实际代码很难确定。您提供的示例唯一明显错误的是 1.0/x 部分。“1.0”是双精度,NVIDIA GPU的双精度浮点性能远低于单精度。此外,它甚至不应该在您的 GTS 240 上编译,因为它是计算能力 1.1,并且根本不支持双精度。

无论如何,您看到的性能几乎可以肯定是由于全局内存瓶颈。200 系列没有强大的缓存功能,您必须采取特殊措施来优化内存访问。(这部分适用于较新的 GPU,但程度较小。)您需要了解代码的内存访问模式并尽量减少全局内存访问。

于 2012-06-08T23:23:47.040 回答
0

GPU上有一个内存层次结构。您希望确保您的内存访问尽可能快,因为您的 IO 带宽似乎是瓶颈。

您可能希望研究纹理内存以改进空间局部性和缓存。

在此处输入图像描述

于 2012-06-08T20:04:00.767 回答
0

费米记忆架构

作为@tskuzzy 发布的内存图的替代方案,我从 Nsight 分析器中获取了它。它显示了 Fermi 上的内存架构的概述,包括哪些内存空间支持每种类型的指令(最接近内核的行)。

于 2012-06-08T21:48:39.953 回答
0

GPU 在某些事情上做得非常好,而在某些事情上做得非常糟糕。诀窍是编写代码以利用他们做得好的地方,并尽可能少地做他们做得不好的事情。

我怀疑,但由于您没有提供任何代码,因此无法判断您的瓶颈与 GPU 进行计算的速度无关。它将是以下之一:

  • 您将大部分时间花费在将数据移入/移出 GPU 上。
    • 即您的内核很简单,几乎不需要时间来执行,但是加载源数据并返回结果需要时间。
    • GPU 喜欢在单个数据集上完成大量工作。
  • 您正在使 GPU 与 CPU 同步工作,而您的 CPU 受限。
    • 如果你有一个 CPU 循环等待 GPU 完成,准备下一组工作,然后再次启动 GPU,那么很容易在 CPU 上遇到瓶颈。最好利用 GPU 正在工作的时间为 GPU 准备下一组工作,而不是仅仅等待。
  • 您没有要求足够的并行线程来完成这项工作。
    • GPU 速度很快,因为它可以运行数百个线程。不是因为一个线程很快(不是)。
    • 如果你不能利用这一点,那就没有意义了。
  • 您正在使用慢速类型的内存来存储变量。
    • GPU 具有各种内存类型,这些内存类型具有不同的访问速度。小型、本地和快速;大型、全球性但缓慢。
    • 经常访问的变量希望尽可能快地存储在内存中。

可能令人惊讶的是,它不太可能是内核,而是会显示很多问题的主机代码,并且代码确实很重要。

于 2012-06-09T17:34:03.200 回答