4

我的任务是查看我开发的算法是否可以使用 GPU 而不是 CPU 上的计算更快地运行。我是加速器计算的新手,我得到了一本我已经彻底阅读过的书“C++ AMP”,我认为我对它的理解相当好(我过去用 C 和 C++ 编写过代码,但现在主要是 C#)。

但是,当进入实际应用程序时,我似乎只是不明白。所以,如果可以的话,请帮助我。

假设我有一个任务来计算一些复杂的函数,该函数需要一个巨大的矩阵输入(如 50000 x 50000)和一些其他数据并输出相同大小的矩阵。整个矩阵的总计算需要几个小时。

在 CPU 上,我只是将任务分成几部分(部分数量大约为 100 左右)并使用 Parralel.For 执行它们,或者只是我自己编写的一个简单的任务管理循环。基本上,保持几个线程运行(线程数 = 内核数),当线程完成时开始新的部分,直到所有部分都完成。而且效果很好!

但是,在 GPU 上,我不能使用相同的方法,不仅因为内存限制(没关系,可以分成几个部分),而且因为如果某些东西运行超过 2 秒,它被认为是“超时”并且 GPU 得到重置!因此,我必须确保我的计算的每个部分运行时间少于 2 秒。

但这并不是每个任务(例如,将一个小时的工作分成 60 个任务,每个任务 1 秒),这很容易,这就是每组任务,因为无论我选择哪种队列模式(立即或自动),如果我运行(通过 parralel_for_each)任何总共需要超过 2 秒才能执行的东西,GPU 将被重置。

不仅如此,如果我的 CPU 程序占用了所有 CPU 资源,只要它保持较低的优先级,UI 就会保持交互 - 系统是响应式的,但是,当在 GPU 上执行代码时,屏幕似乎被冻结,直到执行完成!

那么,我该怎么办?在本书的演示(N-Body 问题)中,它表明它的效率应该是 100 倍(多核计算给出 2 gflops,或者 w/e 的 flops 数量,而 amp 给出 200 gflops),但是在实际应用中,我只是不知道该怎么做!

我是否必须将我的大任务划分为数十亿个部分,例如,划分为每个需要 10 毫秒才能执行的部分,并一次在 parralel_for_each 中运行 100 个?

还是我只是做错了,而我没有得到更好的解决方案?

请帮忙!

4

1 回答 1

0

TDR(您看到的 2 秒超时)是使用在渲染显示和执行计算工作之间共享的资源的现实。操作系统通过强制超时来保护您的应用程序免于完全锁定显示。这也会影响尝试渲染到屏幕的应用程序。将您的 AMP 代码移至单独的 CPU 线程将无济于事,这将释放 CPU 上的 UI 线程,但渲染仍会在 GPU 上被阻止。

当您在低功耗系统上将 N 设置为非常大时,您实际上可以在 n-body 示例中看到这种行为。N的最大值实际上在应用程序中是有限的,以防止您在典型场景中遇到这些类型的问题。

你实际上是在正确的轨道上。如果您想达到特定的帧速率,您确实需要将您的工作分成适合低于 2s 的块或更小的块。您还应该考虑您的工作是如何排队的。请记住,所有 AMP 工作都是排队的,在自动模式下,您无法控制它何时运行。使用立即模式可以更好地控制命令的批处理方式。

注意:TDR 在专用计算 GPU 硬件(如 Tesla)上不是问题,如果底层 GPU 支持,Windows 8 在处理 TDR 超时限制时提供更大的灵活性。

于 2013-11-06T01:49:45.263 回答