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#include "stdafx.h" 2#include "HybridLoader.h" 3using namespace CpuCompute ; 4using namespace ComLight ; 5 6static void populateDecodeTensorsMap (CAtlMap < CStringA ,Tensor *>& map ,int layersDec ,DecoderTensors & dec ) 7{ 8dec .layers .resize (layersDec ); 9 10map ["decoder.positional_embedding" ]= & dec .positionalEmbedding ; 11map ["decoder.token_embedding.weight" ]= & dec .tokenEmbedding ; 12map ["decoder.ln.weight" ]= & dec .ln .w ; 13map ["decoder.ln.bias" ]= & dec .ln .b ; 14 15CStringA tempString ; 16auto add = [& ](const char * name ,int i ,Tensor & t ) 17 { 18tempString .Format ("decoder.blocks.%i.%s" ,i ,name ); 19map [tempString ]= & t ; 20 }; 21 22auto add2 = [& ](const char * name ,int i ,TensorPair & tensors ) 23 { 24tempString .Format ("decoder.blocks.%i.%s.weight" ,i ,name ); 25map [tempString ]= & tensors .w ; 26tempString .Format ("decoder.blocks.%i.%s.bias" ,i ,name ); 27map [tempString ]= & tensors .b ; 28 }; 29 30for (int i = 0 ;i < layersDec ;i ++ ) 31 { 32auto & gpu = dec .layers [i ]; 33add2 ("mlp_ln" ,i ,gpu .mlpLn ); 34add2 ("mlp.0" ,i ,gpu .mlp0 ); 35add2 ("mlp.2" ,i ,gpu .mlp1 ); 36add2 ("attn_ln" ,i ,gpu .attnLn0 ); 37add2 ("attn.query" ,i ,gpu .attnQuery ); 38add ("attn.key.weight" ,i ,gpu .attnKey ); 39 40add2 ("attn.value" ,i ,gpu .attnValue ); 41add2 ("attn.out" ,i ,gpu .attnLn1 ); 42 43add2 ("cross_attn_ln" ,i ,gpu .crossAttnLn0 ); 44add2 ("cross_attn.query" ,i ,gpu .crossAttnQuery ); 45 46// These 3 tensors are used by the encode() method, to compute cross-attention buffers 47// Need them in VRAM even for the hybrid model 48// add( "cross_attn.key.weight", i, gpu.cross_attn_k_w ); 49// add2( "cross_attn.value", i, gpu.cross_attn_v_w, gpu.cross_attn_v_b ); 50add2 ("cross_attn.out" ,i ,gpu .crossAttnLn1 ); 51 } 52} 53 54HybridLoader ::HybridLoader (DecoderTensors & m ,int countLayers ) : 55destination (m ) 56{ 57populateDecodeTensorsMap (map ,countLayers ,destination ); 58pending .reserve (map .GetCount () ); 59} 60 61HRESULT HybridLoader ::setupTensor (const CStringA & name ,int n_dims ,int ftype ,const std::array < int ,4 >& ne ,ComLight ::iReadStream * stream ,int64_t & postponedBytes ) 62{ 63auto p = map .Lookup (name ); 64if (nullptr == p ) 65return S_FALSE ; 66 67Tensor & rdi = * p -> m_value ; 68PendingTensor & pt = pending .emplace_back (); 69 70__m128i vec = load16 (ne .data () ); 71vec = _mm_insert_epi32 (vec ,1 ,3 ); 72store16 (& rdi .ne ,vec ); 73rdi .setDenseStrides (); 74 75pt .destPointer = p -> m_value ; 76CHECK (stream -> getPosition (pt .streamOffset ) ); 77pt .bufferOffset = bufferBytes ; 78 79size_t cbElement ; 80if (ftype == 0 ) 81 { 82rdi .setType ( eDataType::FP32 ); 83cbElement = 4 ; 84 } 85else 86 { 87rdi .setType ( eDataType::FP16 ); 88cbElement = 2 ; 89 } 90 91const size_t totalElts = (size_t )(uint32_t )ne [0 ]* (uint32_t )ne [1 ]* (uint32_t )ne [2 ]; 92if (totalElts * cbElement > UINT_MAX ) 93return DISP_E_OVERFLOW ; 94 95size_t payloadBytes = cbElement * totalElts ; 96pt .payloadBytes = payloadBytes ; 97CHECK (stream -> seek (payloadBytes , eSeekOrigin::Current ) ); 98postponedBytes += (int64_t )payloadBytes ; 99 100payloadBytes = (payloadBytes + 31 )& ( ~( (size_t )31 ) ); 101bufferBytes += payloadBytes ; 102return S_OK ; 103} 104 105HRESULT HybridLoader ::completeLoad (ComLight ::iReadStream * stream ,iLoaderProgressSink & progressSink ) 106{ 107if (pending .size ()!= map .GetCount () ) 108 { 109logError (u8"Not all tensors loaded from model file - expected %zu, got %zu" ,map .GetCount (),pending .size () ); 110return E_INVALIDARG ; 111 } 112 113LargeBuffer buffer ; 114CHECK (buffer .allocate (bufferBytes ) ); 115 116uint8_t * rdi = buffer .pointer (); 117 118for (const auto & pt :pending ) 119 { 120if (pt .payloadBytes > INT_MAX ) 121return DISP_E_OVERFLOW ; 122CHECK (stream -> seek (pt .streamOffset , eSeekOrigin::Begin ) ); 123 124int written = 0 ; 125CHECK (stream -> read (rdi , (int )pt .payloadBytes ,written ) ); 126CHECK (progressSink .gotBytes ( (int64_t )pt .payloadBytes ) ); 127 128pt .destPointer -> setDataPointer (rdi ); 129 130const size_t cb = (pt .payloadBytes + 31 )& ( ~( (size_t )31 ) ); 131rdi += cb ; 132 } 133 134CHECK (buffer .setReadOnly (bufferBytes ) ); 135destination .setMemoryBuffer ( std::move (buffer ) ); 136 137constexpr double mulMb = 1.0 / (1 <<20 ); 138logDebug (u8"Loaded %zu decoder tensors, %g MB RAM" ,pending .size (),mulMb * (double )(int64_t )bufferBytes ); 139return S_OK ; 140}