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 <intrin.h> 3#include "mulMatImpl.h" 4#include "mulMatUtils.hpp" 5using namespace CpuCompute ; 6 7// We want to keep code size reasonable, that's why these panel reshaping methods are in the base class 8HRESULT MulMatBase ::transposePanel (uint16_t * rdi ,size_t i ,size_t m2 ,size_t m3 )const 9{ 10assert (stridesA [0 ]== 1 ); 11 12const size_t heightFloats = (size_t )panelHeightRegisters * 8 ; 13i *=heightFloats ; 14 15const uint16_t * rsi = (const uint16_t * )pa ; 16rsi += m3 * stridesA [3 ]; 17rsi += m2 * stridesA [2 ]; 18rsi += i * stridesA [1 ]; 19 20const size_t resultStride = heightFloats ; 21 22if (i + heightFloats <=resultSize [0 ] ) 23 { 24// A complete panel 25for (size_t i = 0 ;i < panelHeightRegisters ;i ++ ) 26 { 27transpose8 (rdi ,length ,rsi ,stridesA [1 ],resultStride ); 28// Advance by 8 floats in the output buffer 29rdi += 8 ; 30// Advance by 8 rows in the source matrix 31rsi += 8 * stridesA [1 ]; 32 } 33 } 34else 35 { 36// A partial panel, at the bottom of the first argument matrix 37const size_t remainder = resultSize [0 ]- i ; 38assert (remainder > 0 && remainder < heightFloats ); 39zeroAlignedMemory (rdi ,resultStride * length * sizeof (uint16_t ) ); 40 41const size_t completePanels = remainder /8 ; 42for (size_t i = 0 ;i < completePanels ;i ++ ) 43 { 44transpose8 (rdi ,length ,rsi ,stridesA [1 ],resultStride ); 45rdi += 8 ; 46rsi += 8 * stridesA [1 ]; 47 } 48const size_t lastPanel = remainder %8 ; 49if (0 != lastPanel ) 50transpose8Partial (rdi ,length ,lastPanel ,rsi ,stridesA [1 ],resultStride ); 51 } 52return S_OK ; 53} 54 55inline const uint16_t * MulMatBase ::getPanelA (size_t i ,size_t m2 ,size_t m3 )const 56{ 57const uint16_t * rsi = (const uint16_t * )pa ; 58rsi += m3 * stridesA [3 ]; 59rsi += m2 * stridesA [2 ]; 60rsi += i * stridesA [1 ]; 61return rsi ; 62} 63 64HRESULT MulMatBase ::copyPanelColumnMajor8 (uint16_t * rdi ,size_t i ,size_t m2 ,size_t m3 )const 65{ 66assert (stridesA [1 ]== 1 ); 67assert (panelHeightRegisters == 1 ); 68 69constexpr size_t heightFloats = 8 ; 70i *=heightFloats ; 71const uint16_t * rsi = getPanelA (i ,m2 ,m3 ); 72 73constexpr size_t resultStride = heightFloats ; 74 75if (i + heightFloats <=resultSize [0 ] ) 76 { 77// A complete panel, height = 8 elements 78copyColumnMajor (rdi ,length ,rsi ,stridesA [0 ],resultStride ); 79 } 80else 81 { 82// A partial panel, at the bottom of the first argument matrix 83const size_t remainder = resultSize [0 ]- i ; 84assert (remainder > 0 && remainder < heightFloats ); 85copyColumnMajorPartial (rdi ,length ,remainder ,rsi ,stridesA [0 ],resultStride ); 86 } 87return S_OK ; 88} 89 90__forceinline__m128i load8Partial (const uint16_t * x ,size_t len ) 91{ 92assert (len > 0 && len < 8 ); 93__m128i ix = _mm_setzero_si128 (); 94switch (len ) 95 { 96case 1 :// load 2 bytes 97ix = _mm_cvtsi32_si128 (* x ); 98break ; 99case 2 :// load 4 bytes 100ix = _mm_cvtsi32_si128 (* (const int * )x ); 101break ; 102case 3 :// load 6 bytes 103ix = _mm_cvtsi32_si128 (* (const int * )x ); 104ix = _mm_insert_epi16 (ix ,x [2 ],2 ); 105break ; 106case 4 :// load 8 bytes 107ix = _mm_cvtsi64_si128 (* (const int64_t * )x ); 108break ; 109case 5 :// load 10 bytes 110ix = _mm_cvtsi64_si128 (* (const int64_t * )x ); 111ix = _mm_insert_epi16 (ix ,x [4 ],4 ); 112break ; 113case 6 :// load 12 bytes 114ix = _mm_cvtsi64_si128 (* (const int64_t * )x ); 115ix = _mm_insert_epi32 (ix ,* (const int * )(x + 4 ),2 ); 116break ; 117case 7 :// load 14 bytes 118ix = _mm_cvtsi64_si128 (* (const int64_t * )x ); 119ix = _mm_insert_epi32 (ix ,* (const int * )(x + 4 ),2 ); 120ix = _mm_insert_epi16 (ix ,x [6 ],6 ); 121break ; 122 } 123return ix ; 124} 125 126__forceinline__m256i load16Partial (const uint16_t * rsi ,size_t len ) 127{ 128assert (len > 0 && len < 16 ); 129 130if (len < 8 ) 131 { 132__m128i low = load8Partial (rsi ,len ); 133return _mm256_setr_m128i (low ,_mm_setzero_si128 () ); 134 } 135else if (len > 8 ) 136 { 137__m128i low = load16 ( (const int * )rsi ); 138__m128i high = load8Partial (rsi + 8 ,len - 8 ); 139return _mm256_setr_m128i (low ,high ); 140 } 141else 142 { 143__m128i low = load16 ( (const int * )rsi ); 144return _mm256_setr_m128i (low ,_mm_setzero_si128 () ); 145 } 146} 147 148HRESULT MulMatBase ::copyPanelColumnMajor16 (uint16_t * rdi ,size_t i ,size_t m2 ,size_t m3 )const 149{ 150assert (stridesA [1 ]== 1 ); 151assert (panelHeightRegisters == 2 ); 152 153constexpr size_t heightFloats = 16 ; 154i *=heightFloats ; 155 156const uint16_t * rsi = getPanelA (i ,m2 ,m3 ); 157uint16_t * const rdiEnd = rdi + 16 * length ; 158 159if (i + heightFloats <=resultSize [0 ] ) 160 { 161// A complete panel, height = 16 elements 162for ( ;rdi < rdiEnd ;rdi += 16 ,rsi += stridesA [0 ] ) 163 { 164__m256i v = _mm256_loadu_si256 ( (const __m256i * )rsi ); 165_mm256_store_si256 ( (__m256i * )rdi ,v ); 166 } 167 } 168else 169 { 170// A partial panel, at the bottom of the first argument matrix 171const size_t remainder = resultSize [0 ]- i ; 172assert (remainder > 0 && remainder < heightFloats ); 173 174for ( ;rdi < rdiEnd ;rdi += 16 ,rsi += stridesA [0 ] ) 175 { 176__m256i v = load16Partial (rsi ,remainder ); 177_mm256_store_si256 ( (__m256i * )rdi ,v ); 178 } 179 } 180return S_OK ; 181} 182 183HRESULT MulMatBase ::copyPanelColumnMajor32 (uint16_t * rdi ,size_t i ,size_t m2 ,size_t m3 )const 184{ 185assert (stridesA [1 ]== 1 ); 186assert (panelHeightRegisters == 4 ); 187 188constexpr size_t heightFloats = 32 ; 189i *=heightFloats ; 190 191const uint16_t * rsi = getPanelA (i ,m2 ,m3 ); 192uint16_t * const rdiEnd = rdi + 32 * length ; 193 194if (i + heightFloats <=resultSize [0 ] ) 195 { 196// A complete panel, height = 32 elements 197for ( ;rdi < rdiEnd ;rdi += 32 ,rsi += stridesA [0 ] ) 198 { 199__m256i v = _mm256_loadu_si256 ( (const __m256i * )rsi ); 200_mm256_store_si256 ( (__m256i * )rdi ,v ); 201v = _mm256_loadu_si256 ( (const __m256i * )(rsi + 16 ) ); 202_mm256_store_si256 ( (__m256i * )(rdi + 16 ),v ); 203 } 204 } 205else 206 { 207// A partial panel, at the bottom of the first argument matrix 208const size_t remainder = resultSize [0 ]- i ; 209assert (remainder > 0 && remainder < heightFloats ); 210 211// _mm256_setzero_si256 probably compiles into vpxor, that's AVX2, we don't want that here 212const __m256 zero = _mm256_setzero_ps (); 213 214for ( ;rdi < rdiEnd ;rdi += 32 ,rsi += stridesA [0 ] ) 215 { 216if (remainder < 16 ) 217 { 218__m256i v = load16Partial (rsi ,remainder ); 219_mm256_store_si256 ( (__m256i * )rdi ,v ); 220_mm256_store_ps ( (float * )(rdi + 16 ),zero ); 221 } 222else if (remainder > 16 ) 223 { 224__m256i v = _mm256_loadu_si256 ( (const __m256i * )rsi ); 225_mm256_store_si256 ( (__m256i * )rdi ,v ); 226v = load16Partial (rsi + 16 ,remainder - 16 ); 227_mm256_store_si256 ( (__m256i * )(rdi + 16 ),v ); 228 } 229else 230 { 231__m256i v = _mm256_loadu_si256 ( (const __m256i * )rsi ); 232_mm256_store_si256 ( (__m256i * )rdi ,v ); 233_mm256_store_ps ( (float * )(rdi + 16 ),zero ); 234 } 235 } 236 } 237return S_OK ; 238} 239 240HRESULT MulMatBase ::gatherPanel (uint16_t * rdi ,size_t i ,size_t m2 ,size_t m3 )const 241{ 242// BTW, I never saw this method called. 243const size_t heightFloats = (size_t )panelHeightRegisters * 8 ; 244const size_t length = this -> length ; 245 246zeroAlignedMemory (rdi ,length * heightFloats * sizeof (uint16_t ) ); 247 248const size_t height = std::min (heightFloats ,resultSize [0 ]- i ); 249const size_t strideElement = stridesA [0 ]; 250const size_t strideRow = stridesA [1 ]; 251const uint16_t * rsi = getPanelA (i * heightFloats ,m2 ,m3 ); 252 253if (strideElement < strideRow ) 254 { 255for (size_t r = 0 ;r < height ;r ++ ,rsi += strideRow ,rdi ++ ) 256 { 257const uint16_t * sourceRow = rsi ; 258uint16_t * destRow = rdi ; 259for (size_t c = 0 ;c < length ;c ++ ,sourceRow += strideElement ,destRow += heightFloats ) 260* destRow = * sourceRow ; 261 } 262 } 263else 264 { 265for (size_t c = 0 ;c < length ;c ++ ,rsi += strideElement ,rdi += heightFloats ) 266 { 267const uint16_t * sourceCol = rsi ; 268uint16_t * destCol = rdi ; 269for (size_t r = 0 ;r < height ;r ++ ,sourceCol += strideRow ,destCol ++ ) 270* destCol = * sourceCol ; 271 } 272 } 273return S_OK ; 274}