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 "ParallelForRunner.h" 3using namespace CpuCompute ; 4 5ParallelForRunner ::ParallelForRunner (int threads ) : 6maxThreads (threads ) 7{ 8if (maxThreads <=1 ) 9 { 10threadBuffers .resize (1 ); 11return ; 12 } 13 14work = CreateThreadpoolWork (& workCallbackStatic ,this ,nullptr ); 15if (nullptr == work ) 16throw getLastHr (); 17threadBuffers .resize (maxThreads ); 18} 19 20HRESULT ParallelForRunner ::setThreadsCount (int threads ) 21{ 22maxThreads = threads ; 23if (threads <=1 ) 24 { 25threadBuffers .resize (1 ); 26return S_OK ; 27 } 28 29threadBuffers .resize (maxThreads ); 30if (nullptr == work ) 31 { 32work = CreateThreadpoolWork (& workCallbackStatic ,this ,nullptr ); 33if (nullptr == work ) 34return getLastHr (); 35 } 36return S_OK ; 37} 38 39ParallelForRunner ::~ParallelForRunner () 40{ 41if (nullptr != work ) 42 { 43if (S_FALSE == status ) 44WaitForThreadpoolWorkCallbacks (work , FALSE ); 45CloseThreadpoolWork (work ); 46 } 47} 48 49namespace 50{ 51 thread_localuint32_t currentThreadIndex = UINT_MAX ; 52} 53 54void ParallelForRunner ::runBatch (size_t ith )noexcept 55{ 56currentThreadIndex = (uint32_t )ith ; 57const size_t begin = (ith * countItems ) /countThreads ; 58const size_t end = ( (ith + 1 )* countItems ) /countThreads ; 59 60HRESULT hr = E_UNEXPECTED ; 61try 62 { 63hr = computeRange -> compute (begin ,end ); 64 } 65catch (HRESULT code ) 66 { 67hr = code ; 68 } 69catch (const std::bad_alloc & ) 70 { 71hr = E_OUTOFMEMORY ; 72 } 73catch (const std::exception & ) 74 { 75hr = E_FAIL ; 76 } 77currentThreadIndex = UINT_MAX ; 78if (SUCCEEDED (hr ) ) 79return ; 80InterlockedCompareExchange (& status ,hr ,S_FALSE ); 81} 82 83void * ParallelForRunner ::threadLocalBuffer (size_t cb ) 84{ 85const uint32_t idx = currentThreadIndex ; 86if (idx < threadBuffers .size () ) 87 { 88ThreadBuffer & tb = threadBuffers [idx ]; 89if (tb .cb >=cb ) 90 { 91// We already have large enough buffer for the current thread 92return tb .memory .pointer (); 93 } 94tb .memory .deallocate (); 95check (tb .memory .allocate (cb ) ); 96tb .cb = cb ; 97return tb .memory .pointer (); 98 } 99if (idx != UINT_MAX ) 100throw E_BOUNDS ; 101else 102 { 103logError (u8"threadLocalBuffer() method only works from inside a pool callback" ); 104throw E_UNEXPECTED ; 105 } 106} 107 108void __stdcallParallelForRunner ::workCallbackStatic (PTP_CALLBACK_INSTANCE Instance ,void * pv ,PTP_WORK Work )noexcept 109{ 110ParallelForRunner & context = * (ParallelForRunner * )pv ; 111const size_t ith = (uint32_t )(InterlockedIncrement (& context .threadIndex ) ); 112context .runBatch (ith ); 113} 114 115HRESULT ParallelForRunner ::parallelFor (iComputeRange & compute ,size_t length ,size_t minBatch ) 116{ 117if (maxThreads <=1 ) 118 { 119currentThreadIndex = 0 ; 120const HRESULT hr1 = compute .compute (0 ,length ); 121currentThreadIndex = UINT_MAX ; 122return hr1 ; 123 } 124assert (minBatch > 0 ); 125 126size_t nth = length /minBatch ; 127nth = std::min (nth , (size_t )(uint32_t )maxThreads ); 128 129computeRange = & compute ; 130countItems = length ; 131countThreads = nth ; 132threadIndex = 0 ; 133status = S_FALSE ; 134 135for (size_t i = 1 ;i < nth ;i ++ ) 136SubmitThreadpoolWork (work ); 137runBatch (0 ); 138 139if (nth > 1 ) 140WaitForThreadpoolWorkCallbacks (work , FALSE ); 141 142computeRange = nullptr ; 143const HRESULT hr = status ; 144status = S_OK ; 145if (SUCCEEDED (hr ) ) 146return S_OK ; 147 148return hr ; 149}