我正在尝试为我的应用程序find线程和块的最佳值。 因此,我写了一个小套装来运行线程数,块大小和网格大小的可能组合。 我正在使用的任务不是可并行化的,所以每个线程都在计算其独特的问题,并且需要读取和写入访问全局内存的唯一块。 我还必须增加cudaLimitStackSize才能运行我的内核。 当我尝试计算一次可以运行的最大线程数时,我遇到了问题。 我精致的方法(感谢罗伯特克罗维拉)是
threads = (freememory*0.9)/memoryperthread
从cudaMemGetInfo
, memoryperthread
是一个线程的全局内存需求。 即使我减less了常数因子,我仍然遇到“未指定的启动失败”,我无法debugging,因为debugging程序失败, Error: Internal error reported by CUDA debugger API (error=1). The application cannot be further debugged.
Error: Internal error reported by CUDA debugger API (error=1). The application cannot be further debugged.
。 根据设置这个错误,我也遇到了一个问题,当我尝试不同的块大小。 大于512个线程的块大小会产生“请求启动的资源太多”。 正如Robert Crovella指出的那样,这可能是我的内核占用了许多寄存器的问题(63由-Xptxas =“ – v”报告)。 由于块可以分布在多个multiProcessorCount中,所以我安全地找不到任何突然遇到块大小为1024的限制。
我的代码运行良好的线程和块的小值,但我似乎无法计算我可以在同一时间运行的最大数量。 有没有什么办法来正确计算这些或我需要做到经验?
我知道内存繁重的任务不是CUDA的最佳select。 我的设备是具有计算能力2.0的GTX480。 现在我坚持使用CUDA Driver Version = 6.5, CUDA Runtime Version = 5.0
。 我使用-gencode arch=compute_20,code=sm_20
编译Compute Capability。
更新: 在将运行时更新到6.5之后,上述大多数问题都消失了 。 我会以这种方式离开这个post,因为我提到了我遇到的错误,当search错误时,人们可能会偶然发现错误。 为了解决大块的问题,我不得不减less每个线程的寄存器(-maxrregcount)。
threads = totalmemory / memoryperthread
如果您对memoryperthread
的计算是准确的,则这将不起作用,因为totalmemory
通常不可用。 由于CUDA运行时间开销,分配粒度和其他因素,您实际可以分配的数量少于此数。 所以这会以某种方式失败,但是由于你没有提供任何代码,所以不可能说明如何。 如果你正在做主机的所有这些分配,例如通过cudaMalloc
,那么我预计会出现一个错误,而不是内核未指定的启动失败。 但是,如果您正在执行in-kernel malloc
或new
,那么您可能会尝试使用返回的空指针(表示分配失败 – 即内存不足),这可能会导致未指定的启动失败。
具有大于512个线程的块大小会产生“请求启动的太多资源”。
这可能是你没有为cc2.0设备编译的事实,或者你的内核每个线程使用的寄存器比可以支持的更多。 无论如何,这当然是一个可以解决的问题。
那么如何正确计算内核的最大可能线程和块?
通常,全局内存需求是问题的函数,而不是内核大小。 如果您的全局内存要求随着内核大小而扩大,那么可能会有一些比例可以根据cudaMemGetInfo
报告的“可用内存”(例如90%)来确定,这样可以提供合理的安全操作。 但总的来说,如果一个程序能够容忍分配失败,那么这个程序设计得很好,而且至少应该在主机代码和设备代码上明确地检查这些程序,而不是依赖于“未指定的启动失败”来告诉你某些事情已经消失错误。 这可能是由内存使用引发的任何类型的副作用错误,可能不是直接由于分配失败。
我会建议追查这些问题。 调试问题,找到问题的根源。 我认为正确的解决方案将会呈现出来。