📝

Draft article

This draft is visible to admins and superusers only. Sign in with an authorized account.

← Мақалаларға оралу
July 7, 2026
5 мин оқу

GPU қашан өзін ақтайды: параметрлік іздеудің roofline моделі, немесе жарнамалық 167x шын мәнінде 27x алгоритм мен 6.2x аппараттық ұтыстың көбейтіндісі

GPU қашан өзін ақтайды: параметрлік іздеудің roofline моделі, немесе жарнамалық 167x шын мәнінде 27x алгоритм мен 6.2x аппараттық ұтыстың көбейтіндісі
#algotrading
#backtest
#өнімділік
#gpu
#roofline
#оңтайландыру
Part 9 of 10 · Collection
High-Performance Backtest Engines

"Иллюзиясыз бэктестер" сериясының бір бөлігі.

Жылдамдық баспалдағы әдейі көңіл толмас нотамен аяқталған еді. Біз 80 комбинациялық параметрлік іздеуді ноутбук CPU-ында pandas-тың 69.9 секундынан параллель numba-ның 0.23 секундына дейін жеткізіп — өлшенген 298x — сосын GPU жетіспей тұрған саты емес деп дауласқанбыз. Пікірлер бөлімі мұны үнсіз қабылдаған жоқ, және дұрыс істеді. "Жетіспей тұрған саты емес" — бұл бір жүктеме, бір көлем туралы тұжырым. Табиғат заңы емес. Сондықтан бұл мақала адал жолмен жүріп, GPU-ды сынақ орындығына отырғызады.

Нәтиже — үкім емес, қисық. GPU-ның CPU-дан алшақтығы — слайдқа басып шығара салатын жалғыз сан емес; ол — бір шақыруда оған қанша жұмыс тапсырғаныңыздың функциясы. Біздің көп таймфреймді индикаторларды алдын ала есептеуде GPU-ның CPU қозғалтқышынан жеделдеуі бір-бірлеп параметр комбинациясын сұрағанда 54.5x-тен бірден 61 комбинация сұрағанда 359.6x-ке дейін созылады. Сол баяғы ядро, сол баяғы деректер, сол баяғы аппараттық құрал — өзгерген жалғыз нәрсе — топтама (batch). Осы сандардың бірін жариялап, екіншісін жасыратын бенчмарк GPU-ды өлшеп отырған жоқ, айдар таңдап отыр.

Тіпті 359.6x-тің өзі көрінгендей емес. Оны қабат-қабат ашсаңыз, көп таймфреймді үлкен жарнамалық көрсеткіш 167x 27x алгоритмге — CPU-ды да 27x жылдамдататын қайта жазуға — көбейтілген 6.2x нақты аппараттық ұтысқа жіктеледі. 27x-ті GPU жасаған жоқ. Математика жасады. Бұл мақала — осы екеуін ажырата білу туралы, өйткені оларды шатастыру — git commit тегін-ақ шешер мәселеге $2,000 тұратын графикалық картаны сатудың дәл жолы.

Деректердің төркіні: төмендегі барлық сан Apple M2 Max-та өлшенген — Metal GPU-дағы MLX арқылы fp32 он екі CPU ағынындағы fp64 numba-ға қарсы — біздің engine_multitf_gpu.py мен bench_param_sweep.py бенчмарк скриптерінен алынған, әрқайсысы GPU мен CPU жолдары бірдей мәмілелер шығаратынын растайтын эквиваленттілік тексерісімен қорғалған. Бұл мақалаға жария серіктес еңбек жоқ — жазба ретінде скриптердің өзі қызмет етеді.

Сұрақ — бенчмарк емес, roofline

Roofline диаграммасы: оң жақта есептеудің жазық төбесі, сол жақта жад өткізу қабілетінің тік еңісі және үстеме шығын үстемдік ететін бұрыштан жота нүктесіне қарай еңіспен өрмелеп бара жатқан топтама нүктесі

