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
4.1 KiB170 linesraw
1// Ported from ggml_compute_forward_flash_attn_f16
2// Dispatch with [ neq1*neq2*neq3, 1, 1 ] thread groups
3
4#include "flashAttentionCommon.hlsli"
5Buffer<uint> lookupTable: register( t3 );
6#include "groupReduce.hlsli"
7
8inline void computeDotProduct( Buffer<float> buff0, Buffer<float> buff1, uint s0, uint s1, const uint len, const uint thread, inout float acc )
9{
10	acc = 0;
11	const uint s0End = s0 + len;
12	s0 += thread;
13	s1 += thread;
14	for( ; s0 < s0End; s0 += 32, s1 += 32 )
15		acc = mad( buff0[ s0 ], buff1[ s1 ], acc );
16
17	horizontalSum( thread, acc );
18}
19
20inline void computeDotProduct( Buffer<float> buff0, RWBuffer<float> buff1, uint s0, uint s1, const uint len, const uint thread, inout float acc )
21{
22	acc = 0;
23	const uint s0End = s0 + len;
24	s0 += thread;
25	s1 += thread;
26	for( ; s0 < s0End; s0 += 32, s1 += 32 )
27		acc = mad( buff0[ s0 ], buff1[ s1 ], acc );
28
29	horizontalSum( thread, acc );
30}
31
32void scaleTempVector( uint i, const uint length, const uint thread, const float multiplier, bool round )
33{
34	const uint end = i + length;
35	for( i += thread; i < end; i += 32 )
36	{
37		float f = temp[ i ];
38		f *= multiplier;
39		if( round )
40			f = roundToFp16( f );
41		temp[ i ] = f;
42	}
43}
44
45#include "miscUtils.hlsli"
46
47// Transform temp[ i ] = exp( temp[ i ] - tempMax ), and return the sum of these values
48inline float applySoftMax( uint i, const uint length, const uint thread, const float tempMax )
49{
50	// Transform the values, and compute per-thread sum
51	const uint end = i + length;
52	float sum = 0;
53	for( i += thread; i < end; i += 32 )
54	{
55		float f = temp[ i ];
56		[branch]
57		if( f != negativeInfinity )
58		{
59			f -= tempMax;
60			const uint index = fp16Rounded( f );
61			const uint res16 = lookupTable[ index ];
62			f = f16tof32( res16 );
63		}
64		else
65			f = 0;
66
67		temp[ i ] = f;
68		sum += f;
69	}
70
71	// Reduce per-thread sum to the global one, over all threads of the group
72	horizontalSumBroadcast( thread, sum );
73	return sum;
74}
75
76[ numthreads( 32, 1, 1 ) ]
77void main( uint3 group: SV_GroupID, uint thread : SV_GroupIndex )
78{
79	const uint neq0 = q_elements[ 0 ];
80	const uint neq1 = q_elements[ 1 ];
81	const uint neq2 = q_elements[ 2 ];
82	const uint neq3 = q_elements[ 3 ];
83
84	const uint nek0 = k_elements[ 0 ];
85	const uint nek1 = k_elements[ 1 ];
86
87	const uint nev1 = v_elements[ 1 ];
88
89	const uint ne0 = res_elements[ 0 ];
90	const uint ne1 = res_elements[ 1 ];
91
92	const uint nbk0 = k_strides[ 0 ];
93	const uint nbk1 = k_strides[ 1 ];
94	const uint nbk2 = k_strides[ 2 ];
95	const uint nbk3 = k_strides[ 3 ];
96
97	const uint nbq0 = q_strides[ 0 ];
98	const uint nbq1 = q_strides[ 1 ];
99	const uint nbq2 = q_strides[ 2 ];
100	const uint nbq3 = q_strides[ 3 ];
101
102	const uint nbv0 = v_strides[ 0 ];
103	const uint nbv1 = v_strides[ 1 ];
104	const uint nbv2 = v_strides[ 2 ];
105	const uint nbv3 = v_strides[ 3 ];
106
107	const uint nb0 = res_strides[ 0 ];
108	const uint nb1 = res_strides[ 1 ];
109	const uint nb2 = res_strides[ 2 ];
110	const uint nb3 = res_strides[ 3 ];
111
112	const uint D = neq0;
113	const uint N = neq1;
114	const uint P = nek1 - N;
115	const uint M = nek1;
116
117	const uint ir = group.x;
118	const uint iq3 = ir / ( neq2 * neq1 );
119	const uint iq2 = ( ir - iq3 * neq2 * neq1 ) / neq1;
120	const uint iq1 = ( ir - iq3 * neq2 * neq1 - iq2 * neq1 );
121
122	const uint tempIndex = ir * tempBufferStride;
123
124	uint ic;
125	float tvm = negativeInfinity;
126	const uint s1 = iq1 * nbq1 + iq2 * nbq2 + iq3 * nbq3;
127	uint s0 = iq2 * nbk2 + iq3 * nbk3;
128	for( ic = 0; ic < nek1; ic++, s0 += nbk1 )
129	{
130		if( masked )
131		{
132			if( ic > P + iq1 )
133			{
134				if( 0 == thread )
135					temp[ tempIndex + ic ] = negativeInfinity;
136				continue;
137			}
138		}
139
140		float dp;
141		computeDotProduct( k, q, s0, s1, neq0, thread, dp );
142		if( 0 == thread )
143		{
144			dp *= scale;
145			temp[ tempIndex + ic ] = dp;
146			tvm = max( tvm, dp );
147		}
148	}
149
150	if( 0 == thread )
151		sharedAccumulators[ 0 ] = tvm;
152	GroupMemoryBarrierWithGroupSync();
153	tvm = sharedAccumulators[ 0 ];
154
155	// Softmax
156	{
157		float sum = applySoftMax( tempIndex, M, thread, tvm );
158		scaleTempVector( tempIndex, M, thread, 1.0 / sum, true );
159	}
160
161	s0 = iq2 * nbv2 + iq3 * nbv3;
162	uint rdi = iq1 * nb1 + iq2 * nb2 + iq3 * nb3;
163	for( ic = 0; ic < nev1; ic++, s0 += nbv1, rdi += nb0 )
164	{
165		float dp;
166		computeDotProduct( v, temp, s0, tempIndex, nek1, thread, dp );
167		if( 0 == thread )
168			result[ rdi ] = dp;
169	}
170}