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

KonstantinSource codes8c4603c

master
4.4 KiB106 linesraw
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
13	class MulMatBase : public iComputeRange
14	{
15	protected:
16		// Pointers to the payload of the output matrix
17		float* const resultPointer;
18
19		// Lengths of the dot products to compute, equal to width of both source matrices
20		uint32_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.
23		std::array<uint32_t, 3> resultStrides;
24
25		// Size of the output matrix
26		std::array<uint32_t, 4> resultSize;
27
28		// Pointers to the payload of the source matrices
29		const void* const pa;
30		const void* const pb;
31
32		// Matrix strides, expressed as count of elements
33		std::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.
38		uint32_t countPanels;
39
40		// Complete tiles in the length of the panel
41		uint32_t completeTilesPerPanel;
42
43		// Count of the last remainder columns in the panel, can be 0
44		uint8_t lastColumnsInPanel;
45
46		// Same as panelHeightRegs template argument - height of the panels, in AVX vectors
47		uint8_t panelHeightRegisters;
48
49		// Same as tileWidthFloats template argument - width of the tile, in floats
50		uint8_t tileWidth;
51
52		// Method pointer to reshape a panel from the source matrix into a thread-local buffer
53		using pfnTransposePanel = HRESULT( MulMatBase::* )( uint16_t* rdi, size_t i, size_t m2, size_t m3 ) const;
54		pfnTransposePanel pfnMakePanel;
55		// The object which implements multithreading for this job, and supplies memory for thread-local buffers
56		ParallelForRunner& runner;
57
58		// Count of FP16 values in the thread-local panel buffer
59		uint32_t floatsPerPanel() const
60		{
61			return length * panelHeightRegisters * 8;
62		}
63
64		// Transpose a horizontal panel of the first matrix, when the rows are continuous in that matrix
65		HRESULT transposePanel( uint16_t* rdi, size_t i, size_t m2, size_t m3 ) const;
66		HRESULT 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
68		HRESULT copyPanelColumnMajor8( uint16_t* rdi, size_t i, size_t m2, size_t m3 ) const;
69		HRESULT copyPanelColumnMajor16( uint16_t* rdi, size_t i, size_t m2, size_t m3 ) const;
70		HRESULT 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.
73		HRESULT gatherPanel( uint16_t* rdi, size_t i, size_t m2, size_t m3 ) const;
74
75		const 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
77		const float* getLayerB( size_t m2, size_t m3 ) const;
78
79		// Pointer to the first element of the output tile of the result matrix
80		float* getPanelDest( size_t i, size_t m2, size_t m3 ) const
81		{
82			float* rdi = resultPointer;
83			rdi += m2 * resultStrides[ 1 ];
84			rdi += m3 * resultStrides[ 2 ];
85			rdi += i * panelHeightRegisters * 8;
86			return rdi;
87		}
88
89		static const bool haveAvx2;
90	public:
91		MulMatBase( Tensor& result, const Tensor& a, const Tensor& b, ParallelForRunner& pfor, uint8_t panelHeightRegs, uint8_t tileWidthFloats );
92		HRESULT run( ParallelForRunner& pfor );
93	};
94
95	// This class actually contains the kernels implementations
96	template<uint8_t panelHeightRegs, uint8_t tileWidthFloats>
97	class MulMatImpl : public MulMatBase
98	{
99		HRESULT __stdcall compute( size_t i, size_t end ) const noexcept override final;
100
101	public:
102		MulMatImpl( Tensor& result, const Tensor& a, const Tensor& b, ParallelForRunner& pfor ) :
103			MulMatBase( result, a, b, pfor, panelHeightRegs, tileWidthFloats )
104		{ }
105	};
106}