"GPU қаншалықты жылдам" деген сұрақтың жалғыз жауабы жоқтығының себебі — roofline моделі (Williams, Waterman & Patterson, 2009). Процессордың қол жеткізе алатын өнімділігін бір мезгілде екі төбе шектейді: бірі — шыңдық есептеу қуаты (FLOP/s) белгілейтін жазық төбе, екіншісі — жад өткізу қабілеті мен арифметикалық қарқындылықтың, яғни тасымалданған әр байтқа шаққандағы пайдалы операциялар санының, көбейтіндісі белгілейтін еңіс төбе. Әр байтқа шаққанда арзан жұмыс еңіс төбенің астында өмір сүреді және өткізу қабілетімен шектеледі (bandwidth-bound); әр байтқа бай жұмыс жазық төбеге жетеді және есептеумен шектеледі (compute-bound). GPU-ның жазық төбесі CPU-дікінен мұнарадай асқақтайды, бірақ оның еңіс төбесі және — ең маңыздысы — әр шақырудың тұрақты шығыны төмен қарай онша сыпайы масштабталмайды.

Параметрлік іздеу үшін диаграмманың сол жағында үшінші мүше үстемдік етеді: іске қосу мен тасымалдаудың үстеме шығыны. Әр GPU шақыруы шамамен тұрақты баға төлейді — ядроны жөнелту, кіріс деректерді (Apple Silicon-да біріктірілген, бірақ тегін емес) жад шекарасынан өткізу, нәтижелерді кері тасу. BB комбинациядан тұратын топтаманың нақты орындалу уақытын былай модельдейік

Tgpu(B)=O+bB,Tcpu(B)=aBT_{\text{gpu}}(B) = O + b\,B, \qquad T_{\text{cpu}}(B) = a\,B

мұндағы OO — сол тұрақты үстеме шығын, bb — GPU-ның бір комбинацияға шаққандағы шекті шығыны, ал aa — CPU-дікі. Сонда жеделдеу

S(B)=aBO+bB  B  ab.S(B) = \frac{a\,B}{O + b\,B} \;\xrightarrow{B \to \infty}\; \frac{a}{b}.

Осы бір бөлшек бүкіл мақаланы түсіндіреді. Кіші BB кезінде бөлімдегі OO қатынасты жаншып тастайды — сіз GPU-ды оятқаныңыз үшін төледіңіз де, оны әрең пайдаландыңыз. BB өскен сайын OO көбірек комбинацияға бөлініп өтеледі, ал жеделдеу өзінің асимптотасы a/ba/b-ға — нақты аппараттық қатынасқа — қарай өрлейді. Жарты жол нүктесі B=O/bB = O/b-де жатыр: бұл — GPU өз мүмкіндігінің тым болмаса жартысына жетуі үшін іздеуіңіз қаншалықты кең болуы керегін айтатын топтама кеңістігіндегі "жота нүктесі". Бірнеше ондаған комбинациялық іздеу сол жотадан әлдеқайда солға жатады. Мыңдаған комбинациялық іздеу GPU ақыры өз төбесін ақтап шығатын жазық бөлікте отырады.

Демек дұрыс сұрақ ешқашан "GPU жылдамырақ па" болмайды. Дұрысы: "менің іздеуім жотаның оң жағында ма, және әр комбинацияға келетін жұмысым сонда жеткенде жазық төбеге қол созарлықтай есептеуге бай ма". Екеуі де орындалуы тиіс. Мақаланың қалған бөлігі осы табалдырықтардың іс жүзінде қайда түсетінін өлшейді.

Бір таймфреймді үкім: GPU әрең жеңеді

Сол бір 80 комбинациялық бір таймфреймді іздеуге арналған екі баған: секундына 246 комбинация өңдейтін он екі өзекті CPU пулы мен 779 комбинациялық GPU қатар тұр — шыңырау емес, қарапайым 3.2x алшақтық

Жылдамдық баспалдағы пайдаланған жүктемеден бастайық: бір таймфреймді HMA/HMA3 іздеуі, 150,000 бар бойынша 80 комбинация. Ол баспалдаққа біз алтыншы саты қостық — M5: индикаторлар MLX арқылы Apple GPU-да, ал мәмілелер бұрынғыша CPU-да бөлініп алынады. Қыздырылып алынған, үш жүгірістің үздігі, эквиваленттілік қақпасы жасыл:

Әдіс Уақыт pandas-қа қарағанда Комбинация/с
M0 pandas + цикл 287.08s 1.0x 0.3
M2 numba (1 өзек) 2.02s 142x 39.7
M4 mp + numba (12 өзек) 0.33s 883x 245.9
M5 MLX GPU (fp32) 0.10s 2796x 779.2

