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#pragma once 2// Matrix*matrix multiplication is the most expensive algorithm in the model, by far. 3// For this reason, the code in this source file, and in the mulMat.kernel.hpp header, is optimized for performance. Readability suffers. 4// The implementation is inspired by following two articles: 5// https://gist.github.com/nadavrot/5b35d44e8ba3dd718e595e40184d03f0 6// https://link.springer.com/article/10.1007/s11227-022-05003-3 7#include "ParallelForRunner.h" 8#include "Tensor.h" 9 10namespace CpuCompute 11{ 12// Abstract base class for all implementations, to reduce binary size 13class MulMatBase :public iComputeRange 14 { 15protected : 16// Pointers to the payload of the output matrix 17float * const resultPointer ; 18 19// Lengths of the dot products to compute, equal to width of both source matrices 20uint32_t length ; 21 22// Last 3 strides of the output matrix, expressed as count of elements. The first one is always 1 because the output matrix is continuous. 23std ::array < uint32_t ,3 > resultStrides ; 24 25// Size of the output matrix 26std ::array < uint32_t ,4 > resultSize ; 27 28// Pointers to the payload of the source matrices 29const void * const pa ; 30const void * const pb ; 31 32// Matrix strides, expressed as count of elements 33std ::array < uint32_t ,4 > stridesA ,stridesB ; 34 35// Total count of panels in the layer of the output matrix. 36// The last panel might be incomplete, with smaller height. 37// The thread-local buffer however is always complete, unused elements will be zeros. 38uint32_t countPanels ; 39 40// Complete tiles in the length of the panel 41uint32_t completeTilesPerPanel ; 42 43// Count of the last remainder columns in the panel, can be 0 44uint8_t lastColumnsInPanel ; 45 46// Same as panelHeightRegs template argument - height of the panels, in AVX vectors 47uint8_t panelHeightRegisters ; 48 49// Same as tileWidthFloats template argument - width of the tile, in floats 50uint8_t tileWidth ; 51 52// Method pointer to reshape a panel from the source matrix into a thread-local buffer 53using pfnTransposePanel = HRESULT (MulMatBase ::* )( uint16_t * rdi, size_t i, size_t m2, size_t m3 ) const; 54pfnTransposePanel pfnMakePanel; 55// The object which implements multithreading for this job, and supplies memory for thread-local buffers 56ParallelForRunner & runner; 57 58// Count of FP16 values in the thread-local panel buffer 59uint32_t floatsPerPanel () const 60{ 61return length * panelHeightRegisters * 8 ; 62} 63 64// Transpose a horizontal panel of the first matrix, when the rows are continuous in that matrix 65HRESULT transposePanel ( uint16_t * rdi, size_t i, size_t m2, size_t m3 ) const; 66HRESULT transposePanelAvx2 ( uint16_t * rdi, size_t i, size_t m2, size_t m3 ) const; 67// Copy a horizontal panel of the first matrix without transpose, for column major layout of that matrix 68HRESULT copyPanelColumnMajor8 ( uint16_t * rdi, size_t i, size_t m2, size_t m3 ) const; 69HRESULT copyPanelColumnMajor16 ( uint16_t * rdi, size_t i, size_t m2, size_t m3 ) const; 70HRESULT copyPanelColumnMajor32 ( uint16_t * rdi, size_t i, size_t m2, size_t m3 ) const; 71// Transpose a panel of the first matrix for irregular layout of that matrix, when neither rows nor columns are at sequential addresses. 72// This one ain't implemented yet. 73HRESULT gatherPanel ( uint16_t * rdi, size_t i, size_t m2, size_t m3 ) const; 74 75const uint16_t * getPanelA ( size_t i, size_t m2, size_t m3 ) const; 76// Pointer to the first element of the second source matrix in the specified layer 77const float * getLayerB ( size_t m2, size_t m3 ) const; 78 79// Pointer to the first element of the output tile of the result matrix 80float * getPanelDest ( size_t i, size_t m2, size_t m3 ) const 81{ 82float * rdi = resultPointer; 83rdi += m2 * resultStrides[ 1 ]; 84rdi += m3 * resultStrides[ 2 ]; 85rdi += i * panelHeightRegisters * 8 ; 86return rdi; 87} 88 89static const bool haveAvx2; 90public : 91MulMatBase ( Tensor & result, const Tensor & a, const Tensor & b, ParallelForRunner & pfor, uint8_t panelHeightRegs, uint8_t tileWidthFloats ); 92HRESULT run ( ParallelForRunner & pfor ); 93}; 94 95// This class actually contains the kernels implementations 96template < uint8_t panelHeightRegs, uint8_t tileWidthFloats > 97class MulMatImpl : public MulMatBase 98{ 99HRESULT __stdcall compute ( size_t i, size_t end ) const noexcept override final; 100 101public : 102MulMatImpl ( Tensor & result, const Tensor & a, const Tensor & b, ParallelForRunner & pfor ) : 103MulMatBase ( result, a, b, pfor, panelHeightRegs, tileWidthFloats ) 104 { } 105 }; 106}