我再次继承了看起来可疑的代码;基本上就是这样:
(void) nppiFilter...(...);
cudaError_t err = cudaGetLastError();
if (err != cudaSuccess)
{
std::cerr << cudaGetErrorString(err);
}
我们忽略了NPP错误,而是检查了CUDA错误。
首先,NPP是否设置了错误的CUDA错误标志?我很确定答案是&#34;没有明确&#34;所以此代码将错过仅NPP错误,但我想检查。
其次,是否有必要检查这两个错误,或者这样就足够了:
NppStatus nppErr = nppiFilter...(...);
if (nppErr != NPP_NO_ERROR)
{
std::cerr << "NPP error " << nppErr;
}
或者我应该检查两种以防万一?有一个NPP_CUDA_KERNEL_EXECUTION_ERROR
告诉我,检查cudaGetLastError()
可能会有用,但是它是吗?
答案 0 :(得分:3)
首先,NPP是否设置了错误的CUDA错误标志?
不,它没有。 CUDA错误状态可能由NPP完成,但NPP没有专门设置CUDA错误状态。
或者我应该检查两种以防万一?
仅检查NPP状态就足够了。但是,如果要进行其他调试分析,则还可以检查CUDA错误状态。事实上,当我寻找其他线索时,我经常会cuda-memcheck
运行。唯一正常的价值是提供“额外的线索”。
一个安全的假设是许多CUDA库可能具有异步启动工作的功能。即:即使在函数已将控制权返回给CPU线程之后,仍可能发生基础GPU活动。在这种情况下,期望一个设计良好的库将在“稍后”,当您执行后续库调用或CUDA API调用(可能从设备到主机检索计算数据)时捕获由于异步活动引起的错误。 / p>
在这种情况下,无论如何都无法依赖函数返回值。因此,在整个程序中仔细检查错误是最安全的选择,这包括库API级别(例如NPP)以及CUDA API级别。但出于生产目的,我只是在每个机会进行测试,不一定建议您插入额外的检查,例如:
error = cudaGetLastError();
(除非它紧跟CUDA API调用,这是你的策略**)
我也不建议任意插入:
error = cudaDeviceSynchronize();
但是,如果您设计库,您可能希望在函数入口处对上述类型进行某种显式错误检查。
这显然是某种程度上的意见问题。您可能希望将错误检查置于极端水平。它不会对您的程序产生太大影响,只要您不插入同步调用来检查错误。
我上面的评论主要涉及我如何编写生产代码。出于学习目的,或者在您编写代码时遇到问题,通常最好成为very rigorous about error checking,并确实插入额外的错误检查以捕获异步错误,以便将错误定位到特定函数
**您可能希望插入:
error = cudaGetLastError();
每次内核调用后,在您的代码中。这将捕获在启动时可检测到的任何内核错误,例如不正确的网格尺寸。这种类型的调用应该相对轻量级。