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