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

KonstantinSource codes8c4603c

master
2.2 KiB84 linesraw
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}