Почему TensorRT enqueueV2 занимает больше времени при использовании более изолированных потоков в C++?

  • ОС: Windows 10
  • CUDA: версия 11.5
  • ТензорРТ: 8.6.1.6
  • OpenCV: 4.8.0, созданный с использованием CUDA.
  • Версия драйвера: Самый последний драйвер (545.84).

В моем приложении будет транслироваться с нескольких камер. Каждая камера будет управляться одним потоком ЦП, и между этими потоками нет никакого совместного использования. Кроме того, каждый поток будет загружать и использовать модель обнаружения объектов, развернутую с помощью TensorRT. Каждый поток будет иметь свою собственную модель, и модели также не будут общими.

Для двух потоков функция TensorRT enqueuev2, которая выполняет процесс вывода модели, занимает в среднем почти 1 миллисекунду, что кажется довольно многообещающим. Для профилирования программы я использую инструмент NVIDIA Nsight System.

Когда я профилирую программу в системе Nsight, на следующем рисунке показан отчет о профилировании.

Как показано на изображении выше, для одного из потоков enqueuev2 потребовалось 238 микросекунд, что кажется хорошим показателем для двух потоков.

Для второго теста я запускаю 20 потоков, но на этот раз постановке в очередь TensorRT потребовалось почти 20 миллисекунд, чтобы вернуть результаты, и это значение продолжает расти по мере увеличения количества потоков. Вы можете увидеть отчет Nishgt System на следующем изображении:

Как показано цветом наклона, enqueuev2 потребовалось 19 миллисекунд, чтобы вернуть результат, который отрицательно влияет на конечный FPS каждого потока.

Я внимательно просмотрел отчеты и увидел некоторые заблокированные состояния, с которыми я не знаком, и думаю, что это узкое место программы, но понятия не имею, как их уменьшить или устранить.

Вот фрагмент кода, который я использовал для процесса вывода:

              auto t1 = std::chrono::high_resolution_clock::now();
        status = mContext->enqueueV2(&mBindingDataHolder[0], *inferenceCudaStream, nullptr);
        CUDA_CHECK(cudaEventRecord(syncEvent, *inferenceCudaStream));
        CUDA_CHECK(cudaEventSynchronize(syncEvent)); 

        auto t2 = std::chrono::high_resolution_clock::now();
        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count();
        spdlog::info("enqueueV2 time: {} ms", duration);

Поскольку ресурсы и потоки изолированы и ничего не совместно используют, я ожидаю, что функция постановки в очередь для каждого потока займет около 1 миллисекунды, как и в первом случае с двумя потоками, но это в 20 раз медленнее.

Буду признателен, если кто-нибудь скажет мне, являются ли эти заблокированные состояния основной причиной проблемы и если да, то как ее можно решить.

0 ответов

Другие вопросы по тегам