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

KonstantinPerformance improvement, `softMax` shader27dfc34

master
2.4 KiB100 linesraw
1// Dispatch [ nr, 1, 1 ] thread groups of this shader
2RWBuffer<float> result: register( u0 );
3
4cbuffer Constants: register( b0 )
5{
6	uint4 elements: packoffset( c0 );
7	uint4 strides: packoffset( c1 );
8	uint nr: packoffset( c2.x );
9	float inputScale: packoffset( c2.y );
10}
11
12#ifndef THREADS
13static const uint THREADS = 32;
14#endif
15
16groupshared float sharedAccumulators[ THREADS ];
17
18// Compute horizontal maximum of the numbers, and broadcast to all threads of the group.
19void horizontalMaxBroadcast( const uint thread, inout float ax )
20{
21	sharedAccumulators[ thread ] = ax;
22	for( uint i = THREADS / 2; i > 0; i /= 2 )
23	{
24		GroupMemoryBarrierWithGroupSync();
25		if( thread < i )
26		{
27			ax = max( ax, sharedAccumulators[ thread + i ] );
28			sharedAccumulators[ thread ] = ax;
29		}
30	}
31	GroupMemoryBarrierWithGroupSync();
32	ax = sharedAccumulators[ 0 ];
33}
34
35// Compute horisontal sum of the numbers. The result is only correct on the thread #0 of the group.
36void horizontalSum( const uint thread, inout float sum )
37{
38	sharedAccumulators[ thread ] = sum;
39	for( uint i = THREADS / 2; i > 1; i /= 2 )
40	{
41		GroupMemoryBarrierWithGroupSync();
42		if( thread < i )
43		{
44			sum += sharedAccumulators[ thread + i ];
45			sharedAccumulators[ thread ] = sum;
46		}
47	}
48	GroupMemoryBarrierWithGroupSync();
49	if( 0 == thread )
50		sum += sharedAccumulators[ 1 ];
51}
52
53static const float negativeInfinity = asfloat( 0xff800000 );
54
55[numthreads( THREADS, 1, 1 )]
56void main( uint3 group: SV_GroupID, uint thread : SV_GroupIndex )
57{
58	const uint p = group.x * strides[ 1 ];
59	const uint nc = elements[ 0 ];
60	const uint pEnd = p + nc;
61	uint i;
62
63	float m = negativeInfinity;
64	for( i = p + thread; i < pEnd; i += THREADS )
65		m = max( m, result[ i ] );
66	horizontalMaxBroadcast( thread, m );
67
68	float sum = 0;
69	for( i = p + thread; i < pEnd; i += THREADS )
70	{
71		float f = result[ i ];
72
73		[branch]
74		if( f != negativeInfinity )
75		{
76			f = ( f - m ) * inputScale;
77			// On both Radeon Graphics and nVidia 1080Ti, computing the exponent is slightly faster than loading from the lookup table
78			f = exp( f );
79			sum += f;
80		}
81		else
82			f = 0;
83
84		result[ i ] = f;
85	}
86
87	horizontalSum( thread, sum );
88	if( 0 == thread )
89		sharedAccumulators[ 0 ] = 1.0 / sum;
90	GroupMemoryBarrierWithGroupSync();
91	const float scale = sharedAccumulators[ 0 ];
92
93	// ggml_vec_scale_f32
94	for( i = p + thread; i < pEnd; i += THREADS )
95	{
96		float f = result[ i ];
97		f *= scale;
98		result[ i ] = f;
99	}
100}