yum-archive/TaSTT-Whisper
High-performance GPGPU inference of OpenAI's Whisper automatic speech recognition (ASR) model
git clone https://git.yummers.dev/yum-archive/TaSTT-Whisper
5483755
master
1using System . Globalization ; 2using System . Text . RegularExpressions ; 3 4namespace PerfSummary 5{ 6enum eInputClip : byte 7{ 8jfk , 9columbia , 10} 11enum eWhisperModel : byte 12{ 13medium , 14large 15} 16 17struct LogName 18{ 19public readonly eInputClip clip ; 20public readonly eWhisperModel model ; 21public readonly string gpu ; 22 23public override string ToString () => $" { clip } - { model } - { gpu } " ; 24 25public static LogName ? tryParse ( string path ) 26{ 27string ? ext = Path . GetExtension ( path ); 28if ( ext == null || ! ext . Equals ( ".txt" , StringComparison . InvariantCultureIgnoreCase ) ) 29return null ; 30 31string name = Path . GetFileNameWithoutExtension ( path ); 32string [] fields = name . Split ( '-' ); 33if ( fields . Length != 3 ) 34return null ; 35 36return new LogName ( fields ); 37} 38 39LogName ( string [] fields ) 40{ 41clip = Enum . Parse < eInputClip > ( fields [ 0 ] ); 42model = Enum . Parse < eWhisperModel > ( fields [ 1 ] ); 43gpu = fields [ 2 ]; 44} 45} 46 47record class LogData 48{ 49public LogName name { get ; init ; } 50// The numbers are seconds 51public double runComplete { get ; init ; } 52public double encode { get ; init ; } 53public double decode { get ; init ; } 54// The numbers are megabytes 55public double ram { get ; init ; } 56public double vram { get ; init ; } 57} 58 59static class LogParser 60{ 61public static IEnumerable < LogData > parse ( string folder ) 62{ 63foreach ( string path in Directory . EnumerateFiles ( folder , "*.txt" ) ) 64{ 65LogName ? name = LogName . tryParse ( path ); 66if ( name == null ) 67continue ; 68yield return parseFile ( name . Value , path ); 69} 70} 71 72enum eSection : byte 73{ 74CPU , GPU , Shaders , Memory 75} 76static readonly ( string , eSection )[] sectionMarkers = new ( string , eSection )[] 77{ 78( "CPU Tasks" , eSection . CPU ), 79( "GPU Tasks" , eSection . GPU ), 80( "Compute Shaders" , eSection . Shaders ), 81( "Memory Usage" , eSection . Memory ), 82}; 83 84static bool tryParseSection ( ref eSection ? section , string line ) 85{ 86foreach ( ( string marker , eSection s ) in sectionMarkers ) 87{ 88if ( line . Contains ( marker ) ) 89{ 90section = s ; 91return true ; 92} 93} 94return false ; 95} 96 97static bool tryParseTime ( ref double ? val , string key , string line ) 98{ 99if ( ! line . StartsWith ( key ) ) 100return false ; 101if ( ! char . IsWhiteSpace ( line [ key . Length ] ) ) 102return false ; 103 104line = line . Substring ( key . Length ). TrimStart (); 105int comma = line . IndexOf ( ',' ); 106if ( comma > 0 ) 107line = line . Substring ( 0 , comma ); 108string [] fields = line . Split ( ' ' , StringSplitOptions . RemoveEmptyEntries ); 109if ( fields . Length != 2 ) 110throw new ArgumentException (); 111 112double v = double . Parse ( fields [ 0 ], CultureInfo . InvariantCulture ); 113switch ( fields [ 1 ] ) 114{ 115case "seconds" : 116val = v ; 117return true ; 118case "milliseconds" : 119val = v / 1E3 ; 120return true ; 121case "microseconds" : 122val = v / 1E6 ; 123return true ; 124} 125throw new ArgumentException (); 126} 127 128static readonly Regex reMemory = new Regex ( @"^Total\s+([0-9\.]+)\s+(\S+)\s+RAM, ([0-9\.]+)\s+(\S+)\s+VRAM$" ); 129 130static double parseMemory ( Match m , int iv ) 131{ 132double v = double . Parse ( m . Groups [ iv ]. Value , CultureInfo . InvariantCulture ); 133string u = m . Groups [ iv + 1 ]. Value ; 134switch ( u ) 135{ 136case "bytes" : 137return v / ( 1 << 20 ); 138case "KB" : 139return v / ( 1 << 10 ); 140case "MB" : 141return v ; 142case "GB" : 143return v * ( 1 << 10 ); 144} 145throw new ArgumentException (); 146} 147 148static bool tryParseMemory ( ref double ? ram , ref double ? vram , string line ) 149{ 150Match m = reMemory . Match ( line ); 151if ( ! m . Success ) 152return false ; 153ram = parseMemory ( m , 1 ); 154vram = parseMemory ( m , 3 ); 155return true ; 156} 157 158static LogData parseFile ( in LogName name , string path ) 159{ 160using var reader = File . OpenText ( path ); 161double ? runComplete = null ; 162double ? encode = null ; 163double ? decode = null ; 164double ? ram = null ; 165double ? vram = null ; 166eSection ? section = null ; 167 168while ( true ) 169{ 170string ? line = reader . ReadLine (); 171if ( line == null ) 172break ; 173if ( string . IsNullOrEmpty ( line ) ) 174continue ; 175if ( tryParseSection ( ref section , line ) ) 176continue ; 177 178switch ( section ) 179{ 180case eSection . CPU : 181tryParseTime ( ref runComplete , "RunComplete" , line ); 182break ; 183case eSection . GPU : 184tryParseTime ( ref encode , "Encode" , line ); 185tryParseTime ( ref decode , "Decode" , line ); 186break ; 187case eSection . Memory : 188tryParseMemory ( ref ram , ref vram , line ); 189break ; 190} 191} 192 193if ( null == runComplete || null == encode || null == decode || null == ram || null == vram ) 194throw new ArgumentException (); 195 196return new LogData () 197{ 198name = name , 199runComplete = runComplete . Value , 200encode = encode . Value , 201decode = decode . Value , 202ram = ram . Value , 203vram = vram . Value , 204}; 205} 206} 207}