Қарабайыр тізбекті базамен салыстырғанда GPU батыр көрінеді — 2,796x. Бірақ бұл — адал ешкім жасамайтын салыстыру: ол жақсы GPU іске асырылымын ең нашар CPU нұсқасына қарсы қояды. GPU-ды нақты өндіріске қоятын CPU-мен — сол ядроны он екі өзектің бәрінде жүргізетін M4-пен — қатар қойыңыз, сонда ұтыс салиқалы 3.2x-ке дейін құлдырайды (секундына 779 және 246 комбинация). Тұтас бір графикалық карта, бүкіл іздеуді арқалап, он екі өзекті CPU пулын небәрі үш есе озады.

3.2 — түк емес деуге болмайды. Бірақ GPU-ды бұл үшін де ешкім сатып алмайды. Және бұл — дәл осындай тар іздеу үшін roofline болжайтын нәтиже: 80 комбинация — жотаның сол жағы. Тұрақты іске қосу-тасымалдау үстеме шығыны OO 0.10 секундтық жұмыстың әлі де елеулі үлесі, сондықтан біз a/ba/b асимптотасына ешқашан жетпейміз. Одан жаманы, әр комбинацияға келетін шығынның бір бөлігі — O(n) мәміле бөліп алу өтуі, оны біз әдейі CPU-да қалдырдық — GPU оны мүлде жеделдете алмайды (себебі туралы келесі бөлімде). Осы көлемдегі бір таймфреймді зерттеу циклі үшін жылдамдық баспалдағының бастапқы үкімі күшінде қалады: GPU — жетіспей тұрған саты емес. Параллель numba сізді онсыз да 0.23–0.33 секундқа жеткізді, ал оны 0.10-ға дейін қысқарту зерттеушінің қолын шешетін нәрсе емес. Қолды шешетіні — іздеудің айналасындағы оркестрация.

Бұл үкімдегі қызық сөз — осы көлемдегі. Топтама осі бойымен оңға жылжыңыз — әңгіме өзгереді.

Шығын шын мәнінде қайда жатыр

Топтаманы үлкейтпес бұрын, ақшаны нақты не үшін төлеп жатқанымызға қараңыз, өйткені roofline сізді қымбат бөлік есептеумен шектелген болғанда ғана марапаттайды. Іздеуді профильдесеңіз, оның бәрі дерлік бір нәрсе: салмақталған жылжымалы орташалардың (WMA) конволюциялары. HMA — үш WMA; HMA3 — төртеу; әр комбинация оларды бүкіл қатар бойынша қайта жүргізеді. Мәміле бөліп алу — екі индикатор массивін аралап, hma - hma3 таңба ауысуларын тауып, орындалуларды тіркеу — бір ғана арзан O(n) өту. Бұл іздеу — трейдинг стратегиясының киімін киген конволюция жүктемесі.

Бұл бөлініс — roofline-ның дәл сол екі режимі:

  • Конволюциялар есептеумен шектелген. Әр баға көптеген қабаттасатын терезе қосындыларына оқылады, сондықтан арифметикалық қарқындылық — тасымалданған байтқа шаққандағы операциялар — жоғары. Бұл жұмыс жазық есептеу төбесіне қол созады, ал мұнарадай асқақтайтыны — дәл GPU-ның жазық төбесі. Одан да жақсысы, терезелер комбинациялар арасында да қабаттасады: ұзындығы 40 WMA ондаған комбинацияға пайдалы, сондықтан топтамалық алдын ала есептеу оны әр комбинация сайын қайталамай, бір рет есептеп бөліседі. Топтамалау іске қосу шығынын өтеп қана қоймайды; жүктеулерді қайта пайдалану арқылы арифметикалық қарқындылықты да көтереді. GPU-ға тиесілі бөлік — осы.
  • Мәміле бөліп алу өткізу қабілетімен шектелген және тармақты. Бір тізбекті өту, әр қиылыста деректерге тәуелді тармақталу, қайта пайдалану жоқтың қасы. Оның арифметикалық қарқындылығы еденге таяу, ал басқару ағыны SIMD құрылғысына қас. Оны GPU-ға итеру аз пайда әкеліп, көпке түсер еді; ол CPU-да қалады. Демек ол — Амдал заңы бойынша бөліністің тізбекті құйрығы: GPU жеделдеуі ешқашан тесіп өте алмайтын тұрақты еден және бір таймфреймді санның 3.2x-те қанығуының бір себебі.

