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

KonstantinMinor, logging and UXe953396

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