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 "parallelFor.h" 3 4namespace 5{ 6class alignas(64 )ParallelForContext 7 { 8volatile long threadIndex ; 9volatile HRESULT status ; 10 11 alignas(64 )void * const context ; 12const Whisper ::pfnParallelForCallback pfn ; 13 14static void __stdcall callbackStatic (PTP_CALLBACK_INSTANCE Instance ,PVOID pv ,PTP_WORK Work ); 15 16public : 17 18ParallelForContext (void * ctx ,Whisper ::pfnParallelForCallback pfn ); 19 20PTP_WORK createWork (); 21 22HRESULT getStatus ()const ; 23 }; 24 25ParallelForContext ::ParallelForContext (void * ctx ,Whisper ::pfnParallelForCallback callback ) : 26threadIndex (1 ), 27status (S_FALSE ), 28context (ctx ), 29pfn (callback ) 30 { } 31 32PTP_WORK ParallelForContext ::createWork () 33 { 34return CreateThreadpoolWork (& callbackStatic ,this ,nullptr ); 35 } 36 37void __stdcallParallelForContext ::callbackStatic (PTP_CALLBACK_INSTANCE Instance ,PVOID pv ,PTP_WORK Work ) 38 { 39ParallelForContext & context = * (ParallelForContext * )pv ; 40int ith = InterlockedIncrement (& context .threadIndex ); 41ith -- ; 42const HRESULT hr = context .pfn (ith ,context .context ); 43if (SUCCEEDED (hr ) ) 44return ; 45InterlockedCompareExchange (& context .status ,hr ,S_FALSE ); 46 } 47 48HRESULT ParallelForContext ::getStatus ()const 49 { 50const HRESULT hr = status ; 51if (SUCCEEDED (hr ) ) 52return S_OK ; 53return hr ; 54 } 55} 56 57namespace Whisper 58{ 59HRESULT parallelFor (pfnParallelForCallback pfn ,int threadsCount ,void * ctx ) 60 { 61if (threadsCount < 1 ) 62return E_BOUNDS ; 63if (threadsCount == 1 ) 64return pfn (0 ,ctx ); 65 66ParallelForContext context {ctx ,pfn }; 67 68PTP_WORK const pw = context .createWork (); 69if (nullptr == pw ) 70return getLastHr (); 71 72for (int i = 1 ;i < threadsCount ;i ++ ) 73SubmitThreadpoolWork (pw ); 74 75const HRESULT hr0 = pfn (0 ,ctx ); 76 77WaitForThreadpoolWorkCallbacks (pw , FALSE ); 78CloseThreadpoolWork (pw ); 79 80if (FAILED (hr0 ) ) 81return hr0 ; 82return context .getStatus (); 83 } 84} 85 86using namespace Whisper ; 87 88ThreadPoolWork ::~ThreadPoolWork () 89{ 90if (nullptr != work ) 91 { 92CloseThreadpoolWork (work ); 93work = nullptr ; 94 } 95} 96 97HRESULT ThreadPoolWork ::create () 98{ 99if (nullptr == work ) 100 { 101work = CreateThreadpoolWork (& callbackStatic ,this ,nullptr ); 102if (nullptr != work ) 103return S_OK ; 104return getLastHr (); 105 } 106return HRESULT_FROM_WIN32 (ERROR_ALREADY_INITIALIZED ); 107} 108 109HRESULT ThreadPoolWork ::parallelFor (int threadsCount )noexcept 110{ 111if (nullptr != work ) 112 { 113if (threadsCount <=1 ) 114return threadPoolCallback (0 ); 115 116threadIndex = 1 ; 117status = S_FALSE ; 118for (int i = 1 ;i < threadsCount ;i ++ ) 119SubmitThreadpoolWork (work ); 120 121const HRESULT hr0 = threadPoolCallback (0 ); 122 123WaitForThreadpoolWorkCallbacks (work , FALSE ); 124 125if (FAILED (hr0 ) ) 126return hr0 ; 127if (SUCCEEDED (status ) ) 128return S_OK ; 129return status ; 130 } 131 132return OLE_E_BLANK ; 133} 134 135void __stdcallThreadPoolWork ::callbackStatic (PTP_CALLBACK_INSTANCE Instance ,PVOID pv ,PTP_WORK Work ) 136{ 137ThreadPoolWork * tpw = (ThreadPoolWork * )pv ; 138int ith = InterlockedIncrement (& tpw -> threadIndex ); 139ith -- ; 140const HRESULT hr = tpw -> threadPoolCallback (ith ); 141if (SUCCEEDED (hr ) ) 142return ; 143InterlockedCompareExchange (& tpw -> status ,hr ,S_FALSE ); 144}