Просматривая ответы и комментарии на вопросы CUDA и вики-тег CUDA , я вижу, что часто предлагается проверять состояние возврата каждого вызова API на наличие ошибок. Документация по API содержит такие функции, как cudaGetLastError
, cudaPeekAtLastError
и cudaGetErrorString
, но как лучше всего объединить их, чтобы надежно отлавливать и сообщать об ошибках, не требуя большого количества дополнительного кода?
cuda
error-checking
talonmies
источник
источник
getLastCudaError
иcheckCudaErrors
который в значительной степени соответствует описанному в принятом ответе . Смотрите образцы для демонстраций. Просто установите образцы вместе с инструментарием, и он у вас будет.Ответы:
Вероятно, лучший способ проверить наличие ошибок в коде API времени выполнения - это определить функцию-обработчик стиля assert и макрос-обертку следующим образом:
Затем вы можете обернуть каждый вызов API
gpuErrchk
макросом, который обработает возвращаемый статус вызова API, который обертывает, например:Если в вызове произошла ошибка, текстовое сообщение с описанием ошибки, а также файл и строка в вашем коде, где произошла ошибка, будут отправлены,
stderr
и приложение закроется. Вы могли бы, вероятно, изменить,gpuAssert
чтобы вызвать исключение, а не вызыватьexit()
более сложное приложение, если бы это было необходимо.Второй связанный с этим вопрос заключается в том, как проверять наличие ошибок при запуске ядра, которые нельзя напрямую обернуть в вызов макроса, как стандартные вызовы API времени выполнения. Для ядер что-то вроде этого:
сначала проверит неверный аргумент запуска, затем заставит хост ждать, пока ядро не остановится, и проверит наличие ошибки выполнения. Синхронизация может быть устранена, если у вас есть следующий вызов API блокировки, подобный этому:
в этом случае
cudaMemcpy
вызов может вернуть либо ошибки, которые произошли во время выполнения ядра, либо ошибки из самой копии памяти. Это может сбить с толку новичка, и я бы порекомендовал использовать явную синхронизацию после запуска ядра во время отладки, чтобы было легче понять, где могут возникнуть проблемы.Обратите внимание, что при использовании динамического параллелизма CUDA очень похожая методология может и должна применяться к любому использованию API среды выполнения CUDA в ядрах устройств, а также после запуска любого ядра устройства:
источник
cudaDeviceReset()
прежде чем выйти также? И пункт для освобождения памяти?Ответ talonmies выше - отличный способ прервать приложение в
assert
стиле.Иногда мы можем захотеть сообщить и исправить состояние ошибки в контексте C ++ как часть более крупного приложения.
Вот довольно краткий способ сделать это, создав исключение C ++, полученное
std::runtime_error
при использованииthrust::system_error
:Это будет включать имя файла, номер строки и описание на английском языке
cudaError_t
для.what()
члена брошенного исключения :Выход:
При
some_function
желании клиент может отличить ошибки CUDA от других видов ошибок:Поскольку
thrust::system_error
этоstd::runtime_error
, мы можем альтернативно обрабатывать это так же, как и широкий класс ошибок, если нам не требуется точность предыдущего примера:источник
<thrust/system/cuda_error.h>
сейчас эффективно<thrust/system/cuda/error.h>
.C ++ - канонический способ: не проверять на ошибки ... используйте привязки C ++, которые генерируют исключения.
Раньше меня раздражала эта проблема; и я имел обыкновение иметь решение для функции макрокоманды, как в Talonmies и ответах Джареда, но, если честно? Это делает использование CUDA Runtime API еще более уродливым и похожим на C.
Так что я подошел к этому по-другому и более фундаментально. Для примера результата, вот часть
vectorAdd
примера CUDA - с полной проверкой ошибок каждого вызова API времени выполнения:Опять же - все потенциальные ошибки проверены, и исключение, если ошибка произошла (предостережение: если ядро вызвало некоторую ошибку после запуска, оно будет перехвачено после попытки скопировать результат, а не до этого; чтобы убедиться, что ядро было успешным, вы должны необходимо проверить на наличие ошибок между запуском и копией с помощью
cuda::outstanding_error::ensure_none()
команды).Код выше использует мой
Оболочки Thin Modern-C ++ для библиотеки API CUDA Runtime (Github)
Обратите внимание, что после неудачного вызова исключения содержат как строковое объяснение, так и код состояния API среды выполнения CUDA.
Несколько ссылок на то, как ошибки CUDA автоматически проверяются с помощью этих оболочек:
источник
Обсуждаемое здесь решение хорошо сработало для меня. Это решение использует встроенные функции cuda и очень просто в реализации.
Соответствующий код скопирован ниже:
источник