-
Notifications
You must be signed in to change notification settings - Fork 74
Avoid seeking checks when decoding frames sequentially #1028
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Avoid seeking checks when decoding frames sequentially #1028
Conversation
|
Digging into
Can't we now replace that call with your newly added |
| if (frameIndex != lastDecodedFrameIndex_ + 1) { | ||
| int64_t pts = getPts(frameIndex); | ||
| setCursorPtsInSeconds(ptsToSeconds(pts, streamInfo.timeBase)); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I included the changes from #1039 in this PR.
@scotts , does the comment make sense now? What the comment is not saying is why returning early in canWeAvoidSeeking() is important. It's important because it avoids the calls to av_index_search_timestamp which are potentially slow. I don't know if we want to get to that level of detail in the comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this greatly helps with understanding.
I do think we should explain somewhere that canWeAvoidSeeking() is itself expensive in some circumstances. . That's deeply counter-intuitive, that the function we're calling as an optimization to avoid the slow thing is itself also a slow thing. (But hopefully less slow.) Perhaps that should belong at the top of canWeAvoidSeeking().
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will address that in an immediate follow-up
|
Replying to #1028 (comment)
Unfortunately no, the new "skip condition" I am introducing in this PR is different. Our new condition is to return early when we know there's no need to seek, and there isn't even a need to run further "can we skip seeking" checks. This existing condition you mentioned:
is part of those "further checks" (and it's actually the part that's expensive!). The idea is that if we were around keyframe K and the new frame we want is also related to K, we don't need to seek. Note that |
We have a "skip seeking" logic where we try to minimize the number of seeks we have to do. This logic lives in
torchcodec/src/torchcodec/_core/SingleStreamDecoder.cpp
Line 1091 in 7d27c15
The problem is:
canWeAvoidSeeking()itself can be expensive to call!! This is especially true inapproximatemode which, as I just found out, can be slower than exact mode for short videos (10s long).In this PR, we skip the call tocanWeAvoidSeeking()when we can - yes, we "skip the skip-checking logic"!EDIT: we don't skip the call to
canWeAvoidSeeking(), we just add a new condition that causescanWeAvoidSeeking()to return early, before it runs its potentially expensive parts.We can do that when we are decoding frames contiguously: 0, 1, 2, 3....
This will provide significant speedups when:
get_frames_at()andget_frames_played_at().Why is
canWeAvoidSeeking()slow?Because it calls
getKeyFrameIndexForPts()which, in approximate mode, callsav_index_search_timestamp(). Calling this for all frames can dominate the runtime!Benchmarks:
Decoding all 300 frames of a short 10s long h264 720p video (testsrc2), approximate mode goes from 1249.56ms to 825.74ms (1.5X faster).
messy (but correct) benchmarking code: