Skip to content

Commit c5659f5

Browse files
committed
[video][cuda][beta] decoder nvtx annotations
1 parent 99e0f4b commit c5659f5

2 files changed

Lines changed: 53 additions & 0 deletions

File tree

src/torchcodec/_core/BetaCudaDeviceInterface.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ extern "C" {
2626
#include <libavutil/pixdesc.h>
2727
}
2828

29+
#ifdef USE_NVTX
30+
#include "nvtx3/nvtx3.hpp"
31+
32+
#define NVTX_SCOPED_RANGE(NAME) nvtx3::scoped_range NVTX_RANGE_##__LINE__{NAME};
33+
#else
34+
#define NVTX_SCOPED_RANGE(NAME) ((void)0)
35+
#endif
36+
2937
namespace facebook::torchcodec {
3038

3139
namespace {
@@ -95,6 +103,7 @@ pfnDisplayPictureCallback(void* pUserData, CUVIDPARSERDISPINFO* dispInfo) {
95103
}
96104

97105
static UniqueCUvideodecoder createDecoder(CUVIDEOFORMAT* videoFormat) {
106+
NVTX_SCOPED_RANGE("createDecoder");
98107
// Decoder creation parameters, most are taken from DALI
99108
CUVIDDECODECREATEINFO decoderParams = {};
100109
decoderParams.bitDepthMinus8 = videoFormat->bit_depth_luma_minus8;
@@ -197,6 +206,7 @@ std::optional<cudaVideoCodec> validateCodecSupport(AVCodecID codecId) {
197206
bool nativeNVDECSupport(
198207
const torch::Device& device,
199208
const SharedAVCodecContext& codecContext) {
209+
NVTX_SCOPED_RANGE("nativeNVDECSupport");
200210
// Return true iff the input video stream is supported by our NVDEC
201211
// implementation.
202212

@@ -267,6 +277,7 @@ void cudaBufferFreeCallback(void* opaque, [[maybe_unused]] uint8_t* data) {
267277

268278
BetaCudaDeviceInterface::BetaCudaDeviceInterface(const torch::Device& device)
269279
: DeviceInterface(device) {
280+
NVTX_SCOPED_RANGE("BetaCudaDeviceInterface::BetaCudaDeviceInterface");
270281
STD_TORCH_CHECK(g_cuda_beta, "BetaCudaDeviceInterface was not registered!");
271282
STD_TORCH_CHECK(
272283
device_.type() == torch::kCUDA, "Unsupported device: ", device_.str());
@@ -278,7 +289,9 @@ BetaCudaDeviceInterface::BetaCudaDeviceInterface(const torch::Device& device)
278289
}
279290

280291
BetaCudaDeviceInterface::~BetaCudaDeviceInterface() {
292+
NVTX_SCOPED_RANGE("BetaCudaDeviceInterface::~BetaCudaDeviceInterface");
281293
if (decoder_) {
294+
NVTX_SCOPED_RANGE("BetaCudaDeviceInterface::~returnDecoder");
282295
// DALI doesn't seem to do any particular cleanup of the decoder before
283296
// sending it to the cache, so we probably don't need to do anything either.
284297
// Just to be safe, we flush.
@@ -291,6 +304,7 @@ BetaCudaDeviceInterface::~BetaCudaDeviceInterface() {
291304
}
292305

293306
if (videoParser_) {
307+
NVTX_SCOPED_RANGE("BetaCudaDeviceInterface::~cuvidDestroyVideoParser");
294308
cuvidDestroyVideoParser(videoParser_);
295309
videoParser_ = nullptr;
296310
}
@@ -303,6 +317,7 @@ void BetaCudaDeviceInterface::initialize(
303317
const UniqueDecodingAVFormatContext& avFormatCtx,
304318
[[maybe_unused]] const SharedAVCodecContext& codecContext) {
305319
if (!nvcuvidAvailable_ || !nativeNVDECSupport(device_, codecContext)) {
320+
NVTX_SCOPED_RANGE("BetaCudaDeviceInterface::cpu_initialize");
306321
cpuFallback_ = createDeviceInterface(torch::kCPU);
307322
STD_TORCH_CHECK(
308323
cpuFallback_ != nullptr, "Failed to create CPU device interface");
@@ -314,6 +329,7 @@ void BetaCudaDeviceInterface::initialize(
314329
// We'll always use the CPU fallback from now on, so we can return early.
315330
return;
316331
}
332+
NVTX_SCOPED_RANGE("BetaCudaDeviceInterface::gpu_initialize");
317333

318334
STD_TORCH_CHECK(avStream != nullptr, "AVStream cannot be null");
319335
timeBase_ = avStream->time_base;
@@ -348,6 +364,7 @@ void BetaCudaDeviceInterface::initialize(
348364
void BetaCudaDeviceInterface::initializeBSF(
349365
const AVCodecParameters* codecPar,
350366
const UniqueDecodingAVFormatContext& avFormatCtx) {
367+
NVTX_SCOPED_RANGE("BetaCudaDeviceInterface::initializeBSF");
351368
// Setup bit stream filters (BSF):
352369
// https://ffmpeg.org/doxygen/7.0/group__lavc__bsf.html
353370
// This is only needed for some formats, like H264 or HEVC.
@@ -439,6 +456,7 @@ void BetaCudaDeviceInterface::initializeBSF(
439456
// we should handle the case of multiple calls. Probably need to flush buffers,
440457
// etc.
441458
int BetaCudaDeviceInterface::streamPropertyChange(CUVIDEOFORMAT* videoFormat) {
459+
NVTX_SCOPED_RANGE("BetaCudaDeviceInterface::streamPropertyChange");
442460
STD_TORCH_CHECK(videoFormat != nullptr, "Invalid video format");
443461

444462
videoFormat_ = *videoFormat;
@@ -470,6 +488,7 @@ int BetaCudaDeviceInterface::streamPropertyChange(CUVIDEOFORMAT* videoFormat) {
470488
// Moral equivalent of avcodec_send_packet(). Here, we pass the AVPacket down to
471489
// the NVCUVID parser.
472490
int BetaCudaDeviceInterface::sendPacket(ReferenceAVPacket& packet) {
491+
NVTX_SCOPED_RANGE("BetaCudaDeviceInterface::sendPacket");
473492
if (cpuFallback_) {
474493
return cpuFallback_->sendPacket(packet);
475494
}
@@ -497,6 +516,7 @@ int BetaCudaDeviceInterface::sendPacket(ReferenceAVPacket& packet) {
497516
}
498517

499518
int BetaCudaDeviceInterface::sendEOFPacket() {
519+
NVTX_SCOPED_RANGE("BetaCudaDeviceInterface::sendEOFPacket");
500520
if (cpuFallback_) {
501521
return cpuFallback_->sendEOFPacket();
502522
}
@@ -510,13 +530,15 @@ int BetaCudaDeviceInterface::sendEOFPacket() {
510530

511531
int BetaCudaDeviceInterface::sendCuvidPacket(
512532
CUVIDSOURCEDATAPACKET& cuvidPacket) {
533+
NVTX_SCOPED_RANGE("BetaCudaDeviceInterface::sendCuvidPacket");
513534
CUresult result = cuvidParseVideoData(videoParser_, &cuvidPacket);
514535
return result == CUDA_SUCCESS ? AVSUCCESS : AVERROR_EXTERNAL;
515536
}
516537

517538
ReferenceAVPacket& BetaCudaDeviceInterface::applyBSF(
518539
ReferenceAVPacket& packet,
519540
ReferenceAVPacket& filteredPacket) {
541+
NVTX_SCOPED_RANGE("BetaCudaDeviceInterface::applyBSF");
520542
if (!bitstreamFilter_) {
521543
return packet;
522544
}
@@ -545,6 +567,7 @@ ReferenceAVPacket& BetaCudaDeviceInterface::applyBSF(
545567
// given frame. It means we can send that frame to be decoded by the hardware
546568
// NVDEC decoder by calling cuvidDecodePicture which is non-blocking.
547569
int BetaCudaDeviceInterface::frameReadyForDecoding(CUVIDPICPARAMS* picParams) {
570+
NVTX_SCOPED_RANGE("BetaCudaDeviceInterface::frameReadyForDecoding");
548571
STD_TORCH_CHECK(picParams != nullptr, "Invalid picture parameters");
549572
STD_TORCH_CHECK(decoder_, "Decoder not initialized before picture decode");
550573
// Send frame to be decoded by NVDEC - non-blocking call.
@@ -556,12 +579,14 @@ int BetaCudaDeviceInterface::frameReadyForDecoding(CUVIDPICPARAMS* picParams) {
556579

557580
int BetaCudaDeviceInterface::frameReadyInDisplayOrder(
558581
CUVIDPARSERDISPINFO* dispInfo) {
582+
NVTX_SCOPED_RANGE("BetaCudaDeviceInterface::frameReadyInDisplayOrder");
559583
readyFrames_.push(*dispInfo);
560584
return 1; // success
561585
}
562586

563587
// Moral equivalent of avcodec_receive_frame().
564588
int BetaCudaDeviceInterface::receiveFrame(UniqueAVFrame& avFrame) {
589+
NVTX_SCOPED_RANGE("BetaCudaDeviceInterface::receiveFrame");
565590
if (cpuFallback_) {
566591
return cpuFallback_->receiveFrame(avFrame);
567592
}
@@ -618,6 +643,7 @@ int BetaCudaDeviceInterface::receiveFrame(UniqueAVFrame& avFrame) {
618643
}
619644

620645
void BetaCudaDeviceInterface::unmapPreviousFrame() {
646+
NVTX_SCOPED_RANGE("BetaCudaDeviceInterface::unmapPreviousFrame");
621647
if (previouslyMappedFrame_ == 0) {
622648
return;
623649
}
@@ -632,6 +658,7 @@ UniqueAVFrame BetaCudaDeviceInterface::convertCudaFrameToAVFrame(
632658
CUdeviceptr framePtr,
633659
unsigned int pitch,
634660
const CUVIDPARSERDISPINFO& dispInfo) {
661+
NVTX_SCOPED_RANGE("BetaCudaDeviceInterface::convertCudaFrameToAVFrame");
635662
STD_TORCH_CHECK(framePtr != 0, "Invalid CUDA frame pointer");
636663

637664
// Get frame dimensions from video format display area (not coded dimensions)
@@ -700,6 +727,7 @@ UniqueAVFrame BetaCudaDeviceInterface::convertCudaFrameToAVFrame(
700727
}
701728

702729
void BetaCudaDeviceInterface::flush() {
730+
NVTX_SCOPED_RANGE("BetaCudaDeviceInterface::flush");
703731
if (cpuFallback_) {
704732
cpuFallback_->flush();
705733
return;
@@ -720,6 +748,7 @@ void BetaCudaDeviceInterface::flush() {
720748

721749
UniqueAVFrame BetaCudaDeviceInterface::transferCpuFrameToGpuNV12(
722750
UniqueAVFrame& cpuFrame) {
751+
NVTX_SCOPED_RANGE("BetaCudaDeviceInterface::transferCpuFrameToGpuNV12");
723752
// This is called in the context of the CPU fallback: the frame was decoded on
724753
// the CPU, and in this function we convert that frame into NV12 format and
725754
// send it to the GPU.
@@ -859,6 +888,7 @@ void BetaCudaDeviceInterface::convertAVFrameToFrameOutput(
859888
UniqueAVFrame& avFrame,
860889
FrameOutput& frameOutput,
861890
std::optional<torch::Tensor> preAllocatedOutputTensor) {
891+
NVTX_SCOPED_RANGE("BetaCudaDeviceInterface::convertAVFrameToFrameOutput");
862892
UniqueAVFrame gpuFrame =
863893
cpuFallback_ ? transferCpuFrameToGpuNV12(avFrame) : std::move(avFrame);
864894

@@ -878,6 +908,7 @@ void BetaCudaDeviceInterface::convertAVFrameToFrameOutput(
878908
}
879909

880910
std::string BetaCudaDeviceInterface::getDetails() {
911+
NVTX_SCOPED_RANGE("BetaCudaDeviceInterface::getDetails");
881912
std::string details = "Beta CUDA Device Interface.";
882913
if (cpuFallback_) {
883914
details += " Using CPU fallback.";

src/torchcodec/_core/CMakeLists.txt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,24 @@ find_package(pybind11 REQUIRED)
88
find_package(Torch REQUIRED)
99
find_package(Python3 ${PYTHON_VERSION} EXACT COMPONENTS Development)
1010

11+
# NVTX support - read env variable into a normal variable
12+
set(USE_NVTX_ENV OFF)
13+
if(DEFINED ENV{USE_NVTX})
14+
if($ENV{USE_NVTX} STREQUAL "1" OR $ENV{USE_NVTX} STREQUAL "ON")
15+
set(USE_NVTX_ENV ON)
16+
endif()
17+
endif()
18+
19+
# NVTX support - only if ENABLE_CUDA is set
20+
include(CMakeDependentOption)
21+
cmake_dependent_option(
22+
USE_NVTX
23+
"Enable NVTX annotations for profiling (requires CUDA)"
24+
${USE_NVTX_ENV} # default if dependency satisfied
25+
"ENABLE_CUDA" # dependency
26+
OFF # value if dependency not satisfied
27+
)
28+
1129
if(DEFINED TORCHCODEC_DISABLE_COMPILE_WARNING_AS_ERROR AND TORCHCODEC_DISABLE_COMPILE_WARNING_AS_ERROR)
1230
set(TORCHCODEC_WERROR_OPTION "")
1331
else()
@@ -58,6 +76,10 @@ function(make_torchcodec_sublibrary
5876
# all the `#ifdef FMT_HEADER_ONLY` paths, so we define FMT_HEADER_ONLY here.```
5977
target_compile_definitions(${library_name} PRIVATE FMT_HEADER_ONLY)
6078

79+
if(USE_NVTX)
80+
target_compile_definitions(${library_name} PRIVATE USE_NVTX)
81+
endif()
82+
6183
# Avoid adding the "lib" prefix which we already add explicitly.
6284
set_target_properties(${library_name} PROPERTIES PREFIX "")
6385

0 commit comments

Comments
 (0)