Проверка ошибок АЭС и CUDA
Я снова унаследовал код, который выглядит подозрительно; это в основном это:
(void) nppiFilter...(...);
cudaError_t err = cudaGetLastError();
if (err != cudaSuccess)
{
std::cerr << cudaGetErrorString(err);
}
Мы игнорируем ошибку NPP, но вместо этого проверяем ошибку CUDA.
Во-первых, устанавливает ли NPP флаг ошибки CUDA на ошибку? Я почти уверен, что ответ "не явно", поэтому в этом коде будут пропущены только ошибки NPP, но я хочу проверить.
Во-вторых, необходимо проверить обе ошибки или этого будет достаточно:
NppStatus nppErr = nppiFilter...(...);
if (nppErr != NPP_NO_ERROR)
{
std::cerr << "NPP error " << nppErr;
}
Или я должен проверить оба на всякий случай? E сть NPP_CUDA_KERNEL_EXECUTION_ERROR
который предлагает мне, что, возможно, проверка cudaGetLastError()
было бы полезно, но так ли это?
1 ответ
Во-первых, устанавливает ли NPP флаг ошибки CUDA на ошибку?
Нет. Состояние ошибки CUDA может быть установлено чем-то скрытым, выполняемым NPP, но NPP специально не устанавливает состояние ошибки CUDA.
Или я должен проверить оба на всякий случай?
Достаточно просто проверить статус АЭС. Однако, если вы хотите выполнить дополнительный анализ отладки, может быть полезно также проверить состояние ошибки CUDA. На самом деле я часто бегаю cuda-memcheck
когда я ищу дополнительные подсказки. Единственное нормальное значение, которое это имело бы, должно предоставить "дополнительные подсказки".
Безопасное предположение состоит в том, что многие библиотеки CUDA могут иметь функции, которые запускают работу асинхронно. То есть: основная активность GPU может все еще происходить даже после того, как функция вернула управление потоку ЦП. В таких случаях ожидается, что хорошо спроектированная библиотека будет перехватывать ошибки из-за асинхронной активности "позже", когда вы делаете последующий вызов библиотеки или вызов API CUDA (возможно, для получения рассчитанных данных с устройства на хост).
В таких случаях вы не сможете полагаться на возвращаемое значение функции в любом случае. Поэтому самая надежная ставка - это тщательная проверка ошибок в вашей программе, которая включает как уровень API библиотеки (например, NPP), так и уровень API CUDA. Но для производственных целей я просто проверял бы при каждой возможности, не обязательно предлагая вставить дополнительные проверки, такие как:
error = cudaGetLastError();
(если это не следует сразу за вызовом API CUDA и это ваша стратегия **)
и при этом я не предложил бы произвольно вставить:
error = cudaDeviceSynchronize();
Однако, если вы проектировали библиотеку, вы могли бы хотеть иметь какую-то явную проверку ошибок вышеуказанного типа при входе в ваши функции.
Это, очевидно, вопрос мнения в некоторой степени. Возможно, вы захотите довести проверку ошибок до крайнего уровня. Это не должно сильно влиять на вашу программу, если вы не вставляете синхронизирующие вызовы для проверки ошибок.
Мои комментарии выше в основном касаются того, как я написал бы производственный код. В целях обучения или в любое время, когда у вас возникают проблемы с кодом, который вы пишете, обычно рекомендуется очень строго относиться к проверке ошибок и даже вставлять дополнительную проверку ошибок, чтобы перехватывать асинхронные ошибки для локализации ошибки в определенной функции.,
** Вы можете добавить:
error = cudaGetLastError();
после каждого вызова ядра, в вашем коде. Это отлавливает любые ошибки ядра, которые можно обнаружить во время запуска, например, неверные размеры сетки. Этот тип звонка должен быть относительно легким.