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.0 KiB125 linesraw
1// Dispatch with [ neq1*neq2*neq3, 1, 1 ] thread groups
2#include "flashAttentionCommon.hlsli"
3#include "groupReduce.hlsli"
4
5inline void computeDotProduct( Buffer<float> buff0, Buffer<float> buff1, uint s0, uint s1, const uint len, const uint thread, inout float acc )
6{
7	acc = 0;
8	/*
9	const uint s0End = s0 + len;
10	s0 += thread;
11	s1 += thread;
12	for( ; s0 < s0End; s0 += 32, s1 += 32 )
13		acc = mad( buff0[ s0 ], buff1[ s1 ], acc );
14	horizontalSumCompatNew( thread, acc );
15	*/
16
17	const uint completeVectors = len / 32;
18	uint i;
19	for( i = 0; i < completeVectors; i++, s0 += 32, s1 += 32 )
20		acc = mad( buff0[ s0 + thread ], buff1[ s1 + thread ], acc );
21
22	horizontalSumCompatNew( thread, acc );
23
24	if( 0 == thread )
25	{
26		const uint rem = len % 32;
27		for( i = 0; i < rem; i++ )
28		{
29			precise float a = buff0[ s0 + i ];
30			precise float b = buff1[ s1 + i ];
31			precise float prod = a * b;
32			acc += prod;
33		}
34	}
35}
36
37void scaleTempVector( uint i, const uint length, const uint thread, const float multiplier )
38{
39	const uint end = i + length;
40	for( i += thread; i < end; i += 32 )
41	{
42		float f = temp[ i ];
43		f *= multiplier;
44		temp[ i ] = f;
45	}
46}
47
48[ numthreads( 32, 1, 1 ) ]
49void main( uint3 group: SV_GroupID, uint thread : SV_GroupIndex )
50{
51	const uint neq0 = q_elements[ 0 ];
52	const uint neq1 = q_elements[ 1 ];
53	const uint neq2 = q_elements[ 2 ];
54	const uint neq3 = q_elements[ 3 ];
55
56	const uint nek0 = k_elements[ 0 ];
57	const uint nek1 = k_elements[ 1 ];
58
59	const uint nev1 = v_elements[ 1 ];
60
61	const uint ne0 = res_elements[ 0 ];
62	const uint ne1 = res_elements[ 1 ];
63
64	const uint nbk0 = k_strides[ 0 ];
65	const uint nbk1 = k_strides[ 1 ];
66	const uint nbk2 = k_strides[ 2 ];
67	const uint nbk3 = k_strides[ 3 ];
68
69	const uint nbq0 = q_strides[ 0 ];
70	const uint nbq1 = q_strides[ 1 ];
71	const uint nbq2 = q_strides[ 2 ];
72	const uint nbq3 = q_strides[ 3 ];
73
74	const uint nbv0 = v_strides[ 0 ];
75	const uint nbv1 = v_strides[ 1 ];
76	const uint nbv2 = v_strides[ 2 ];
77	const uint nbv3 = v_strides[ 3 ];
78
79	const uint nb0 = res_strides[ 0 ];
80	const uint nb1 = res_strides[ 1 ];
81	const uint nb2 = res_strides[ 2 ];
82	const uint nb3 = res_strides[ 3 ];
83
84	const uint D = neq0;
85	const uint N = neq1;
86	const uint P = nek1 - N;
87	// const uint M = P + N;
88	const uint M = nek1;
89
90	const uint ir = group.x;
91	const uint iq3 = ir / ( neq2 * neq1 );
92	const uint iq2 = ( ir - iq3 * neq2 * neq1 ) / neq1;
93	const uint iq1 = ( ir - iq3 * neq2 * neq1 - iq2 * neq1 );
94
95	const uint tempIndex = ir * tempBufferStride;
96
97	uint ic;
98	for( ic = 0; ic < nek1; ic++ )
99	{
100		// k indices
101		const uint ik3 = iq3;
102		const uint ik2 = iq2;
103		const uint ik1 = ic;
104
105		// S indices
106		const uint i1 = ik1;
107
108		if( masked )
109		{
110			if( ic > P + iq1 )
111			{
112				if( 0 == thread )
113					temp[ tempIndex + ic ] = negativeInfinity;
114				continue;
115			}
116		}
117
118		const uint s0 = ik1 * nbk1 + ik2 * nbk2 + ik3 * nbk3;
119		const uint s1 = iq1 * nbq1 + iq2 * nbq2 + iq3 * nbq3;
120		float dp;
121		computeDotProduct( k, q, s0, s1, neq0, thread, dp );
122		if( 0 == thread )
123			temp[ tempIndex + ic ] = dp * scale;
124	}
125}