3
3
import subprocess
4
4
import urllib .request
5
5
from concurrent .futures import ThreadPoolExecutor , wait
6
+ from dataclasses import dataclass
6
7
from itertools import product
7
8
from pathlib import Path
8
9
@@ -479,13 +480,51 @@ def get_metadata(video_file_path: str) -> VideoStreamMetadata:
479
480
return VideoDecoder (video_file_path ).metadata
480
481
481
482
483
+ @dataclass
484
+ class BatchParameters :
485
+ num_threads : int
486
+ batch_size : int
487
+
488
+
489
+ def run_batch_using_threads (
490
+ function ,
491
+ * args ,
492
+ batch_parameters : BatchParameters = BatchParameters (num_threads = 8 , batch_size = 40 ),
493
+ ):
494
+ executor = ThreadPoolExecutor (max_workers = batch_parameters .num_threads )
495
+ futures = []
496
+ for _ in range (batch_parameters .batch_size ):
497
+ futures .append (executor .submit (function , * args ))
498
+ for f in futures :
499
+ assert f .result ()
500
+ executor .shutdown (wait = True )
501
+
502
+
503
+ def convert_result_to_df_item (
504
+ result , decoder_name , video_file_path , num_samples , decode_pattern
505
+ ):
506
+ df_item = {}
507
+ df_item ["decoder" ] = decoder_name
508
+ df_item ["video" ] = str (video_file_path )
509
+ df_item ["description" ] = result .description
510
+ df_item ["frame_count" ] = num_samples
511
+ df_item ["median" ] = result .median
512
+ df_item ["iqr" ] = result .iqr
513
+ df_item ["type" ] = decode_pattern
514
+ df_item ["fps_median" ] = num_samples / result .median
515
+ df_item ["fps_p75" ] = num_samples / result ._p75
516
+ df_item ["fps_p25" ] = num_samples / result ._p25
517
+ return df_item
518
+
519
+
482
520
def run_benchmarks (
483
521
decoder_dict : dict [str , AbstractDecoder ],
484
522
video_files_paths : list [Path ],
485
523
num_samples : int ,
486
524
num_sequential_frames_from_start : list [int ],
487
525
min_runtime_seconds : float ,
488
526
benchmark_video_creation : bool ,
527
+ batch_parameters : BatchParameters = None ,
489
528
) -> list [dict [str , str | float | int ]]:
490
529
# Ensure that we have the same seed across benchmark runs.
491
530
torch .manual_seed (0 )
@@ -532,18 +571,44 @@ def run_benchmarks(
532
571
results .append (
533
572
seeked_result .blocked_autorange (min_run_time = min_runtime_seconds )
534
573
)
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 )
574
+ df_data .append (
575
+ convert_result_to_df_item (
576
+ results [- 1 ],
577
+ decoder_name ,
578
+ video_file_path ,
579
+ num_samples ,
580
+ f"{ kind } seek()+next()" ,
581
+ )
582
+ )
583
+
584
+ if batch_parameters :
585
+ seeked_result = benchmark .Timer (
586
+ stmt = "run_batch_using_threads(decoder.get_frames_from_video, video_file, pts_list, batch_parameters=batch_parameters)" ,
587
+ globals = {
588
+ "video_file" : str (video_file_path ),
589
+ "pts_list" : pts_list ,
590
+ "decoder" : decoder ,
591
+ "run_batch_using_threads" : run_batch_using_threads ,
592
+ "batch_parameters" : batch_parameters ,
593
+ },
594
+ label = f"video={ video_file_path } { metadata_label } " ,
595
+ sub_label = decoder_name ,
596
+ description = f"batch { kind } { num_samples } seek()+next()" ,
597
+ )
598
+ results .append (
599
+ seeked_result .blocked_autorange (
600
+ min_run_time = min_runtime_seconds
601
+ )
602
+ )
603
+ df_data .append (
604
+ convert_result_to_df_item (
605
+ results [- 1 ],
606
+ decoder_name ,
607
+ video_file_path ,
608
+ num_samples * batch_parameters .batch_size ,
609
+ f"batch { kind } seek()+next()" ,
610
+ )
611
+ )
547
612
548
613
for num_consecutive_nexts in num_sequential_frames_from_start :
549
614
consecutive_frames_result = benchmark .Timer (
@@ -562,18 +627,44 @@ def run_benchmarks(
562
627
min_run_time = min_runtime_seconds
563
628
)
564
629
)
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 )
630
+ df_data .append (
631
+ convert_result_to_df_item (
632
+ results [- 1 ],
633
+ decoder_name ,
634
+ video_file_path ,
635
+ num_consecutive_nexts ,
636
+ f"{ num_consecutive_nexts } next()" ,
637
+ )
638
+ )
639
+
640
+ if batch_parameters :
641
+ consecutive_frames_result = benchmark .Timer (
642
+ stmt = "run_batch_using_threads(decoder.get_consecutive_frames_from_video, video_file, consecutive_frames_to_extract, batch_parameters=batch_parameters)" ,
643
+ globals = {
644
+ "video_file" : str (video_file_path ),
645
+ "consecutive_frames_to_extract" : num_consecutive_nexts ,
646
+ "decoder" : decoder ,
647
+ "run_batch_using_threads" : run_batch_using_threads ,
648
+ "batch_parameters" : batch_parameters ,
649
+ },
650
+ label = f"video={ video_file_path } { metadata_label } " ,
651
+ sub_label = decoder_name ,
652
+ description = f"batch { num_consecutive_nexts } next()" ,
653
+ )
654
+ results .append (
655
+ consecutive_frames_result .blocked_autorange (
656
+ min_run_time = min_runtime_seconds
657
+ )
658
+ )
659
+ df_data .append (
660
+ convert_result_to_df_item (
661
+ results [- 1 ],
662
+ decoder_name ,
663
+ video_file_path ,
664
+ num_consecutive_nexts * batch_parameters .batch_size ,
665
+ f"batch { num_consecutive_nexts } next()" ,
666
+ )
667
+ )
577
668
578
669
first_video_file_path = video_files_paths [0 ]
579
670
if benchmark_video_creation :
0 commit comments