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
e953396
master
1#include "stdafx.h" 2#include "device.h" 3#include <immintrin.h> 4#include <ammintrin.h> 5#pragma comment(lib, "D3D11.lib") 6#include "RenderDoc/renderDoc.h" 7#include "../API/eGpuModelFlags.h" 8 9namespace DirectCompute 10{ 11CComPtr < ID3D11Device > g_device ; 12CComPtr < ID3D11DeviceContext > g_context ; 13D3D_FEATURE_LEVEL g_featureLevel = (D3D_FEATURE_LEVEL )0 ; 14 15ID3D11Device * device () {return g_device ; } 16ID3D11DeviceContext * context () {return g_context ; } 17D3D_FEATURE_LEVEL featureLevel () {return g_featureLevel ; } 18 19void terminate () 20 { 21g_context = nullptr ; 22g_device = nullptr ; 23 } 24 25static HRESULT createDevice () 26 { 27if (g_device ) 28return S_FALSE ; 29 30const std::array < D3D_FEATURE_LEVEL ,4 > levels = {D3D_FEATURE_LEVEL_12_1 ,D3D_FEATURE_LEVEL_12_0 ,D3D_FEATURE_LEVEL_11_1 ,D3D_FEATURE_LEVEL_11_0 }; 31UINT flags = D3D11_CREATE_DEVICE_DISABLE_GPU_TIMEOUT |D3D11_CREATE_DEVICE_SINGLETHREADED ; 32bool renderDoc = initializeRenderDoc (); 33#ifdef _DEBUG 34if ( !renderDoc ) 35 { 36// Last time I checked, RenderDoc crashed with debug version of D3D11 runtime 37// Only setting this flag unless renderdoc.dll is loaded to the current process 38flags |=D3D11_CREATE_DEVICE_DEBUG ; 39 } 40#endif 41constexpr UINT levelsCount = (UINT )levels .size (); 42HRESULT hr = D3D11CreateDevice (nullptr ,D3D_DRIVER_TYPE_HARDWARE ,nullptr ,flags ,levels .data (),levelsCount ,D3D11_SDK_VERSION ,& g_device ,& g_featureLevel ,& g_context ); 43if (SUCCEEDED (hr ) ) 44return S_OK ; 45// D3D11_CREATE_DEVICE_DISABLE_GPU_TIMEOUT: This value is not supported until Direct3D 11.1 46// https://learn.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_create_device_flag 47flags = _andn_u32 (D3D11_CREATE_DEVICE_DISABLE_GPU_TIMEOUT ,flags ); 48 49hr = D3D11CreateDevice (nullptr ,D3D_DRIVER_TYPE_HARDWARE ,nullptr ,flags ,levels .data (),levelsCount ,D3D11_SDK_VERSION ,& g_device ,& g_featureLevel ,& g_context ); 50if (SUCCEEDED (hr ) ) 51return S_OK ; 52return hr ; 53 } 54 55sGpuInfo s_gpuInfo = {}; 56const sGpuInfo & gpuInfo = s_gpuInfo ; 57 58using Whisper ::eGpuModelFlags ; 59inline constexpr uint32_t operator|(eGpuModelFlags a ,eGpuModelFlags b ) 60 { 61return (uint32_t )a | (uint32_t )b ; 62 } 63inline bool operator& (uint32_t flags ,eGpuModelFlags bit ) 64 { 65return 0 != (flags & (uint32_t )bit ); 66 } 67inline bool merge3 (uint32_t flags ,eGpuModelFlags enabled ,eGpuModelFlags disabled ,bool def ) 68 { 69if (flags & enabled ) 70return true; 71if (flags & disabled ) 72return false; 73return def ; 74 } 75 76static HRESULT queryDeviceInfo (uint32_t flags ) 77 { 78if (nullptr == g_device ) 79return OLE_E_BLANK ; 80CComPtr < IDXGIDevice > dd ; 81CHECK (g_device .QueryInterface (& dd ) ); 82 83CComPtr < IDXGIAdapter > adapter ; 84CHECK (dd -> GetAdapter (& adapter ) ); 85 86DXGI_ADAPTER_DESC desc ; 87adapter -> GetDesc (& desc ); 88 89const size_t descLen = wcsnlen_s (desc .Description ,128 ); 90const wchar_t * rsi = & desc .Description [0 ]; 91s_gpuInfo .description .assign (rsi ,rsi + descLen ); 92s_gpuInfo .vendor = (eGpuVendor )desc .VendorId ; 93s_gpuInfo .device = (uint16_t )desc .DeviceId ; 94s_gpuInfo .revision = (uint16_t )desc .Revision ; 95s_gpuInfo .subsystem = desc .SubSysId ; 96s_gpuInfo .vramDedicated = desc .DedicatedVideoMemory ; 97s_gpuInfo .ramDedicated = desc .DedicatedSystemMemory ; 98s_gpuInfo .ramShared = desc .SharedSystemMemory ; 99 100// Set up these flags 101uint8_t ef = 0 ; 102const bool amd = (s_gpuInfo .vendor == eGpuVendor::AMD ); 103if (merge3 (flags , eGpuModelFlags::Wave64 , eGpuModelFlags::Wave32 ,amd ) ) 104ef |= (uint8_t )eGpuEffectiveFlags::Wave64 ; 105if (merge3 (flags , eGpuModelFlags::UseReshapedMatMul , eGpuModelFlags::NoReshapedMatMul ,amd ) ) 106ef |= (uint8_t )eGpuEffectiveFlags::ReshapedMatMul ; 107s_gpuInfo .flags = (eGpuEffectiveFlags )ef ; 108 109 110if (willLogMessage (Whisper ::eLogLevel::Debug ) ) 111 { 112const int fl = g_featureLevel ; 113const int flMajor = (fl >>12 )& 0xF ; 114const int flMinor = (fl >>8 )& 0xF ; 115 116logDebug16 (L"Using GPU \"%s\", feature level %i.%i, effective flags %S | %S" , 117s_gpuInfo .description .c_str (),flMajor ,flMinor , 118s_gpuInfo .wave64 () ?"Wave64" :"Wave32" , 119s_gpuInfo .useReshapedMatMul () ?"UseReshapedMatMul" :"NoReshapedMatMul" ); 120 } 121return S_OK ; 122 } 123 124static HRESULT validateFlags (uint32_t flags ) 125 { 126constexpr uint32_t waveBoth = eGpuModelFlags::Wave32 | eGpuModelFlags::Wave64 ; 127if ( (flags & waveBoth )== waveBoth ) 128 { 129logError (u8"eGpuModelFlags.%s and eGpuModelFlags.%s are mutually exclusive" ,"Wave32" ,"Wave64" ); 130return E_INVALIDARG ; 131 } 132 133constexpr uint32_t reshapedBoth = eGpuModelFlags::NoReshapedMatMul | eGpuModelFlags::UseReshapedMatMul ; 134if ( (flags & reshapedBoth )== reshapedBoth ) 135 { 136logError (u8"eGpuModelFlags.%s and eGpuModelFlags.%s are mutually exclusive" ,"NoReshapedMatMul" ,"UseReshapedMatMul" ); 137return E_INVALIDARG ; 138 } 139return S_OK ; 140 } 141 142HRESULT initialize (uint32_t flags ) 143 { 144CHECK (validateFlags (flags ) ); 145HRESULT hr = createDevice (); 146if (hr != S_OK ) 147return hr ; 148queryDeviceInfo (flags ); 149return S_OK ; 150 } 151 152__m128i __declspec(noinline )bufferMemoryUsage (ID3D11Buffer * buffer ) 153 { 154if (nullptr != buffer ) 155 { 156D3D11_BUFFER_DESC desc ; 157buffer -> GetDesc (& desc ); 158 159if (desc .Usage != D3D11_USAGE_STAGING ) 160return setHigh_size (desc .ByteWidth ); 161else 162return setLow_size (desc .ByteWidth ); 163 } 164return _mm_setzero_si128 (); 165 } 166 167__m128i __declspec(noinline )resourceMemoryUsage (ID3D11ShaderResourceView * srv ) 168 { 169if (nullptr != srv ) 170 { 171CComPtr < ID3D11Resource > res ; 172srv -> GetResource (& res ); 173CComPtr < ID3D11Buffer > buff ; 174if (SUCCEEDED (res .QueryInterface (& buff ) ) ) 175return bufferMemoryUsage (buff ); 176assert ( false );// We don't use textures in this project 177 } 178return _mm_setzero_si128 (); 179 } 180}