Осы ядроның көп таймфреймді нұсқасында екінші, өткірлеу сабақ жасырынып жатыр, және біз түсіндіруге уәде беріп жүрген 27x-тің қайнары — осы. Көп таймфреймді қозғалтқыш жоғарырақ таймфреймнің HMA-сын болашаққа қарамай базалық 1 минуттық индекске туралайды. Мұны көзге бірден түсетін жолмен жазсаңыз, бұл — әр барға O(length^1.5) жұмыс: жоғарғы таймфреймнің жылжымалы орташаларын әр базалық барда қайта есептеу. Бірақ тураланған HMA соңғы бірнеше жабылған жоғарғы таймфрейм шамы мен ағымдағы жабылу бағасынан тұратын қысқа буферге қатысты сызықтық, сондықтан әр барға келетін бүкіл есептеу тұрақты салмақ векторына жиырылады: жабылған шамдар қатары бойынша бір conv1d, содан кейін O(n) жинап алу (gather). Жүздеген миллион артық операция әлдеқайда қысқа қатар бойынша бір конволюцияға айналады.

Бұл жиырылу — аппараттық емес, алгоритмдік ұтыс. Бұл — жақсырақ формула. Ол GPU-да жүреді, CPU-да да дәл сондай жақсы жүреді — fp64-те np.correlate қосу жинап алу. Осыны берік есте сақтаңыз: көп таймфреймді жарнамалық көрсеткіштің ең үлкен жалғыз факторы — GPU-сы мүлде жоқ машинаға да қолжетімді қайта жазу. 167x-ті ақыры жіктеген кезде, 27x дегеніміз — осы.

Алшақтық топтама өлшемімен бірге өседі

Топтама өлшеміне қатысты GPU мен CPU арасындағы жеделдеудің өрлеме қисығы: бір комбинациядағы 54.5x-тен басталып алпыс бірдегі 359.6x-тен асып өтеді, отыз екідегі жалғыз ойыс бөлік шекарасының артефакті ретінде белгіленген

Енді roofline бізге жасауды бұйырған өлшем. Қымбат осьті алыңыз — қолымыздағы ең ұзын шам ағыны, 1 минуттық базалық қатардағы тураланған жоғарғы таймфреймді HMA алдын ала есептеуі — және GPU-ға бір шақыруға өсіп отыратын ұзындық комбинацияларының санын беріңіз: B=1,2,4,,61B = 1, 2, 4, \dots, 61. Мұндағы CPU базасы — адал өндірістік қозғалтқыш: он екі өзектің бәрінде prange-бен жүретін numba. Әр топтама үшін екеуін де өлшеп, қатынасын аламыз.

Топтама BB (комбинация/шақыру) GPU-ның 12 өзекті CPU қозғалтқышынан жеделдеуі
1 54.5x
2 102.5x
4 129.5x
8 187.4x
16 267.4x
32 245.0x
61 359.6x

Бұл — нақты өлшемдермен сызылған S(B)=aB/(O+bB)S(B) = aB/(O + bB). B=1B = 1-де GPU қазірдің өзінде 54.5x алда — өйткені бұл салыстыру әр барда қайта есептейтін қарабайыр қозғалтқышқа қарсы, яғни алгоритмдік жиырылу бір комбинацияның өзінде ішіне қаланған — бірақ ол өз төбесінен әлі алыс: бір комбинациялық шақыруда тұрақты үстеме шығын әлі де үстемдік етеді. Топтаманы екі еселесеңіз, жеделдеу де екі еселенуге жақындап 102.5x-ке жетеді; B=16B = 16-да ол 267.4x; B=61B = 61-де 359.6x және көзге көрініп әлі өрлеп барады. Алшақтық есептің көлемімен бірге өседі. Бұл — GPU мен параметрлік іздеу туралы ең маңызды жалғыз сөйлем, және ол GPU жеделдеуінің әдетте қалай келтірілетініне — чиптің тұрақты қасиеті сияқты етіп — тура қарама-қарсы.

Екі адалдық ескертпесі — өйткені бұл Иллюзиясыз бэктестер сериясы, ал мінсіз монотонды кесте әрқашан күдікке лайық.

