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// When GPUs are converting FP32 to FP16, they always truncate towards 0, documented there: 2// https://learn.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-data-conversion#conververting-from-a-higher-range-representation-to-a-lower-range-representation 3// Whisper code uses _mm_cvtps_ph( x, 0 ), the 0 stands for "Round to nearest even": https://www.felixcloutier.com/x86/vcvtps2ph 4// This function adjusts FP32 value making it so that truncation towards 0 results in the value equal to what CPU is doing 5inline float adjustFp16( const float src ) 6{ 7 const uint trunc16 = f32tof16( src ); 8 const float trunc32 = f16tof32( trunc16 ); 9 10 const uint truncExp = ( trunc16 >> 10 ) & 0x1F; 11 if( truncExp != 0x1F ) 12 { 13 const uint next16 = trunc16 + 1; 14 const float next32 = f16tof32( next16 ); 15 16 const float errTrunc = abs( src - trunc32 ); 17 const float errNext = abs( src - next32 ); 18 19 if( errTrunc < errNext ) 20 { 21 // Truncated was closer to the source 22 return src; 23 } 24 else if( errTrunc > errNext ) 25 { 26 // Truncated + 1 was closer to the source 27 return next32; 28 } 29 else 30 { 31 // Exactly half, doing banker's rounding to nearest even 32 return ( 0 == ( trunc16 & 1 ) ) ? src : next32; 33 } 34 } 35 else 36 { 37 // INF or NAN 38 return src; 39 } 40} 41 42// Convert FP32 number to FP16, using rounding to nearest 43inline uint fp16Rounded( const float src ) 44{ 45 const uint trunc16 = f32tof16( src ); 46 const float trunc32 = f16tof32( trunc16 ); 47 48 const uint truncExp = ( trunc16 >> 10 ) & 0x1F; 49 if( truncExp != 0x1F ) 50 { 51 const uint next16 = trunc16 + 1; 52 const float next32 = f16tof32( next16 ); 53 54 const float errTrunc = abs( src - trunc32 ); 55 const float errNext = abs( src - next32 ); 56 57 if( errTrunc < errNext ) 58 { 59 // Truncated was closer to the source 60 return trunc16; 61 } 62 else if( errTrunc > errNext ) 63 { 64 // Truncated + 1 was closer to the source 65 return next16; 66 } 67 else 68 { 69 // Exactly half, doing banker's rounding to nearest even 70 return ( 0 == ( trunc16 & 1 ) ) ? trunc16 : next16; 71 } 72 } 73 else 74 { 75 // INF or NAN 76 return trunc16; 77 } 78} 79 80// Round up the number to be a multiple of 32 81inline uint roundUp32( uint x ) 82{ 83 return ( x + 31 ) & ( ~31u ); 84}