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
cacec67
master
1#pragma once 2#include "../D3D/device.h" 3#include "ProfileCollection.h" 4#include "DelayExecution.h" 5 6namespace DirectCompute 7{ 8enum struct eProfilerBlock :uint16_t 9 { 10LoadModel = 0x1000 , 11Run = 0x2000 , 12Encode = 0x3000 , 13EncodeLayer = 0x4000 , 14Decode = 0x5000 , 15DecodeStep = 0x6000 , 16DecodeLayer = 0x7000 , 17 }; 18 19enum struct eComputeShader :uint16_t ; 20 21class GpuProfiler 22 { 23DelayExecution delay ; 24CComPtr < ID3D11Query > disjoint ; 25 26enum struct eEvent 27 { 28None = 0 , 29BlockStart , 30BlockEnd , 31Shader 32 }; 33 34struct BlockState ; 35static constexpruint16_t EmptyShader = ~(uint16_t )0 ; 36 37// A circular buffer with in-flight queries which feeds timestamps into the iTimestampSink interface 38class Queue 39 { 40static constexprsize_t queueLength = 32 ; 41 42// Ring buffer for individual measures 43struct Entry 44 { 45CComPtr < ID3D11Query > query ; 46BlockState * block ; 47eEvent event ; 48uint16_t shader ; 49#if PROFILER_COLLECT_TAGS 50uint16_t tag = 0 ; 51#endif 52void join (GpuProfiler & owner ); 53 }; 54 55GpuProfiler & owner ; 56std ::array < Entry ,queueLength > queue ; 57size_t nextEntry = 0 ; 58 59public : 60Queue (GpuProfiler & gp ) :owner (gp ) {} 61 62HRESULT create (); 63 64// Begin a next query. Eventually, this will result in the BlockState.haveTimestamp callback 65void submit (BlockState * block ,eEvent evt ,uint16_t shader = EmptyShader ,uint16_t tag = 0 ); 66 67// Wait for all the pending queries, and call their callbacks 68void join (); 69 }; 70Queue queries ; 71 72struct sProfilerData ; 73struct BlockState 74 { 75int64_t timeStart = -1 ; 76sProfilerData * destBlock = nullptr; 77int64_t shaderStart = -1 ; 78uint16_t prevShader = EmptyShader ; 79uint16_t prevShaderTag = 0 ; 80BlockState * parentBlock = nullptr; 81void haveTimestamp (eEvent evt ,uint16_t cs ,uint16_t tag ,uint64_t time ,GpuProfiler & profiler ); 82private : 83void completePrevShader (uint64_t time ,GpuProfiler & profiler ); 84 }; 85CAtlMap < eProfilerBlock ,BlockState > blockStates ; 86std ::vector < BlockState *> stack ; 87 88struct sProfilerData 89 { 90// Count of accumulated measures 91size_t callsPending ; 92// Total time spent running all instances of that measure, expressed in GPU ticks 93uint64_t timePending ; 94 95Whisper ::ProfileCollection ::Measure * dest ; 96 97inline void makeTime (uint64_t freq ); 98inline void addPending (int64_t time ); 99inline void reset (); 100inline void dropPending (); 101 102sProfilerData () 103 { 104reset (); 105 } 106 }; 107 108CAtlMap < uint16_t ,sProfilerData > results ; 109#if PROFILER_COLLECT_TAGS 110CAtlMap < uint32_t ,sProfilerData > resultsTagged ; 111#endif 112void resultsMakeTime (uint64_t freq ); 113void resultsDropPending (); 114void resultsReset (); 115 116void blockStart (eProfilerBlock which ); 117void blockEnd (); 118 119Whisper ::ProfileCollection & dest ; 120#if PROFILER_COLLECT_TAGS 121uint16_t m_nextTag = 0 ; 122#endif 123public : 124 125GpuProfiler (Whisper ::ProfileCollection & pc ) : 126dest (pc ),queries (* this ) { } 127 128HRESULT create (size_t maxDepth = 3 ); 129 130class BlockRaii 131 { 132GpuProfiler * profiler ; 133 134public : 135BlockRaii (GpuProfiler & owner ,eProfilerBlock which ) 136 { 137owner .blockStart (which ); 138profiler = & owner ; 139 } 140 ~BlockRaii () 141 { 142if (nullptr != profiler ) 143 { 144profiler -> blockEnd (); 145profiler = nullptr ; 146 } 147 } 148BlockRaii (BlockRaii && that )noexcept : 149profiler (that .profiler ) 150 { 151that .profiler = nullptr ; 152 } 153BlockRaii (const BlockRaii & )= delete ; 154void operator = (const BlockRaii & )= delete ; 155void operator = (BlockRaii && ) = delete; 156}; 157 158BlockRaii block ( eProfilerBlock which ) 159{ 160return BlockRaii{ * this, which }; 161} 162 163void computeShader ( eComputeShader cs ); 164 165bool profileShaders = false; 166// bool profileShaders = true; 167 168decltype( auto ) cpuBlock ( Whisper ::eCpuBlock block ) 169{ 170return dest. cpuBlock ( block ); 171} 172Whisper ::ProfileCollection & profiler () { return dest; } 173 174// Set tag string for the next compute shader 175// The string should be readonly: for performance reason the implementation doesn�t copy nor compare any strings, it only keeps the pointer 176#if PROFILER_COLLECT_TAGS 177uint16_t setNextTag ( const char * name ); 178#else 179inline uint16_t setNextTag ( const char * name ) { return 0 ; } 180#endif 181 182void setNextTag ( uint16_t tag ) 183{ 184#if PROFILER_COLLECT_TAGS 185m_nextTag = tag; 186#endif 187 } 188 }; 189}