Біріншісі — ойыс: B=32B = 32-де 245.0x, бұл B=16B = 16-дағы 267.4x-тен төмен. Бұл кілем астына сыпыра салатын шу емес — бөлік (chunk) шекарасының артефакті. Біздің conv1d 32 ұзындықты бір ядро бөлігіне буып салады, сондықтан B=32B = 32 бір бөлікті қалдықсыз дәл толтырады, ал B=61B = 61 екінші бөлікке асып түседі де, ол құрылғыны кездейсоқ жақсырақ қанықтырады. Roofline-ның мәні — үрдісте, ал нақты құрылғының ішінде кванттау сатылары бар; біз ыңғайлысын теріп алмай, дірілді сол күйінде хабарлаймыз.

Екіншісі, маңыздырағы: 54.5x пен 359.6x екеуі де қарабайыр CPU қозғалтқышына қарсы өлшенген, және екеуі де аппараттық ұтыс емес. Екі санның ішінде де әлі 27x алгоритмдік жиырылу отыр. Егер CPU базасын CPU-да жүретін жиырылған алгоритмге ауыстырсаңыз — сол формула, fp64, екі жағы да оңтайландырылған — әр жол шамамен сол факторға кішірейер еді. Келесі бөлім дәл осы жіктеуді дәлме-дәл жасайды.

Адал жіктеу: 27x алгоритм мен 6.2x аппараттық ұтыстың көбейтіндісі

Жалғыз 167x бағаны қабаттасқан екі факторға бөлініп тұр — CPU-ға да қолжетімді, алгоритм деп белгіленген үлкен 27x және GPU нақты қосатын жалғыз бөлік — аппараттық деп белгіленген кішірек 6.2x

Алгоритмді кремнийден бөлу үшін бір көп таймфреймді торда екі емес, үш жолды өлшеу керек. Сондықтан бенчмарк мыналарды жүргізеді:

  1. cpu-engine — өндірістік numba қозғалтқышы, барлық өзектерде әр бар сайын туралайтын HMA. Қарабайыр, бірақ параллель база.
  2. cpu-collapsed — жиырылған салмақ векторлары, np.correlate қосу жинап алу, fp64, CPU-да. (1)-мен аппараттық құралы бірдей, алгоритмі жақсырақ.
  3. gpu-mlx — жиырылған салмақтар Metal GPU-да топтамалық conv1d ретінде, fp32. (2)-мен алгоритмі бірдей, аппараттық құралы басқа.

Үшеуін қатар қойыңыз — көп таймфреймді толық жарнамалық көрсеткіш таза жіктеледі:

167×gpu vs naive CPU  =  27×cpu-collapsed vs cpu-engine  ×  6.2×gpu vs cpu-collapsed\underbrace{167\times}_{\text{gpu vs naive CPU}} \;=\; \underbrace{27\times}_{\text{cpu-collapsed vs cpu-engine}} \;\times\; \underbrace{6.2\times}_{\text{gpu vs cpu-collapsed}}

Сол жақ фактор — 27x — алгоритм: алдыңғы бөлімдегі әр бардан конволюцияға жиырылу. Оның GPU-ға еш қатысы жоқ. Оны numpy-да іске асырыңыз — ноутбугіңіздің CPU-ы бір рефакторингтің құнына осы жүктемеде 27x жылдамдайды. Оң жақ фактор — 6.2x — аппараттық ұтыс: Metal GPU-ның он екі CPU өзегіндегі дәл сол оңтайландырылған алгоритмнен адал, теңді теңімен салыстырғандағы озуы. Сол 6.2x — GPU шынымен қажет болған жалғыз бөлік.

Бұл — мақаланың бүкіл өнегесі арифметика тілінде айтылғаны. Вендор бенчмаркі, кітапхана README-і немесе көзі жанып тұрған әріптесіңіз сізге "GPU-да 167x" көрсеткенде, рефлекс жалғыз сұрақ болуы керек: CPU базасы қандай еді? Егер база қарабайыр іске асырылым болса — ал ол әрдайым дерлік солай, өйткені баяу база слайдты әдемілейді — онда жарнамалық көрсеткіштің басым бөлігі CPU-дың да заңды үлесі болған алгоритмдік ұтыс, ал аппараттық бөлігі — қалдық қана. Мұнда қалдық — 6.2x. 167x деген дәйексөз аппараттық құралдың үлесін шамамен 27 есе асыра көрсетеді.

