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
8c4603c
master
1#include "stdafx.h" 2#include "TraceWriter.h" 3#include <atlfile.h> 4#include <atlcoll.h> 5#include <atlstr.h> 6#include "TraceStructures.h" 7#include "../../ML/Tensor.h" 8#include "../../CPU/Tensor.h" 9#include <Shlobj.h> 10using namespace Tracing ; 11 12namespace 13{ 14static HRESULT createDir (LPCTSTR pathFile ) 15 { 16LPCWSTR fn = PathFindFileName (pathFile ); 17if (fn == pathFile ) 18return E_FAIL ; 19 20const int cc = (int )(fn - pathFile ); 21CString dir {pathFile ,cc }; 22if (PathIsDirectory (dir ) ) 23return S_OK ; 24const int status = SHCreateDirectoryEx (nullptr ,dir ,nullptr ); 25if (0 == status ) 26return S_OK ; 27return HRESULT_FROM_WIN32 (status ); 28 } 29 30class TraceFileWriter 31 { 32CAtlFile file ; 33// Concatenated strings, including the 0 terminators 34 std::vector < char > stringsData ; 35// Index = string ID, value = start offset into stringsData 36 std::vector < uint32_t > stringsIndex ; 37// Hash map to unduplicate these strings 38CAtlMap < CStringA ,uint32_t > stringsHash ; 39 40uint32_t addString (const CStringA & s ) 41 { 42auto p = stringsHash .Lookup (s ); 43if (p != nullptr ) 44return p -> m_value ; 45 46const uint32_t off = (uint32_t )stringsData .size (); 47const char * rsi = s ; 48stringsData .insert (stringsData .end (),rsi ,rsi + s .GetLength ()+ 1 ); 49stringsIndex .push_back (off ); 50 51const uint32_t newId = (uint32_t )stringsHash .GetCount (); 52stringsHash .SetAt (s ,newId ); 53return newId ; 54 } 55 56void addString (sTraceItem & rdi ,const ItemName & name ) 57 { 58rdi .countFormatArgs = name .countArgs ; 59rdi .stringIndex = addString (name .pointer ); 60rdi .formatArgs = name .args ; 61 } 62 63 std::vector < sTraceItem > items ; 64uint64_t offset = 0 ; 65 66public : 67 68HRESULT create (LPCTSTR path ) 69 { 70CHECK (createDir (path ) ); 71CHECK (file .Create (path ,GENERIC_WRITE ,0 ,CREATE_ALWAYS ) ); 72 73constexpr uint64_t cbHeader = sizeof (sFileHeader ); 74CHECK (file .SetSize (cbHeader ) ); 75CHECK (file .Seek (0 ,SEEK_END ) ); 76offset = 0 ; 77 78return S_OK ; 79 } 80 81HRESULT buffer (const ItemName & name ,const void * rsi ,size_t length ,eDataType dt ) 82 { 83sTraceItem & rdi = items .emplace_back (); 84const uint64_t cb = rdi .buffer (offset ,length ,dt ); 85addString (rdi ,name ); 86assert (cb <=UINT_MAX ); 87CHECK (file .Write (rsi , (DWORD )cb ) ); 88offset += cb ; 89return S_OK ; 90 } 91 92HRESULT tensor (const ItemName & name ,const void * rsi ,__m128i size ,__m128i strides ,eDataType dt ) 93 { 94sTraceItem & rdi = items .emplace_back (); 95const uint64_t cb = rdi .tensor (offset ,size ,strides ,dt ); 96addString (rdi ,name ); 97assert (cb <=UINT_MAX ); 98CHECK (file .Write (rsi , (DWORD )cb ) ); 99offset += cb ; 100return S_OK ; 101 } 102 103HRESULT close () 104 { 105if ( !file ) 106return S_FALSE ; 107 108const uint32_t cbStringsData = (uint32_t )stringsData .size (); 109const uint32_t cbStringsIndex = (uint32_t )(stringsIndex .size ()* 4 ); 110if ( !stringsIndex .empty () ) 111CHECK (file .Write (stringsIndex .data (),cbStringsIndex ) ); 112if ( !stringsData .empty () ) 113CHECK (file .Write (stringsData .data (),cbStringsData ) ); 114 115const uint32_t cbItems = (uint32_t )items .size ()* (uint32_t )sizeof (sTraceItem ); 116if ( !items .empty () ) 117CHECK (file .Write (items .data (),cbItems ) ); 118CHECK (file .Seek (0 ,FILE_BEGIN ) ); 119 120sFileHeader header ; 121memset (& header ,0 ,sizeof (header ) ); 122header .magic = header .correctMagic ; 123header .cbItem = sizeof (sTraceItem ); 124header .countItems = (uint32_t )items .size (); 125header .bytesPayload = offset ; 126header .countStrings = (uint32_t )stringsIndex .size (); 127header .bytesStrings = cbStringsData + cbStringsIndex ; 128CHECK (file .Write (& header ,sizeof (header ) ) ); 129CHECK (file .Flush () ); 130file .Close (); 131 132return S_OK ; 133 } 134 }; 135 136class TraceWriter :public iTraceWriter 137 { 138TraceFileWriter file ; 139 140HRESULT buffer (const ItemName & name ,const void * rsi ,size_t length ,eDataType dt )override final 141 { 142return file .buffer (name ,rsi ,length ,dt ); 143 } 144 145HRESULT tensor (const ItemName & name ,const void * rsi ,__m128i size ,__m128i strides ,eDataType dt )override final 146 { 147return file .tensor (name ,rsi ,size ,strides ,dt ); 148 } 149 150public : 151 152TraceWriter (LPCTSTR path ) 153 { 154check (file .create (path ) ); 155 } 156 157 ~TraceWriter () 158 { 159check (file .close () ); 160 } 161 }; 162} 163 164std::unique_ptr < iTraceWriter > iTraceWriter::create (LPCTSTR path ) 165{ 166return std::make_unique < TraceWriter > (path ); 167} 168 169namespace 170{ 171static std::vector < float > tempFp32 ; 172static std::vector < uint16_t > tempFp16 ; 173 174template < class E > 175inline const void * ptr (const std::vector < E >& vec ) 176 { 177return vec .empty () ?nullptr :vec .data (); 178 } 179} 180 181HRESULT iTraceWriter::tensor (const ItemName & name ,const DirectCompute ::Tensor & source ) 182{ 183const __m128i size = source .sizeVec (); 184const __m128i strides = source .stridesVec (); 185const eDataType dt = source .getType (); 186if (dt == eDataType::FP32 ) 187 { 188source .download (tempFp32 ); 189return tensor (name ,ptr (tempFp32 ),size ,strides , eDataType::FP32 ); 190 } 191else if (dt == eDataType::FP16 ) 192 { 193source .download (tempFp16 ); 194return tensor (name ,ptr (tempFp16 ),size ,strides , eDataType::FP16 ); 195 } 196return E_NOTIMPL ; 197} 198 199HRESULT iTraceWriter::tensor (const ItemName & name ,const CpuCompute ::Tensor & source ) 200{ 201const __m128i size = source .sizeVec (); 202const __m128i strides = source .stridesVec (); 203const eDataType dt = source .type (); 204 205if (dt == eDataType::FP32 ) 206return tensor (name ,source .fp32 (),size ,strides , eDataType::FP32 ); 207else if (dt == eDataType::FP16 ) 208return tensor (name ,source .fp16 (),size ,strides , eDataType::FP16 ); 209else 210return E_NOTIMPL ; 211} 212 213#if BUILD_BOTH_VERSIONS 214#include "../../source/ggml.h" 215HRESULT __declspec(noinline ) iTraceWriter::tensor (const ItemName & name ,const ggml_tensor & source ) 216{ 217__m128i size = load16 (source .ne ); 218__m128i strides = _mm_setr_epi32 ( 219 (int )(uint32_t )source .nb [0 ], 220 (int )(uint32_t )source .nb [1 ], 221 (int )(uint32_t )source .nb [2 ], 222 (int )(uint32_t )source .nb [3 ] ); 223 224const __m128i ones = _mm_set1_epi32 (1 ); 225switch (source .n_dims ) 226 { 227case 0 : 228size = ones ; 229break ; 230case 1 : 231size = _mm_blend_epi16 (size ,ones ,0b11111100 ); 232break ; 233case 2 : 234size = _mm_blend_epi16 (size ,ones ,0b11110000 ); 235break ; 236case 3 : 237size = _mm_blend_epi16 (size ,ones ,0b11000000 ); 238break ; 239case 4 : 240break ; 241default : 242return E_INVALIDARG ; 243 } 244 245const ggml_type dt = source .type ; 246switch (dt ) 247 { 248case GGML_TYPE_F16 : 249strides = _mm_srli_epi32 (strides ,1 ); 250return tensor (name ,source .data ,size ,strides , eDataType::FP16 ); 251case GGML_TYPE_F32 : 252strides = _mm_srli_epi32 (strides ,2 ); 253return tensor (name ,source .data ,size ,strides , eDataType::FP32 ); 254default : 255return E_NOTIMPL ; 256} 257} 258#else 259HRESULT iTraceWriter::tensor (const ItemName & name ,const ggml_tensor & source ) 260{ 261return E_NOTIMPL ; 262} 263#endif