Skip to content

Commit cf91336

Browse files
committed
Add batch benchmarks and cuda decoder
1 parent 3e1f4b5 commit cf91336

File tree

2 files changed

+100
-26
lines changed

2 files changed

+100
-26
lines changed

benchmarks/decoders/benchmark_decoders_library.py

Lines changed: 99 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,30 @@ def get_metadata(video_file_path: str) -> VideoStreamMetadata:
479479
return VideoDecoder(video_file_path).metadata
480480

481481

482+
def run_batch_using_threads(function, *args, num_threads=10, batch_size=40):
483+
executor = ThreadPoolExecutor(max_workers=10)
484+
for _ in range(batch_size):
485+
executor.submit(function, *args)
486+
executor.shutdown(wait=True)
487+
488+
489+
def convert_result_to_df_item(
490+
result, decoder_name, video_file_path, num_samples, decode_pattern
491+
):
492+
df_item = {}
493+
df_item["decoder"] = decoder_name
494+
df_item["video"] = str(video_file_path)
495+
df_item["description"] = result.description
496+
df_item["frame_count"] = num_samples
497+
df_item["median"] = result.median
498+
df_item["iqr"] = result.iqr
499+
df_item["type"] = decode_pattern
500+
df_item["fps_median"] = num_samples / result.median
501+
df_item["fps_p75"] = num_samples / result._p75
502+
df_item["fps_p25"] = num_samples / result._p25
503+
return df_item
504+
505+
482506
def run_benchmarks(
483507
decoder_dict: dict[str, AbstractDecoder],
484508
video_files_paths: list[Path],
@@ -506,6 +530,7 @@ def run_benchmarks(
506530
# video. However, because we use the duration as part of this calculation, we
507531
# are using different random pts values across videos.
508532
random_pts_list = (torch.rand(num_samples) * duration).tolist()
533+
batch_size = 40
509534

510535
for decoder_name, decoder in decoder_dict.items():
511536
print(f"video={video_file_path}, decoder={decoder_name}")
@@ -527,23 +552,46 @@ def run_benchmarks(
527552
},
528553
label=f"video={video_file_path} {metadata_label}",
529554
sub_label=decoder_name,
530-
description=f"{kind} {num_samples} seek()+next()",
555+
description=f"batch {kind} {num_samples} seek()+next()",
556+
)
557+
results.append(
558+
seeked_result.blocked_autorange(min_run_time=min_runtime_seconds)
559+
)
560+
df_data.append(
561+
convert_result_to_df_item(
562+
results[-1],
563+
decoder_name,
564+
video_file_path,
565+
num_samples * batch_size,
566+
f"{kind} {num_samples} seek()+next()",
567+
)
568+
)
569+
570+
seeked_result = benchmark.Timer(
571+
stmt="run_batch_using_threads(decoder.get_frames_from_video, video_file, pts_list, batch_size=batch_size)",
572+
globals={
573+
"video_file": str(video_file_path),
574+
"pts_list": pts_list,
575+
"decoder": decoder,
576+
"run_batch_using_threads": run_batch_using_threads,
577+
"batch_size": batch_size,
578+
},
579+
label=f"video={video_file_path} {metadata_label}",
580+
sub_label=decoder_name,
581+
description=f"batch {kind} {num_samples} seek()+next()",
531582
)
532583
results.append(
533584
seeked_result.blocked_autorange(min_run_time=min_runtime_seconds)
534585
)
535-
df_item = {}
536-
df_item["decoder"] = decoder_name
537-
df_item["video"] = str(video_file_path)
538-
df_item["description"] = results[-1].description
539-
df_item["frame_count"] = num_samples
540-
df_item["median"] = results[-1].median
541-
df_item["iqr"] = results[-1].iqr
542-
df_item["type"] = f"{kind}:seek()+next()"
543-
df_item["fps_median"] = num_samples / results[-1].median
544-
df_item["fps_p75"] = num_samples / results[-1]._p75
545-
df_item["fps_p25"] = num_samples / results[-1]._p25
546-
df_data.append(df_item)
586+
df_data.append(
587+
convert_result_to_df_item(
588+
results[-1],
589+
decoder_name,
590+
video_file_path,
591+
num_samples * batch_size,
592+
f"batch {kind} {num_samples} seek()+next()",
593+
)
594+
)
547595

548596
for num_consecutive_nexts in num_sequential_frames_from_start:
549597
consecutive_frames_result = benchmark.Timer(
@@ -555,25 +603,50 @@ def run_benchmarks(
555603
},
556604
label=f"video={video_file_path} {metadata_label}",
557605
sub_label=decoder_name,
558-
description=f"{num_consecutive_nexts} next()",
606+
description=f"batch {num_consecutive_nexts} next()",
559607
)
560608
results.append(
561609
consecutive_frames_result.blocked_autorange(
562610
min_run_time=min_runtime_seconds
563611
)
564612
)
565-
df_item = {}
566-
df_item["decoder"] = decoder_name
567-
df_item["video"] = str(video_file_path)
568-
df_item["description"] = results[-1].description
569-
df_item["frame_count"] = num_consecutive_nexts
570-
df_item["median"] = results[-1].median
571-
df_item["iqr"] = results[-1].iqr
572-
df_item["type"] = "next()"
573-
df_item["fps_median"] = num_consecutive_nexts / results[-1].median
574-
df_item["fps_p75"] = num_consecutive_nexts / results[-1]._p75
575-
df_item["fps_p25"] = num_consecutive_nexts / results[-1]._p25
576-
df_data.append(df_item)
613+
df_data.append(
614+
convert_result_to_df_item(
615+
results[-1],
616+
decoder_name,
617+
video_file_path,
618+
num_consecutive_nexts * batch_size,
619+
f"{num_consecutive_nexts} next()",
620+
)
621+
)
622+
623+
consecutive_frames_result = benchmark.Timer(
624+
stmt="run_batch_using_threads(decoder.get_consecutive_frames_from_video, video_file, consecutive_frames_to_extract, batch_size=batch_size)",
625+
globals={
626+
"video_file": str(video_file_path),
627+
"consecutive_frames_to_extract": num_consecutive_nexts,
628+
"decoder": decoder,
629+
"run_batch_using_threads": run_batch_using_threads,
630+
"batch_size": batch_size,
631+
},
632+
label=f"video={video_file_path} {metadata_label}",
633+
sub_label=decoder_name,
634+
description=f"batch {num_consecutive_nexts} next()",
635+
)
636+
results.append(
637+
consecutive_frames_result.blocked_autorange(
638+
min_run_time=min_runtime_seconds
639+
)
640+
)
641+
df_data.append(
642+
convert_result_to_df_item(
643+
results[-1],
644+
decoder_name,
645+
video_file_path,
646+
num_consecutive_nexts * batch_size,
647+
f"batch {num_consecutive_nexts} next()",
648+
)
649+
)
577650

578651
first_video_file_path = video_files_paths[0]
579652
if benchmark_video_creation:

benchmarks/decoders/generate_readme_data.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ def main() -> None:
5757

5858
decoder_dict = {}
5959
decoder_dict["TorchCodec"] = TorchCodecPublic()
60+
decoder_dict["TorchCodec[cuda]"] = TorchCodecPublic(device="cuda")
6061
decoder_dict["TorchVision[video_reader]"] = TorchVision("video_reader")
6162
decoder_dict["TorchAudio"] = TorchAudioDecoder()
6263
decoder_dict["Decord"] = DecordAccurateBatch()

0 commit comments

Comments
 (0)