Және аппараттық фактордың өзі есеп көлемімен бірге қалай жылжығанына назар аударыңыз. Шағын бір таймфреймді іздеуде GPU-ның ең жақсы CPU-дан нақты ұтысы 3.2x болды. Үлкенірек көп таймфреймді алдын ала есептеуде — 6.2x: сол екі чип, аппараттық артықшылық екі есеге жуық өсті — тек үлкенірек жүктеме CPU ілесе алғанша roofline бойымен GPU-ның жазық есептеу төбесіне қарай жоғарырақ итермелегені үшін ғана. Аппараттық алшақтық та тұрақты шама емес. Ол — сол өрлеме қисықтың бір нүктесі, ал сол қисықпен оңға жылжудың жолы — топтаманы үлкейтіп, әр комбинацияға келетін жұмысты байыту.

Шешім нұсқаулығы: іздеу қаншалықты кең болуы керек?

Қарапайым шешім ағыны: шағын іздеу немесе комбинацияға жұқа жұмыс CPU-ға бағытталады, есептеуге ауыр мыңдаған комбинациялық кең іздеу GPU-ға бағытталады, GPU тармағында fp32 сәйкестік қақпасы тұр

Roofline-ды ақша жұмсамас бұрын қабылдай алатын шешімге қайта орап берейік. GPU roofline-ның екі шарты бір мезгілде орындалғанда өзін ақтайды: іздеуіңіз топтама жотасының оң жағында (BO/bB \gg O/b, яғни іске қосу мен тасымалдаудың тұрақты үстеме шығыны өтеледі), және әр комбинацияға келетін жұмыс есептеумен шектелген (жазық төбеге жетерліктей бай арифметикалық қарқындылық, жұқа O(n) өту емес). Нақтылап айтқанда, өлшегендерімізден:

  • Бір таймфреймді стратегияның бірнеше ондаған комбинациясы: GPU-ды қоя тұрыңыз. Сіз жотаның сол жағындасыз; параллель numba-дан адал ұтыс — онсыз да секундтың оннан бірін ғана алатын жұмыста ~3.2x. Кедергі ядрода емес, оның айналасындағының бәрінде.
  • Мыңдаған комбинация немесе шын мәнінде көп таймфреймді / көп индикаторлы алдын ала есептеу: GPU орнын ақтайды. Үстеме шығын өтеледі, ортақ конволюциялар арифметикалық қарқындылықты көтереді, аппараттық ұтыс 6.2x-ке өрлеп, топтамамен бірге өсе береді. GPU түні бойғы іздеуді кофе үзілісіне айналдыратын режим — осы.
  • Алдымен CPU баспалдағымен көтеріліңіз — ол арзанырақ және бірінші кезекте тұр. CPU-дағы 298x пен 27x алгоритмдік жиырылу тегін немесе соған жуық, әрі олар балама емес, алғышарт: GPU-ның 6.2x-і жиырылған алгоритмнің үстіне қосылады, ал ол алгоритмді сіз бәрібір жазуға тиіс едіңіз. Қарабайыр конвейерге жапсырылған GPU көбіне сол қарабайырлықтың өзін өлшейді.

GPU тармағында жылдамдыққа еш қатысы жоқ салық та бар, оны да бағаға қосу міндет: Apple-дың Metal GPU-ында fp64 мүлде жоқ. Барлығы fp32-де жүреді, салыстырмалы дәлдігі ~1.2e-7. Бұл жылдам жылжымалы орташалардың оқулықтағы амалын — O(n) префикстік қосынды WMA-ны — өлтіреді: бағасы 30,000-ға жуық шкалада 150k бар бойынша жинақталған қосындылар ~1e14-ке жетеді, бұл fp32-нің қауіпсіз бүтін сан ауқымынан жеті реттік дәрежеге асып түседі; біз ~2e2-ге дейінгі салыстырмалы қателерді өлшедік (екі жүз есе, екі пайыз емес). Жұмыс істейтін тұжырым — тікелей терезелік конволюция: онда әр терезе қосындысы өлшемдері шамалас мүшелердің шектеулі санынан тұрады да, fp32 ~8e-7 деңгейінде дәл қалады. Тіпті сонда да hma - hma3 таңбасына қарап шешім қабылдайтын стратегия екі қисық бір-біріне тиер-тимес тұрған шекаралық барда қиылысты анда-санда аударып жібереді, өйткені fp32 дөңгелектеуі тепе-теңдікке жақын жағдайды бір жаққа қисайтады. Сондықтан GPU жолы ешқашан бере алмайтын бит-бірдей нәтижені талап етудің орнына мәмілелердің қаншалықты алшақтағанын өлшейтін эквиваленттілік қақпасымен бірге жеткізіледі — PnL айырмасы базистік тармақпен, мәміле санының салыстырмалы ығысуы. Біздің жүгірісте бұл алшақтық 479,016 орындалудың ішінде 90 ығысқан орындалу болды (0.019%) — рұқсат шегінің әбден ішінде, бірақ жүк нақты: GPU-ға көшу — жылдамырақ такт қана емес, сандық сәйкестік тарихын мойнына алу деген сөз. Бұл инженерлік шығын да өтелу нүктесінің бір бөлігі.

