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// This shader reshapes a matrix into the shape expected by mulMatTiledEx.hlsl and mulMatByRowTiledEx.hlsl compute shaders 2// It's called in runtime, also while loading models from disk. 3// So far, it's only used when running on AMD GPUs. 4#ifndef TILE_SIZE 5static const uint TILE_SIZE = 32 ; 6#endif 7 8// Input tensor 9Buffer < float > source :register ( t0 ); 10// Output tensor 11RWBuffer < float > result :register ( u0 ); 12 13cbuffer Constants :register ( b0 ) 14{ 15uint4 arg0Size :packoffset ( c0 ); 16uint4 arg0Strides :packoffset ( c1 ); 17// Count of elements per panel 18uint panelSize :packoffset ( c2 . y ); 19// Layer strides of the output matrix 20uint2 layerStrides :packoffset ( c2 . z ); 21} 22 23inline uint hadd ( uint2 v2 ) { return v2 . x + v2 . y ; } 24 25groupsharedfloat tileBuffer [ TILE_SIZE ][ TILE_SIZE ]; 26 27[ numthreads ( TILE_SIZE , 1 , 1 ) ] 28void main ( const uint3 group : SV_GroupID , const uint thread : SV_GroupIndex ) 29{ 30uint rdi = hadd ( group . yz * layerStrides ); 31rdi += group . x * panelSize ; 32rdi += thread ; 33 34uint rsi = hadd ( group . yz * arg0Strides . zw ); 35const uint baseY = group . x * TILE_SIZE ; 36const uint dispatchThread = baseY + thread ; 37// Reshaping into a column major horizontal panel, height = TILE_SIZE, width = width of the source matrix 38uint width = arg0Size . x ; 39// Usually TILE_SIZE; can be less for the last panel on the matrix when we need to generate zeros instead of loading these numbers 40const uint height = min ( TILE_SIZE , arg0Size . y - baseY ); 41 42if ( arg0Strides . x == 1 ) 43{ 44// The input matrix is row major, can improve performance with coalesced loads and group shared buffer. 45rsi += baseY * arg0Strides . y ; 46 47const uint widthCompleteTiles = width / TILE_SIZE ; 48 49if ( height < TILE_SIZE ) 50{ 51// This thread group was dispatched for the last panel of the matrix, it doesn't have enough rows 52// Write zeros to the corresponding elements of the groupshared buffer 53for ( uint j = height ; j < TILE_SIZE ; j ++ ) 54tileBuffer [ thread ][ j ] = 0.0 ; 55} 56 57for ( uint i = 0 ; i < widthCompleteTiles ; i ++ , rsi += TILE_SIZE ) 58{ 59// Load [ TILE_SIZE ] * [ TILE_SIZE ] block with fully coalesced loads, store to group shared buffer in transposed order 60uint rsiTile = rsi + thread ; 61uint j ; 62for ( j = 0 ; j < height ; j ++ , rsiTile += arg0Strides . y ) 63{ 64// Each iteration of the loop loads a row of [ TILE_SIZE ] elements from the corresponding row of the source tensor 65// Fully coalesced load 66float f = source [ rsiTile ]; 67// Random store but the local memory's fast, this works rather well in practice 68tileBuffer [ thread ][ j ] = f ; 69} 70 71GroupMemoryBarrierWithGroupSync (); 72 73// Copy from group shared buffer to output tensor 74for ( j = 0 ; j < TILE_SIZE ; j ++ , rdi += TILE_SIZE ) 75{ 76// Fully coalesced loads and stores 77float f = tileBuffer [ j ][ thread ]; 78result [ rdi ] = f ; 79} 80 81GroupMemoryBarrierWithGroupSync (); 82} 83 84width %=TILE_SIZE ; 85if ( 0 == width ) 86return ; 87rsi += thread * arg0Strides . y ; 88} 89else 90rsi += dispatchThread * arg0Strides . y ; 91 92for ( uint i = 0 ; i < width ; i ++ ) 93{ 94float f ; 95[ branch ] 96if ( thread < height ) 97f = source [ rsi ]; 98else 99f = 0.0 ; 100rsi += arg0Strides . x ; 101 102result [ rdi ] = f ; 103rdi += TILE_SIZE ; 104} 105}