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 "BufferAllocator.h" 3#include <immintrin.h> 4#include <ammintrin.h> 5using namespace CpuCompute ; 6 7HRESULT BufferAllocator ::create (size_t cb ) 8{ 9CHECK (buffer .allocate (cb ) ); 10head = 0 ; 11size = cb ; 12dbgMarkUninitializedMemory (buffer .pointer (),cb ); 13return S_OK ; 14} 15 16namespace 17{ 18// Round up the integer by 32 bytes 19 __forceinlinesize_t roundUpAlloc (size_t cb ) 20 { 21const size_t mask = 31 ; 22cb += mask ; 23// We require AVX1+FMA3 support, might as well use BMI1 24return _andn_u64 (mask ,cb ); 25 } 26} 27 28void * BufferAllocator ::allocate (size_t cb ,size_t align )noexcept 29{ 30assert (align <=32 ); 31cb = roundUpAlloc (cb ); 32 33uint8_t * pointer = buffer .pointer (); 34if (head + cb > size || nullptr == pointer ) 35 { 36logError (u8"BufferAllocator.allocate, not enough capacity" ); 37return nullptr ; 38 } 39 40void * const res = pointer + head ; 41head += cb ; 42assert (head <=size ); 43dbgMarkUninitializedMemory (res ,cb ); 44return res ; 45} 46 47namespace 48{ 49// 2 MB of memory, we hope the OS kernel will then be smart enough to give us large pages. 50constexpr size_t virtualAllocGranularityExp2 = 21 ; 51 52constexpr size_t virtualAllocGranularityMask = ( ( (size_t )1 ) <<virtualAllocGranularityExp2 )- 1 ; 53 54// Round up the integer by 2 megabytes 55 __forceinlinesize_t roundUpVirtualAlloc (size_t cb ) 56 { 57const size_t mask = virtualAllocGranularityMask ; 58cb += mask ; 59return _andn_u64 (mask ,cb ); 60 } 61} 62 63HRESULT VirtualAllocator ::create (size_t cb ) 64{ 65if (nullptr != pointer ) 66return HRESULT_FROM_WIN32 (ERROR_ALREADY_INITIALIZED ); 67cb = roundUpVirtualAlloc (cb ); 68pointer = (uint8_t * )VirtualAlloc (NULL ,cb ,MEM_RESERVE ,PAGE_READWRITE ); 69if (nullptr != pointer ) 70 { 71head = 0 ; 72sizeAllocated = 0 ; 73sizeVirtual = cb ; 74return S_OK ; 75 } 76 77const HRESULT hr = getLastHr (); 78logErrorHr (hr ,u8"VirtualAlloc failed" ); 79return hr ; 80} 81 82void * VirtualAllocator ::allocate (size_t cb ,size_t align )noexcept 83{ 84assert (align <=32 ); 85cb = roundUpAlloc (cb ); 86 87const size_t newHead = head + cb ; 88if (newHead <=sizeAllocated ) 89 { 90void * const res = pointer + head ; 91head = newHead ; 92dbgMarkUninitializedMemory (res ,cb ); 93return res ; 94 } 95 96if (newHead <=sizeVirtual ) 97 { 98uint8_t * const ptrCommit = pointer + sizeAllocated ; 99const size_t cbCommit = roundUpVirtualAlloc (newHead )- sizeAllocated ; 100void * const res = VirtualAlloc (ptrCommit ,cbCommit ,MEM_COMMIT ,PAGE_READWRITE ); 101if (nullptr != res ) 102 { 103sizeAllocated += cbCommit ; 104assert (sizeAllocated <=sizeVirtual ); 105void * const res = pointer + head ; 106head = newHead ; 107dbgMarkUninitializedMemory (res ,cb ); 108return res ; 109 } 110 111const HRESULT hr = getLastHr (); 112logErrorHr (hr ,u8"VirtualAllocator.allocate, VirtualAlloc failed" ); 113return nullptr ; 114 } 115 116logError (u8"VirtualAllocator.allocate, not enough arena capacity" ); 117return nullptr ; 118} 119 120VirtualAllocator ::~VirtualAllocator () 121{ 122if (nullptr == pointer ) 123return ; 124 125if (VirtualFree (pointer ,0 ,MEM_RELEASE ) ) 126 { 127pointer = nullptr ; 128return ; 129 } 130 131const HRESULT hr = getLastHr (); 132logErrorHr (hr ,u8"VirtualFree failed" ); 133} 134 135#ifndef NDEBUG 136// Reusing Microsoft's magic numbers: https://asawicki.info/news_1292_magic_numbers_in_visual_c 137void CpuCompute ::dbgMarkUninitializedMemory (void * pv ,size_t cb ) 138{ 139__stosb ( (uint8_t * )pv ,0xCD ,cb ); 140} 141void CpuCompute ::dbgMarkFreedMemory (void * pv ,size_t cb ) 142{ 143__stosd ( (DWORD * )pv ,0xFEEEFEEEu ,cb /4 ); 144} 145#endif