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 "../../Whisper/API/iContext.cl.h" 3#include "TraceReader.h" 4#include "../../Whisper/ML/testUtils.h" 5#include "compare.h" 6using namespace Tracing ; 7using namespace DirectCompute ; 8 9namespace 10{ 11inline const char * cstr (eItemType it ) 12 { 13switch (it ) 14 { 15case eItemType::Buffer :return "Buffer" ; 16case eItemType::Tensor :return "Tensor" ; 17 } 18throw E_INVALIDARG ; 19 } 20inline const char * cstr (const CStringA & s ) {return s ; } 21 22inline int tensorDims (__m128i vec ) 23 { 24const __m128i one = _mm_set1_epi32 (1 ); 25const uint32_t bitmapOnes = (uint32_t )_mm_movemask_ps (_mm_castsi128_ps (_mm_cmpeq_epi32 (vec ,one ) ) ); 26const uint32_t bitmapNotOnes = bitmapOnes ^0b1111u ; 27unsigned long idx ; 28if ( !_BitScanReverse (& idx ,bitmapNotOnes ) ) 29return 0 ; 30return idx + 1 ; 31 } 32 33int printSize (__m128i vec ) 34 { 35const int sz = tensorDims (vec ); 36switch (sz ) 37 { 38case 0 : 39printf ("[ scalar ]" ); 40break ; 41case 1 : 42printf ("[ %i ]" ,_mm_cvtsi128_si32 (vec ) ); 43break ; 44case 2 : 45printf ("[ %i, %i ]" ,_mm_cvtsi128_si32 (vec ),_mm_extract_epi32 (vec ,1 ) ); 46break ; 47case 3 : 48printf ("[ %i, %i, %i ]" ,_mm_cvtsi128_si32 (vec ),_mm_extract_epi32 (vec ,1 ),_mm_extract_epi32 (vec ,2 ) ); 49break ; 50case 4 : 51printf ("[ %i, %i, %i, %i ]" ,_mm_cvtsi128_si32 (vec ),_mm_extract_epi32 (vec ,1 ),_mm_extract_epi32 (vec ,2 ),_mm_extract_epi32 (vec ,3 ) ); 52break ; 53default : 54throw E_UNEXPECTED ; 55 } 56return sz ; 57 } 58 59class Comparer 60 { 61TraceReader & readerA ; 62TraceReader & readerB ; 63 64bool diffBuffers (size_t i ,const sTraceItem & a ,const sTraceItem & b ,const CStringA & name ) 65 { 66const size_t lenA = * (const uint64_t * )a .size .data (); 67const size_t lenB = * (const uint64_t * )b .size .data (); 68if (lenA != lenB ) 69 { 70printf ("Buffer %zu \"%s\": different size, %zu in trace A, %zu in trace B\n" ,i ,cstr (name ),lenA ,lenB ); 71return false; 72 } 73if (a .dataType != b .dataType ) 74 { 75printf ("Buffer %zu \"%s\": different data types\n" ,i ,cstr (name ) ); 76return false; 77 } 78 79switch (a .dataType ) 80 { 81case eDataType::FP32 : 82return buffersFp32 (i ,name , (const float * )readerA .payload (a ), (const float * )readerB .payload (b ),lenA ); 83 } 84throw E_NOTIMPL ; 85 } 86 87bool diffTensors (size_t i ,const sTraceItem & a ,const sTraceItem & b ,const CStringA & name ) 88 { 89const __m128i ne1 = load (a .size ); 90const __m128i ne2 = load (b .size ); 91if ( !vectorEqual (ne1 ,ne2 ) ) 92 { 93printf ("Tensor %zu \"%s\" - different size: trace A size is " ,i ,cstr (name ) ); 94printSize (ne1 ); 95printf (", trace B size is " ); 96printSize (ne2 ); 97printf ("\n" ); 98return false; 99 } 100 101const __m128i stride1 = load (a .stride ); 102const __m128i stride2 = load (b .stride ); 103if ( !vectorEqual (stride1 ,stride2 ) ) 104 { 105printf ("Tensor %zu \"%s\" - different memory layout\n" ,i ,cstr (name ) ); 106return false; 107 } 108 109if (a .dataType != b .dataType ) 110 { 111printf ("Tensor %zu \"%s\": different data types\n" ,i ,cstr (name ) ); 112return false; 113 } 114 115size_t elements = (uint32_t )_mm_cvtsi128_si32 (ne1 ); 116elements *= (uint32_t )_mm_extract_epi32 (ne1 ,1 ); 117elements *= (uint32_t )_mm_extract_epi32 (ne1 ,2 ); 118elements *= (uint32_t )_mm_extract_epi32 (ne1 ,3 ); 119 120switch (a .dataType ) 121 { 122case eDataType::FP32 : 123return tensorsFp32 (i ,name , (const float * )readerA .payload (a ), (const float * )readerB .payload (b ),elements ,ne1 ,stride1 ); 124 } 125throw E_NOTIMPL ; 126 } 127 128protected : 129virtual bool buffersFp32 (size_t idx ,const CStringA & name ,const float * a ,const float * b ,size_t length )= 0 ; 130virtual bool tensorsFp32 (size_t idx ,const CStringA & name ,const float * a ,const float * b ,size_t length ,__m128i ne ,__m128i nb )= 0 ; 131 132public : 133 134Comparer (TraceReader & t1 ,TraceReader & t2 ) : 135readerA (t1 ),readerB (t2 ) { } 136 137bool compare (size_t i ) 138 { 139const sTraceItem & a = readerA [i ]; 140const sTraceItem & b = readerB [i ]; 141CStringA name1 = readerA .getName (a ); 142CStringA name2 = readerB .getName (b ); 143 144if (a .itemType != b .itemType ) 145 { 146printf ("Item %zu: different type, trace A %s \"%s\", trace B %s \"%s\"\n" ,i , 147cstr (a .itemType ),cstr (name1 ),cstr (b .itemType ),cstr (name2 ) ); 148return false; 149 } 150 151if (name1 != name2 ) 152 { 153printf ("%s %zu: different names, they are \"%s\" and \"%s\"\n" ,cstr (a .itemType ),i ,cstr (name1 ),cstr (name2 ) ); 154return false; 155 } 156 157switch (a .itemType ) 158 { 159case eItemType::Buffer : 160return diffBuffers (i ,a ,b ,name1 ); 161case eItemType::Tensor : 162return diffTensors (i ,a ,b ,name1 ); 163default : 164throw E_INVALIDARG ; 165 } 166 } 167 }; 168 169class PrintSummary :public Comparer 170 { 171bool buffersFp32 (size_t idx ,const CStringA & name ,const float * a ,const float * b ,size_t length )override ; 172bool tensorsFp32 (size_t idx ,const CStringA & name ,const float * a ,const float * b ,size_t length ,__m128i ne ,__m128i nb )override ; 173 174public : 175PrintSummary (TraceReader & a ,TraceReader & b ) :Comparer (a ,b ) { } 176 }; 177 178bool PrintSummary ::buffersFp32 (size_t idx ,const CStringA & name ,const float * a ,const float * b ,size_t length ) 179 { 180sTensorDiff diff = computeDiff (a ,b ,length ); 181printf ("%s %zu \"%s\": " ,cstr ( eItemType::Buffer ),idx ,cstr (name ) ); 182diff .return true; 184 } 185 186bool PrintSummary ::tensorsFp32 (size_t idx ,const CStringA & name ,const float * a ,const float * b ,size_t length ,__m128i ne ,__m128i nb ) 187 { 188printSize (ne ); 189printf (" " ); 190sTensorDiff diff = computeDiff (a ,b ,length ); 191printf ("%s %zu \"%s\": " ,cstr ( eItemType::Tensor ),idx ,cstr (name ) ); 192diff .return true; 194 } 195 196class PrintDiff :public Comparer 197 { 198bool buffersFp32 (size_t idx ,const CStringA & name ,const float * a ,const float * b ,size_t length )override ; 199bool tensorsFp32 (size_t idx ,const CStringA & name ,const float * a ,const float * b ,size_t length ,__m128i ne ,__m128i nb )override ; 200public : 201PrintDiff (TraceReader & a ,TraceReader & b ) :Comparer (a ,b ) { } 202 }; 203 204bool PrintDiff ::buffersFp32 (size_t idx ,const CStringA & name ,const float * A ,const float * B ,size_t length ) 205 { 206printf ("idx\tA\tB\tA(hex)\tB(hex)\tdiff\n" ); 207for (size_t i = 0 ;i < length ;i ++ ) 208 { 209const float a = * A ; 210const float b = * B ; 211__m128 vf = _mm_setr_ps (a ,b ,0 ,0 ); 212__m128i vi = _mm_castps_si128 (vf ); 213const float diff = std::abs (a - b ); 214printf ("%zu\t%g\t%g\t0x%08X\t0x%08X\t%g\n" , 215i ,a ,b ,_mm_cvtsi128_si32 (vi ),_mm_extract_epi32 (vi ,1 ),diff ); 216 } 217return true; 218 } 219 220 std::array < uint32_t ,4 > storeSize (__m128i v ) 221 { 222 std::array < uint32_t ,4 > a ; 223_mm_storeu_si128 ( (__m128i * )a .data (),v ); 224return a ; 225 } 226 227 std::array < size_t ,4 > storeStrides (__m128i v ) 228 { 229const __m128i zero = _mm_setzero_si128 (); 230 std::array < size_t ,4 > a ; 231_mm_storeu_si128 ( (__m128i * )& a [0 ],_mm_unpacklo_epi32 (v ,zero ) ); 232_mm_storeu_si128 ( (__m128i * )& a [2 ],_mm_unpackhi_epi32 (v ,zero ) ); 233return a ; 234 } 235 236bool PrintDiff ::tensorsFp32 (size_t idx ,const CStringA & name ,const float * A ,const float * B ,size_t length ,__m128i ne ,__m128i nb ) 237 { 238const int dims = tensorDims (ne ); 239const std::array < uint32_t ,4 > size = storeSize (ne ); 240const std::array < size_t ,4 > strides = storeStrides (ne ); 241CStringA line ; 242if (dims > 4 ) 243throw E_UNEXPECTED ; 244 245for (int i = 0 ;i < dims ;i ++ ) 246 { 247const char c = "xyzw" [i ]; 248line .AppendChar (c ); 249line .AppendChar ('\t' ); 250 } 251line += "A\tB\tA(hex)\tB(hex)\tdiff\n" ; 252printf ("%s" ,cstr (line ) ); 253 254if (0 == dims ) 255 { 256const float a = * A ; 257const float b = * B ; 258__m128 vf = _mm_setr_ps (a ,b ,0 ,0 ); 259__m128i vi = _mm_castps_si128 (vf ); 260const float diff = std::abs (a - b ); 261printf ("%g\t%g\t0x%08X\t0x%08X\t%g\n" , 262a ,b ,_mm_cvtsi128_si32 (vi ),_mm_extract_epi32 (vi ,1 ),diff ); 263return true; 264 } 265 266size_t offLayer2 = 0 ; 267for (uint32_t w = 0 ;w < size [3 ];w ++ ,offLayer2 += strides [3 ] ) 268 { 269size_t offLayer = offLayer2 ; 270for (uint32_t z = 0 ;z < size [2 ];z ++ ,offLayer += strides [2 ] ) 271 { 272size_t offRow = offLayer ; 273for (uint32_t y = 0 ;y < size [1 ];y ++ ,offRow += strides [1 ] ) 274 { 275size_t off = offRow ; 276for (uint32_t x = 0 ;x < size [0 ];x ++ ,off += strides [0 ] ) 277 { 278line .Format ("%i\t" ,x ); 279if (dims > 1 ) 280line .AppendFormat ("%i\t" ,y ); 281if (dims > 2 ) 282line .AppendFormat ("%i\t" ,z ); 283if (dims > 3 ) 284line .AppendFormat ("%i\t" ,w ); 285 286const float a = A [off ]; 287const float b = B [off ]; 288__m128 vf = _mm_setr_ps (a ,b ,0 ,0 ); 289__m128i vi = _mm_castps_si128 (vf ); 290const float diff = std::abs (a - b ); 291line .AppendFormat ("%g\t%g\t0x%08X\t0x%08X\t%g\n" , 292a ,b ,_mm_cvtsi128_si32 (vi ),_mm_extract_epi32 (vi ,1 ),diff ); 293printf ("%s" ,cstr (line ) ); 294 } 295 } 296 } 297 } 298return true; 299 } 300} 301 302HRESULT compareTraces (const CommandLineArgs & arguments ) 303{ 304const wchar_t * pathA = arguments .inputs [0 ]; 305const wchar_t * pathB = arguments .inputs [1 ]; 306 307TraceReader a ,b ; 308HRESULT hr = a .open (pathA ); 309if (FAILED (hr ) ) 310 { 311fwprintf (stderr ,L"Unable to load trace A from \"%s\"" ,pathA ); 312printError (hr ); 313return hr ; 314 } 315 316hr = b .open (pathB ); 317if (FAILED (hr ) ) 318 { 319fwprintf (stderr ,L"Unable to load trace B from \"%s\"" ,pathA ); 320printError (hr ); 321return hr ; 322 } 323 324wprintf (L"Trace A: %s\n" ,pathA ); 325wprintf (L"Trace B: %s\n" ,pathB ); 326const size_t sizeA = a .size (); 327const size_t sizeB = b .size (); 328const size_t count = std::min (sizeA ,sizeB ); 329 330if (arguments .printDiff >=0 ) 331 { 332if (arguments .printDiff >= (int64_t )count ) 333 { 334fprintf (stderr ,"Trace A has %zu entries, trace B %zu entries; entry %zu ain't there\n" , 335sizeA ,sizeB , (size_t )arguments .printDiff ); 336return E_INVALIDARG ; 337 } 338try 339 { 340PrintDiff a ,b }; 341compare (arguments .printDiff ); 342return S_OK ; 343 } 344catch (HRESULT hr ) 345 { 346return hr ; 347 } 348 } 349 350printf ("Trace A has %zu entries, trace B %zu entries, comparing first %zu\n" ,sizeA ,sizeB ,count ); 351 352try 353 { 354PrintSummary a ,b }; 355for (size_t i = 0 ;i < count ;i ++ ) 356if ( !compare (i ) ) 357return S_FALSE ; 358return S_OK ; 359 } 360catch (HRESULT hr ) 361 { 362return hr ; 363 } 364}