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
3.2 KiB124 linesraw
1// Ported from ggml_compute_forward_norm_f32
2// Dispatch [ ne01, ne02, ne03 ] thread groups of this shader
3Buffer<float> arg0: register( t0 );
4RWBuffer<float> result: register( u0 );
5
6cbuffer Constants: register( b0 )
7{
8	uint4 src0_elements: packoffset( c0 );
9	uint4 src0_strides: packoffset( c1 );
10	uint4 result_strides: packoffset( c3 );
11}
12
13static const float eps = 1e-5f; // TODO: make this a parameter
14
15// #include "groupReduce.hlsli"
16
17#ifndef THREADS
18static const uint THREADS = 32;
19#endif
20static const uint ROW_LENGTH = 1024;
21groupshared float rowBuffer[ ROW_LENGTH ];
22
23static const uint REDUCTION_BUFFER = 32;
24groupshared float sharedAccumulators[ REDUCTION_BUFFER ];
25
26// Compute horisontal sum of the numbers. The result is only correct on the thread #0 of the group.
27void horizontalSum( const uint thread, inout float sum )
28{
29	if( THREADS > REDUCTION_BUFFER )
30	{
31		for( uint t = REDUCTION_BUFFER; t < THREADS; t += REDUCTION_BUFFER )
32		{
33			// Threads [ t .. t + REDUCTION_BUFFER ] store into the buffer
34			if( thread >= t && thread < t + REDUCTION_BUFFER )
35				sharedAccumulators[ thread - t ] = sum;
36
37			GroupMemoryBarrierWithGroupSync();
38
39			// Threads [ 0 .. REDUCTION_BUFFER ] increment their local sum with the value loaded from the buffer
40			if( thread < REDUCTION_BUFFER )
41				sum += sharedAccumulators[ thread ];
42		}
43	}
44
45	if( thread < REDUCTION_BUFFER )
46		sharedAccumulators[ thread ] = sum;
47
48	for( uint i = REDUCTION_BUFFER / 2; i > 1; i /= 2 )
49	{
50		GroupMemoryBarrierWithGroupSync();
51		if( thread < i )
52		{
53			sum += sharedAccumulators[ thread + i ];
54			sharedAccumulators[ thread ] = sum;
55		}
56	}
57
58	GroupMemoryBarrierWithGroupSync();
59	if( 0 == thread )
60		sum += sharedAccumulators[ 1 ];
61}
62
63[ numthreads( THREADS, 1, 1 ) ]
64void main( uint3 group: SV_GroupID, uint thread : SV_GroupIndex )
65{
66	const uint i03 = group.z;
67	const uint i02 = group.y;
68	const uint i01 = group.x;
69	const uint ne00 = ROW_LENGTH;
70
71	// First pass: copy the data to local buffer, and compute sum
72	{
73		const uint nb01 = src0_strides[ 1 ];
74		const uint nb02 = src0_strides[ 2 ];
75		const uint nb03 = src0_strides[ 3 ];
76		const uint p = i01 * nb01 + i02 * nb02 + i03 * nb03;
77
78		float sum = 0;
79		for( uint i = thread; i < ne00; i += THREADS )
80		{
81			float f = arg0[ p + i ];
82			rowBuffer[ i ] = f;
83			sum += f;
84		}
85		horizontalSum( thread, sum );
86		if( 0 == thread )
87			sharedAccumulators[ 0 ] = sum / (float)(int)ne00;
88		GroupMemoryBarrierWithGroupSync();
89	}
90
91	// Second pass: offset and compute sum of squares
92	{
93		const float mean = sharedAccumulators[ 0 ];
94		float sum2 = 0;
95		for( uint i = thread; i < ne00; i += THREADS )
96		{
97			float v = rowBuffer[ i ];
98			v -= mean;
99			rowBuffer[ i ] = v;
100			sum2 = mad( v, v, sum2 );
101		}
102		horizontalSum( thread, sum2 );
103		if( 0 == thread )
104			sharedAccumulators[ 0 ] = 1.0 / sqrt( sum2 / (float)(int)ne00 + eps );
105		GroupMemoryBarrierWithGroupSync();
106	}
107
108	// Final pass: apply the scale, and copy from group shared buffer to the destination
109	{
110		const float scale = sharedAccumulators[ 0 ];
111
112		const uint nb1 = result_strides[ 1 ];
113		const uint nb2 = result_strides[ 2 ];
114		const uint nb3 = result_strides[ 3 ];
115		const uint y = i01 * nb1 + i02 * nb2 + i03 * nb3;
116
117		for( uint i = thread; i < ne00; i += THREADS )
118		{
119			float v = rowBuffer[ i ];
120			v *= scale;
121			result[ y + i ] = v;
122		}
123	}
124}