Сандар Apple пішінді, бірақ қисық олай емес

Жоғарыдағы әрбір сан — Apple M2 Max: GPU мен CPU бір қорды бөлісетін біріктірілген жадты құрылғы және қос дәлдігі жоқ, тек fp32-мен жұмыс істейтін GPU. Дискретті NVIDIA немесе AMD картасы константаларды өзгертеді, және әрқайсысы қай бағытта жылжитынын ашық айтқан жөн, өйткені сандар өзгерсе де, дәлелдің пішіні аман қалады.

  • Тасымалдау үстеме шығыны OO жақсармайды, нашарлайды. Дискретті карта PCIe артында отырады, сондықтан кіріс деректер мен нәтижелер біріктірілген жад айналып өтетін шинадан нақты көшірмемен өтеді. Бұл топтама жотасы O/bO/b-ны оңға итереді — дискретті GPU өз іске қосылуын өтеуі үшін одан да кең іздеу керек. PCIe құрылғысында roofline-ның сол жақ шеті жұмсақ емес, тікірек.
  • Жазық төбе a/ba/b биіктейді. Деректер орталығының GPU-ында интеграцияланғанға қарағанда FLOP/s пен өткізу қабілеті әлдеқайда көп, сондықтан қанықтыратын іздеудегі асимптоталық аппараттық ұтыс біздің 6.2x-тен үлкенірек. Қисықтың оң жағына жеткеннің сыйы өседі; сол жағында отырғанның төлемі де өседі.
  • fp64 қайта оралады, онымен бірге префикстік қосынды амалы да. Нағыз қос дәлдігі бар картада O(n) префикстік қосынды WMA қайтадан жарамды, ал сәйкестік қақпасын бит-дәлдікке қарай қатайтуға болады. Біз төлеген нақты fp32 салығы — префикстік қосындылардың орнына тікелей конволюция, assert-тің орнына алшақтықты өлшейтін қақпа — заң емес, Apple Silicon-ның жеке ерекшелігі.

Мұның ешқайсысы тезисті өзгертпейді. Кез келген құрылғыда S(B)=aB/(O+bB)S(B) = aB/(O + bB): өтеуге тиіс тұрақты үстеме шығын және тек оң жақтан жақындайтын асимптота. Константалар — аппараттық құрал; қисық — арифметика. Кімнің болсын жарнамалық көрсеткішіне сенбес бұрын — біздікін қоса — өз OO, aa және bb-ңызды бес жолдық топтама іздеуімен өлшеңіз.

Мұның түйісетін жерлері

Бұл — бэктест жылдамдығы шын мәнінде қайдан келетіні туралы шағын ішкі серияның төртінші өлшемі, әрі бөлшектер ақша жұмсамас бұрын нені оңтайландыру керек деген бір бүтін дәлелге құрастырылады:

  • Жылдамдық баспалдағы pandas-тан параллель numba-ға дейін өрлеп, тек CPU-дың өзінде 298x алды да, GPU-ды ашық сұрақ етіп қалдырды. Бұл мақала оған жауап береді: GPU — нақты, бірақ шартты бесінші саты, ең жоғарғы CPU сатысынан 3.2x–6.2x артық, және тек іздеу roofline-мен өрлеуге жетерліктей кең болғанда ғана.
  • IPC салығы дәл осы қадамды қарама-қарсы бағытта жасады — процестен шығу қанша тұратынын өлшеді — және дәл сондай пішінді қорытындыға жетті: шекараның өзі (сокет, GPU іске қосуы) арзан; салық — одан қаншалықты жиі және қаншалықты сөзуар өтетініңізде. GPU шақыруларын IPC-ді топтайтын себеппен топтаңыз: әр өтудің тұрақты шығынын өтеу үшін.
  • Жинақталған parquet кэші — GPU-дағы алдын ала есептеудің CPU жағындағы баламасы: ортақ индикаторларды бір рет есептеп, әр комбинацияда қайта пайдалану. GPU сол қайта пайдалану мен топтау қағидасын кремнийге көшіреді, бар болғаны.
  • Ал fp32 сәйкестік қақпасы — бэктест пен лайв сәйкестігі мәселесінің миниатюрасы: жылдам жолыңыз эталонға қарағанда сәл өзгеше нәрсе есептеген бойда сіз алшақтық жөнінде қол сермеп құтылмай, сандық есеп беруге міндеттісіз.

Жалғастырушы тәртіп — осы бүкіл серия ұстанатын тәртіп: сізге нақты не сатылып жатса, соны өлшеңіз. Жеделдеу — қатынас, ал қатынастың алымы мен бөлімі бар. GPU-дан көңіл қалудың көбі жағымпаз етіп таңдалған бөлімнен — CPU базасынан — келеді, ал GPU ысырабының көбі roofline-ның сол жақ шетінен шыға алмайтындай тым шағын іздеу жүргізуден келеді.

Түйіндер

  1. GPU жеделдеуі — сан емес, қисық. Біздің көп таймфреймді алдын ала есептеуде CPU-дан алшақтық бір шақыруға бір комбинацияда 54.5x-тен алпыс бірде 359.6x-ке дейін жетті — сол чип, сол деректер. Кез келген жеке сан — сол қисықтың бір нүктесі; қандай топтама өлшемінде өлшенгенін сұраңыз.
  2. CPU базасын әрқашан тергеңіз. Көп таймфреймді жарнамалық 167x таза түрде 27x алгоритмге (әр бардан конволюцияға жиырылу, ол CPU-ды да дәл сондай жылдамдатады) көбейтілген 6.2x нақты аппараттық ұтысқа жіктеледі. Мұндағы әділ GPU мен ең жақсы CPU арасындағы ұтыс — бір таймфреймде 3.2x, көп таймфреймде 6.2x — 167x емес.
  3. Алшақтық есеп көлемімен бірге өседі, аппараттық фактор да солай. Ірірек топтама мен әр комбинацияға байырақ жұмыс сізді roofline бойымен жоғары итереді: адал аппараттық ұтыстың өзі жүктемені үлкейткеннің арқасында ғана 3.2x-тен 6.2x-ке көтерілді. Шағын іздеулер жотаның сол жағында отырады да, пайдасы шамалы.
  4. Алдымен алгоритмді түзеп, CPU баспалдағымен көтеріліңіз — GPU ұтысы солардың орнына емес, үстіне қонады. 6.2x бәрібір жазуға тура келетін жиырылған алгоритмге қарсы өлшенген. Қарабайыр конвейерге GPU жапсырсаңыз, өлшейтініңіздің көбі кремний емес, сол қарабайырлықтың өзі.
  5. GPU-ға көшу — сандық сәйкестік тарихын мойнына алу. Metal-да fp64 жоқ, префикстік қосынды WMA амалы баға шкаласында өледі (салыстырмалы қате ~2e2), ал қиылыс таңбасына қарайтын стратегиялар шекаралық барларда аунап түседі. Алшақтықты базистік тармақпен сандық түрде өлшейтін эквиваленттілік қақпасын жеткізіңіз; сол инженерлік шығынды өтелу есебіңізге қосыңыз.

Біреу сізге GPU оның бэктестін жүз есе жылдамдатты десе, ол сізге түк дерлік айтпады. Одан топтама өлшемі мен CPU базасын сұраңыз — сол жүз әдетте тегін-ақ алуға болатын алгоритмдік ұтысты орап тұрған бір таңбалы аппараттық ұтысқа тарқатылады. Жеткілікті кең іздеуде оның өзі де иеленуге тұрарлық — дәл roofline айтқан себептермен, артық бірде-бір себепсіз.

blog.disclaimer

Authors

Eugen Soloviov
Eugen Soloviov

Trading-systems engineer

Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.

Newsletter

Нарықтан бір қадам алда болыңыз

AI сауда талдаулары, нарық аналитикасы және платформа жаңалықтары үшін біздің ақпараттық бюллетеньге жазылыңыз.

Біз сіздің жекелігіңізді құрметтейміз. Кез келген уақытта жазылымнан шығуға болады.