GPU Ne Zaman Karşılığını Verir: Parametre Taraması Roofline'ı — Manşetteki 167x'in Aslında 27x Algoritma Çarpı 6.2x Donanım Olduğu Yer
"Yanılsamasız Backtestler" serisinin bir parçası.
Hız merdiveni bilinçli olarak tatmin etmeyen bir notayla bitmişti. 80 kombinasyonluk bir parametre taramasını 69.9 saniyelik pandas'tan bir dizüstü CPU'sundaki 0.23 saniyelik paralel numba'ya indirmiştik — ölçülen bir 298x — ve ardından bir GPU'nun eksik basamak olmadığını savunmuştuk. Yorumlar bölümü bunu sessizce kabul etmedi ve etmemekte de haklıydı. "Eksik basamak değil", tek bir iş yükü hakkında, tek bir boyutta bir iddiadır. Bir doğa yasası değildir. Bu yüzden bu makale dürüst olanı yapıyor ve GPU'yu ölçüm tezgahına yatırıyor.
Sonuç bir verdict değil, bir eğri. GPU'nun CPU'ya karşı üstünlüğü, bir slayta basabileceğiniz tek bir rakam değil; çağrı başına ona ne kadar iş verdiğinizin bir fonksiyonu. Çoklu zaman dilimli (multi-timeframe) gösterge ön hesaplamamızda GPU'nun CPU motoruna karşı hızlanması, ondan tek seferde bir parametre kombinasyonu istediğimizde 54.5x'ten, aynı anda 61 tane istediğimizde 359.6x'e kadar uzanıyor. Aynı kernel, aynı veri, aynı donanım — değişen tek şey batch. Bu rakamlardan birini bildirip diğerini gizleyen bir benchmark GPU'yu ölçmüyordur; bir manşet seçiyordur.
Ve 359.6x bile göründüğü gibi değil. Soyup açın; çoklu zaman dilimli büyük bir manşet olan 167x, 27x algoritmaya — CPU'yu da 27x hızlandıran bir yeniden yazım — çarpı 6.2x gerçek donanıma ayrışıyor. 27x'i GPU yapmadı. Matematik yaptı. Bu makale bu ikisini birbirinden ayırt edebilmek üzerine, çünkü ikisini birbirine karıştırmak, bir git commit'in bedavaya çözeceği bir sorunu çözsün diye 2,000 dolarlık bir ekran kartının satılma yoludur.
Kaynak: aşağıdaki tüm rakamlar bir Apple M2 Max üzerinde ölçülmüştür — MLX aracılığıyla Metal GPU'da fp32'ye karşı on iki CPU thread'inde fp64 numba — engine_multitf_gpu.py ve bench_param_sweep.py benchmark betiklerimizden, her biri GPU ve CPU yollarının aynı işlemleri ürettiğini doğrulayan bir eşdeğerlik kontrolüyle kapılanmış halde. Bu çalışma için kamuya açık bir eşlik eden makale yok — kayıt, betiklerin kendisidir.
Soru bir benchmark değil, bir roofline

"GPU ne kadar daha hızlı" sorusunun tek bir yanıtının olmamasının nedeni roofline modelidir (Williams, Waterman & Patterson, 2009). Bir işlemcinin ulaşabileceği performans aynı anda iki tavanla sınırlıdır: tepe hesaplama gücünün (FLOP/s) belirlediği düz bir tavan ve bellek bant genişliği çarpı aritmetik yoğunluğun — taşıdığınız bayt başına yaptığınız faydalı işlem sayısının — belirlediği eğimli bir tavan. Bayt başına ucuz iş eğimli tavanın altında yaşar ve bant genişliği sınırlıdır; bayt başına zengin iş düz tavana ulaşır ve hesaplama sınırlıdır. GPU'nun düz tavanı CPU'nunkinin çok üzerinde yükselir, ama eğimli tavanı ve — kritik olarak — çağrı başına sabit maliyeti aynı zarafetle aşağı ölçeklenmez.
Bir parametre taraması için grafiğin sol tarafını üçüncü bir terim domine eder: başlatma ve aktarım ek yükü. Her GPU çağrısı kabaca sabit bir bedel öder — kernel'i dispatch et, girdileri (Apple Silicon'da birleşik, ama bedava olmayan) bellek sınırından geçir, sonuçları geri taşı. kombinasyonluk bir batch için duvar saati süresini şöyle modelleyin:
Burada o sabit ek yük, GPU'nun kombinasyon başına marjinal maliyeti, ise CPU'nunki. Hızlanma o zaman şu olur:
Bu tek kesir tüm makaleyi açıklıyor. Küçük 'de paydadaki oranı ezer — GPU'yu uyandırmak için ödediniz ve onu neredeyse hiç kullanmadınız. büyüdükçe 'yu daha fazla kombinasyona yayarak amorti edersiniz ve hızlanma asimptotu olan 'ye — gerçek donanım oranına — doğru tırmanır. Yarı yol noktası 'de oturur: taramanızın, GPU'nun olabileceğinin yarısına bile ulaşması için ne kadar geniş olması gerektiğini söyleyen, batch uzayında bir "sırt noktası" (ridge point). Birkaç düzine kombinasyonluk bir tarama o sırtın çok solunda oturur. Binlerce kombinasyonluk bir tarama, GPU'nun tavanını nihayet hak ettiği düz kısımda oturur.
Dolayısıyla doğru soru asla "GPU daha mı hızlı" değildir. Doğru soru şudur: "taramam sırtın sağında mı, ve kombinasyon başına işim oraya vardığında düz tavana ulaşacak kadar hesaplama sınırlı mı." İkisinin de doğru olması gerekir. Makalenin geri kalanı bu eşiklerin gerçekte nereye düştüğünü ölçüyor.
Tek zaman dilimi verdict'i: GPU kıl payı kazanıyor

Hız merdiveninin kullandığı iş yüküyle başlayalım: tek zaman dilimli bir HMA/HMA3 taraması, 150,000 bar üzerinde 80 kombinasyon. O merdivene altıncı bir basamak ekledik — M5, göstergeler MLX aracılığıyla Apple GPU'sunda, işlemler hâlâ CPU'da çıkarılıyor. Isıtılmış, 3'ün en iyisi, eşdeğerlik kapısı yeşil:
| Yöntem | Duvar saati | pandas'a göre | Kombinasyon/s |
|---|---|---|---|
| M0 pandas + döngü | 287.08s | 1.0x | 0.3 |
| M2 numba (1 çekirdek) | 2.02s | 142x | 39.7 |
| M4 mp + numba (12 çekirdek) | 0.33s | 883x | 245.9 |
| M5 MLX GPU (fp32) | 0.10s | 2796x | 779.2 |
Naif seri referansa karşı GPU kahramanca görünüyor — 2,796x. Ama bu, dürüst hiç kimsenin yapmaması gereken bir karşılaştırma: iyi bir GPU uygulamasını en kötü CPU uygulamasıyla yarıştırıyor. GPU'yu gerçekten devreye alacağınız CPU ile hizalayın — aynı çekirdeğin on iki CPU çekirdeğinin tamamında çalıştığı M4 ile — ve kazanç aklı başında bir 3.2x'e çöküyor (saniyede 779'a karşı 246 kombinasyon). Koca bir ekran kartı, taramanın tamamını çalıştırarak, on iki çekirdekli bir CPU pool'unu üç kat farkla geçiyor.
Üç nokta iki hiç yoktan iyidir. Ama kimsenin bir GPU satın alma nedeni de değildir. Ve bu kadar dar bir tarama için roofline'ın öngördüğü şey tam olarak budur: 80 kombinasyon sırtın solundadır. Sabit başlatma-ve-aktarım ek yükü , 0.10 saniyelik bir işin hâlâ anlamlı bir dilimidir, bu yüzden asimptot 'ye asla ulaşamayız. Daha kötüsü, kombinasyon başına maliyetin bir kısmı, bilinçli olarak CPU'da bıraktığımız O(n) işlem çıkarma geçişidir — GPU'nun hiç hızlandıramayacağı bir terim (nedenine bir sonraki bölümde geleceğiz). Bu boyuttaki tek zaman dilimli bir araştırma döngüsü için hız merdiveninin özgün verdict'i geçerliliğini koruyor: GPU eksik basamak değil. Paralel numba sizi zaten 0.23–0.33 saniyeye koymuştu ve bunu 0.10'a törpülemek bir araştırmacının önünü açan şey değil. Önünü açan, taramanın etrafındaki orkestrasyon.
Bu verdict'teki ilginç ifade bu boyutta. Batch ekseni boyunca sağa ilerleyin ve hikaye değişiyor.
Maliyet gerçekte nerede yaşıyor
Batch'i büyütmeden önce, gerçekte neye para ödediğimize bakın, çünkü roofline sizi ancak pahalı kısım hesaplama sınırlıysa ödüllendirir. Taramayı profilleyin; neredeyse tamamı tek bir şeydir: ağırlıklı hareketli ortalama convolution'ları. Bir HMA üç WMA'dır; bir HMA3 dörttür; her kombinasyon bunları tüm seri üzerinde yeniden çalıştırır. İşlem çıkarma — iki gösterge dizisi boyunca yürü, hma - hma3'ün işaret dönüşlerini bul, fill'leri kaydet — tek bir ucuz O(n) geçiştir. Tarama, trading stratejisi kostümü giymiş bir convolution iş yüküdür.
Bu ayrım tam olarak roofline'ın iki rejimidir:
- Convolution'lar hesaplama sınırlıdır. Her fiyat, örtüşen birçok pencere toplamına okunur, dolayısıyla aritmetik yoğunluk — taşınan bayt başına işlem — yüksektir. Bu iş düz hesaplama tavanına uzanır ve göklere yükselen tavan GPU'nunkidir. Daha da iyisi, pencereler kombinasyonlar arasında örtüşür: uzunluğu 40 olan bir WMA düzinelerce kombinasyonun işine yarar, dolayısıyla batch'lenmiş bir ön hesaplama onu kombinasyon başına yeniden hesaplamak yerine bir kez paylaşır. Batch'leme yalnızca başlatma ek yükünü amorti etmez; yüklemeleri yeniden kullanarak aritmetik yoğunluğu da yükseltir. GPU'ya ait olan kısım budur.
- İşlem çıkarma bant genişliği sınırlı ve dallanmalıdır. Tek bir sıralı geçiş, her kesişimde veriye bağımlı dallanmalar, esasen sıfır yeniden kullanım. Aritmetik yoğunluğu tabana yakındır ve kontrol akışı bir SIMD cihazına düşmandır. Onu GPU'ya itmek az kazandırıp çok kaybettirirdi; CPU'da kalır. Bu da onu bir Amdahl yasası ayrımının seri kuyruğu yapar — GPU hızlanmasının asla delemeyeceği sabit bir taban ve tek-TF rakamının 3.2x'te doymasının nedenlerinden biri.
Bu çekirdeğin çoklu zaman dilimli versiyonunda saklanan ikinci, daha keskin bir ders var ve açıklamayı vaat edip durduğumuz 27x'in kaynağı bu. Multi-TF motoru, daha yüksek zaman dilimli bir HMA'yı look-ahead olmadan taban 1 dakikalık indekse hizalar. Bariz şekilde yazıldığında bu, bar başına O(length^1.5) iştir — yüksek zaman diliminin hareketli ortalamalarını her taban barda yeniden hesaplamak. Ama hizalanmış HMA, son birkaç kapanmış yüksek-TF mumundan oluşan kısa bir buffer artı çalışan kapanışta doğrusaldır, dolayısıyla bar başına hesaplamanın tamamı sabit bir ağırlık vektörüne çöker: kapanmış mumlar serisi üzerinde tek bir conv1d, ardından bir O(n) gather. Yüz milyonlarca gereksiz işlem, çok daha kısa bir seri üzerinde bir convolution'a dönüşür.
Bu çökme bir donanım kazancı değil, algoritmik bir kazançtır. Daha iyi bir formüldür. GPU'da çalışır ve CPU'da da aynı derecede iyi çalışır — np.correlate artı bir gather, fp64'te. Bunu aklınızda sıkıca tutun: multi-TF manşetindeki en büyük tekil faktör, hiç GPU'su olmayan bir makinenin de erişebildiği bir yeniden yazımdır. 167x'i nihayet ayrıştırdığımızda, 27x budur.
Üstünlük batch boyutuyla büyüyor

Şimdi roofline'ın bize yapmamızı söylediği ölçüm. Pahalı ekseni alın — elimizdeki en uzun mum akışı olan 1 dakikalık taban seri üzerinde hizalanmış yüksek zaman dilimli HMA ön hesaplaması — ve GPU'ya çağrı başına giderek artan sayıda uzunluk kombinasyonu verin, . Buradaki CPU referansı dürüst üretim motoru: on iki çekirdeğin tamamında prange ile numba. Her batch için ikisini de ölçüyor ve oranı alıyoruz.
| Batch (kombinasyon/çağrı) | 12 çekirdekli CPU motoruna karşı GPU hızlanması |
|---|---|
| 1 | 54.5x |
| 2 | 102.5x |
| 4 | 129.5x |
| 8 | 187.4x |
| 16 | 267.4x |
| 32 | 245.0x |
| 61 | 359.6x |
Bu, gerçek ölçümlerle çizilmiş . 'de GPU zaten 54.5x önde — çünkü bu karşılaştırma naif bar başına motora karşı, dolayısıyla algoritmik çökme tek kombinasyonda bile pakete dahil — ama tavanının yakınından bile geçmiyor: sabit ek yük, tek kombinasyonluk bir çağrıyı hâlâ domine ediyor. Batch'i ikiye katlayın ve hızlanma neredeyse ikiye katlanarak 102.5x'e çıkıyor; 'da 267.4x; 'de 359.6x ve gözle görülür biçimde hâlâ tırmanıyor. Üstünlük problemin boyutuyla büyüyor. GPU'lar ve parametre taramaları hakkındaki en önemli tekil cümle bu — ve GPU hızlanmalarının genellikle alıntılanma şeklinin, sanki çipin sabit bir özelliğiymiş gibi sunulmasının tam tersi.
İki dürüstlük notu, çünkü bu Yanılsamasız Backtestler serisi ve tertemiz monoton bir tablo her zaman şüpheyi hak eder.
Önce çukur: , 'daki 267.4x'in altında, 245.0x okunuyor. Bu, halının altına süpürülecek bir gürültü değil — bir chunk sınırı artefaktı. conv1d'miz 32 uzunluğu tek bir kernel chunk'ına paketliyor, dolayısıyla tam olarak bir chunk'ı boşluksuz dolduruyor; ise cihazı daha iyi doyurmayı beceren ikinci bir chunk'a taşıyor. Roofline'ın amacı eğilimdir ve gerçek bir cihazın içinde nicemleme basamakları vardır; biz de dalgalanmayı işimize gelen noktaları cımbızlayarak gizlemek yerine olduğu gibi bildiriyoruz.
İkincisi ve daha önemlisi: 54.5x de 359.6x de naif CPU motoruna karşı ve ikisi de donanım kazancı değil. Her iki rakam da 27x'lik algoritmik çökmeyi hâlâ içeriyor. CPU referansını, CPU'da çalışan çökertilmiş algoritmayla değiştirseydiniz — aynı formül, fp64, iki taraf da optimize — her satır kabaca o faktör kadar küçülürdü. Bir sonraki bölümün kesinleştirdiği ayrıştırma tam olarak bu.
Dürüst ayrıştırma: 27x algoritma çarpı 6.2x donanım

Algoritmayı silikondan ayırmak için aynı çoklu zaman dilimli ızgara üzerinde iki değil, üç yol ölçmeniz gerekir. Benchmark bu yüzden şunları çalıştırıyor:
- cpu-engine — üretimdeki numba motoru, tüm çekirdeklerde bar başına hizalanmış HMA. Naif-ama-paralel referans.
- cpu-collapsed — çökertilmiş ağırlık vektörleri,
np.correlateartı gather, fp64, CPU'da. (1) ile aynı donanım, daha iyi algoritma. - gpu-mlx — çökertilmiş ağırlıklar, Metal GPU'da batch'lenmiş bir
conv1dolarak, fp32. (2) ile aynı algoritma, farklı donanım.
Bunları yan yana koyun ve çoklu zaman dilimli manşetin tamamı temiz biçimde çarpanlarına ayrılıyor:
Soldaki faktör, 27x, algoritmadır — önceki bölümdeki bar-başınadan-convolution'a çökme. GPU ile hiçbir ilgisi yok. Onu numpy'da uygulayın ve dizüstü CPU'nuz bu iş yükünde bir refactor bedeline 27x hızlansın. Sağdaki faktör, 6.2x, donanımdır — Metal GPU'nun, on iki CPU çekirdeğindeki aynı optimize algoritma karşısındaki dürüst, birebir kazancı. Elde etmek için gerçekten bir GPU'ya ihtiyaç duyduğunuz tek kısım o 6.2x.
Bu, makalenin tüm ahlaki dersinin aritmetik olarak ifadesi. Bir üretici benchmark'ı, bir kütüphane README'si ya da heyecanlı bir meslektaş size "GPU'da 167x" gösterdiğinde, refleks tek bir soru olmalı: CPU referansı neydi? Referans naif uygulamaysa — ve neredeyse her zaman öyledir, çünkü yavaş bir referans daha iyi bir slayt yapar — o zaman manşetin çoğu, CPU'nun da hakkı olan bir algoritmik kazançtır ve yalnızca kalan kısım donanımdır. Burada kalan kısım 6.2x. 167x'lik bir alıntı, donanımın katkısını kabaca 27 kat abartıyor.
Ve donanım faktörünün kendisinin de problem boyutuyla nasıl hareket ettiğine dikkat edin. Küçük tek zaman dilimli taramada gerçek GPU-en-iyi-CPU kazancı 3.2x idi. Daha büyük çoklu zaman dilimli ön hesaplamada 6.2x — aynı iki çip, neredeyse iki katı donanım avantajı; sırf daha büyük iş yükü, CPU ayak uyduramadan roofline'da GPU'nun düz hesaplama tavanına doğru daha yukarı itiyor diye. Donanım üstünlüğü de bir sabit değil. Aynı yükselen eğri üzerinde bir nokta ve o eğride sağa doğru ilerlemenin yolu, batch'i büyütmek ve kombinasyon başına işi zenginleştirmek.
Bir karar rehberi: tarama ne kadar geniş olmalı?

Roofline'ı, para harcamadan önce verebileceğiniz bir karara geri katlayın. GPU, roofline'ın iki koşulu aynı anda geçerli olduğunda karşılığını verir: taramanız batch sırtının sağındadır (, yani sabit başlatma-ve-aktarım ek yükü amorti edilmiştir) ve kombinasyon başına işiniz hesaplama sınırlıdır (ince bir O(n) geçişi değil, düz tavana ulaşacak kadar zengin aritmetik yoğunluk). Somut olarak, ölçtüklerimizden:
- Tek zaman dilimli bir stratejinin birkaç düzine kombinasyonu: GPU'yu atlayın. Sırtın solundasınız; paralel numba'ya karşı dürüst kazanç, zaten saniyenin onda birini alan bir işte ~3.2x. Darboğaz çekirdek değil, etrafındaki her şey.
- Binlerce kombinasyon, ya da gerçekten çoklu zaman dilimli / çoklu göstergeli bir ön hesaplama: GPU yerini hak ediyor. Ek yük amorti oluyor, paylaşılan convolution'lar aritmetik yoğunluğu yükseltiyor ve donanım kazancı 6.2x'e tırmanıp batch ile yükselmeye devam ediyor. Bir GPU'nun bir gecelik taramayı bir kahve molasına çevirdiği rejim bu.
- Önce CPU merdivenini tırmanın — daha ucuz ve sırada önce geliyor. CPU'daki 298x ve 27x'lik algoritmik çökme bedava ya da bedavaya yakın; ve bunlar alternatif değil ön koşul: GPU'nun 6.2x'i, zaten yazmak zorunda olduğunuz çökertilmiş algoritmanın üzerine gelir. Naif bir pipeline'a cıvatalanan bir GPU çoğunlukla naifliği ölçer.
GPU dalında hızla hiçbir ilgisi olmayan bir vergi de var ve onu fiyata dahil etmek zorundasınız: Apple'ın Metal GPU'sunda fp64 hiç yok. Her şey fp32'de çalışıyor, ~1.2e-7 göreli hassasiyet. Bu, hızlı hareketli ortalamalar için ders kitabı hilesini — O(n) prefix-sum WMA'yı — öldürüyor, çünkü 150k bar üzerinde 30,000 civarı bir fiyat ölçeğinde çalışan toplamlar ~1e14'e ulaşıyor; fp32'nin güvenli tamsayı aralığının yedi büyüklük mertebesi ötesi. ~2e2'ye varan göreli hatalar ölçtük (yüzde iki değil, iki yüz kat). Çalışan formülasyon, her pencere toplamının karşılaştırılabilir boyutta sınırlı sayıda terimden oluştuğu ve fp32'nin ~8e-7'ye kadar doğru kaldığı doğrudan pencereli convolution. O zaman bile, hma - hma3'ün işaretine göre karar veren bir strateji, iki eğrinin neredeyse temas ettiği sınırdaki bir barda kesişimi ara sıra ters çevirecektir, çünkü fp32 yuvarlaması başa baş bir durumu bir tarafa devirir. GPU yolunun, asla teslim edemeyeceği bit-bit aynı çıktıyı iddia etmek yerine işlemlerin ne kadar saptığını ölçen bir eşdeğerlik kapısıyla — baz puan cinsinden PnL farkı, işlem sayısında göreli kayma — gelmesinin nedeni bu. Bizim çalıştırmamızda bu sapma 479,016 fill'den 90 kaymış fill'di (%0.019) — toleransın rahatça içinde — ama yük gerçek: GPU'ya gitmek, yalnızca daha hızlı bir saate değil, bir sayısal eşitlik hikayesine sahip çıkmak demektir. Bu mühendislik maliyeti de break-even'ın bir parçası.
Rakamlar Apple biçimli; eğri değil
Yukarıdaki her rakam bir Apple M2 Max: GPU ile CPU'nun tek bir havuzu paylaştığı birleşik bellekli (unified-memory) bir cihaz ve çift hassasiyeti hiç olmayan, yalnızca fp32'lik bir GPU. Ayrık bir NVIDIA veya AMD kartı sabitleri değiştirir ve her birinin hangi yöne hareket ettiği konusunda açık olmaya değer, çünkü rakamlar hayatta kalmasa da argümanın şekli hayatta kalır.
- Aktarım ek yükü iyileşmez, kötüleşir. Ayrık bir kart PCIe'nin arkasında oturur, dolayısıyla girdiler ve sonuçlar, birleşik belleğin kaçındığı gerçek bir kopyayı bus üzerinden yapar. Bu, batch sırtı 'yi sağa iter — ayrık bir GPU'nun başlatmasını amorti etmesi için daha da geniş bir taramaya ihtiyacınız olur. Roofline'ın sol kenarı bir PCIe cihazında daha yumuşak değil, daha diktir.
- Düz tavan yükselir. Bir veri merkezi GPU'su, entegre olandan çok daha fazla FLOP/s'ye ve bant genişliğine sahiptir, dolayısıyla doyuran bir taramadaki asimptotik donanım kazancı bizim 6.2x'imizden büyüktür. Eğrinin sağ tarafına ulaşmanın ödülü büyür; solda oturmanın bedeli de büyür.
- fp64 geri gelir ve onunla birlikte prefix-sum hilesi de. Gerçek çift hassasiyetli bir kartta O(n) prefix-sum WMA yeniden uygulanabilir hale gelir ve eşitlik kapısı bit-kesinliğine doğru sıkılaştırılabilir. Ödediğimiz özgül fp32 vergisi — prefix sum yerine doğrudan convolution, assert yerine sapma ölçen bir kapı — bir yasa değil, bir Apple Silicon ayrıntısıdır.
Bunların hiçbiri tezi değiştirmiyor. Herhangi bir cihazda, : amorti etmeniz gereken sabit bir ek yük, yalnızca sağdan yaklaştığınız bir asimptot. Sabitler donanımdır; eğri aritmetiktir. Herhangi birinin manşetine — bizimki dahil — güvenmeden önce kendi , ve 'nizi beş satırlık bir batch taramasıyla ölçün.
Bunun bağlandığı yerler
Bu, backtest hızının gerçekte nereden geldiğine dair küçük bir alt serideki dördüncü ölçüm ve parçalar, harcamadan önce neyi optimize etmeli hakkında tek bir argüman olarak birbirine oturuyor:
- Hız merdiveni, yalnızca CPU'da 298x için pandas'tan paralel numba'ya tırmandı ve GPU'yu açık bir soru olarak bıraktı. Bu makale onu yanıtlıyor: GPU gerçek ama koşullu bir beşinci basamak — en üst CPU basamağına karşı 3.2x–6.2x değerinde ve yalnızca tarama roofline'ı tırmanacak kadar genişse.
- IPC vergisi aynı hamleyi diğer yönde yaptı — process'ten çıkmanın neye mal olduğunu ölçtü — ve aynı biçimde bir sonuca ulaştı: sınır (bir soket, bir GPU başlatması) ucuz; vergi, onu ne sıklıkla ve ne kadar gevezelikle geçtiğinizde. GPU çağrılarınızı, IPC'nizi batch'lediğiniz nedenin aynısıyla batch'leyin: geçiş başına sabit bir maliyeti amorti etmek için.
- Toplulaştırılmış parquet önbelleği, GPU ön hesaplamasının yaptığının CPU tarafındaki versiyonu — paylaşılan göstergeleri bir kez hesapla, her kombinasyonda yeniden kullan. GPU, o yeniden-kullan-ve-batch'le ilkesini yalnızca silikona taşıyor.
- Ve fp32 eşitlik kapısı, minyatürde bir backtest-canlı eşitlik problemi: hızlı yolunuz referansınızdan biraz farklı bir şey hesapladığı anda, sapmanın el sallamayla geçiştirilmiş değil, nicelleştirilmiş bir hesabını borçlusunuz.
Bağlayıcı disiplin, tüm bu serinin bastırdığı disiplinle aynı: size fiilen satılan şeyi ölçün. Bir hızlanma bir orandır ve bir oranın payı ve paydası vardır. GPU hayal kırıklıklarının çoğu, pohpohlamak için seçilmiş bir paydadan — CPU referansından — gelir; GPU israfının çoğu ise roofline'ın sol kenarını terk edemeyecek kadar küçük bir tarama çalıştırmaktan.
Çıkarımlar
- Bir GPU hızlanması bir rakam değil, bir eğridir. Çoklu zaman dilimli ön hesaplamamızda CPU'ya karşı üstünlük, çağrı başına tek kombinasyonda 54.5x'ten altmış birde 359.6x'e uzandı — aynı çip, aynı veri. Herhangi bir tekil rakam o eğri üzerinde bir noktadır; hangi batch boyutunda ölçüldüğünü sorun.
- CPU referansını her zaman sorguya çekin. Çoklu zaman dilimli 167x manşeti, temiz biçimde 27x algoritma (CPU'yu da aynı ölçüde hızlandıran, bar-başınadan-convolution'a bir çökme) çarpı 6.2x gerçek donanıma ayrışıyor. Buradaki adil GPU-en-iyi-CPU kazancı tek zaman diliminde 3.2x, çokluda 6.2x — 167x değil.
- Üstünlük problem boyutuyla büyüyor, donanım faktörü de öyle. Daha büyük batch ve kombinasyon başına daha zengin iş sizi roofline'da yukarı iter: dürüst donanım kazancının kendisi, sırf iş yükü büyütülerek 3.2x'ten 6.2x'e yükseldi. Küçük taramalar sırtın solunda oturur ve neredeyse hiç yararlanmaz.
- Önce algoritmayı düzeltin ve CPU merdivenini tırmanın — GPU kazancı onların yerine değil, üzerine oturur. 6.2x, zaten yazmak zorunda olduğunuz çökertilmiş algoritmaya karşı ölçülüyor. Naif bir pipeline'a bir GPU cıvatalayın; ölçtüğünüzün çoğu silikon değil, naiflik olur.
- GPU'ya gitmek, bir sayısal eşitlik hikayesine sahip çıkmak demektir. Metal'de fp64 yok, prefix-sum WMA hilesi fiyat ölçeğinde ölüyor (göreli hata ~2e2) ve kesişim işaretine dayalı stratejiler sınırdaki barlarda ters dönüyor. Sapmayı baz puan cinsinden nicelleştiren bir eşdeğerlik kapısıyla gelin; o mühendislik maliyetini break-even'ınıza sayın.
Biri size GPU'nun backtest'ini yüz kat hızlandırdığını söylediğinde, size neredeyse hiçbir şey söylememiştir. Batch boyutunu ve CPU referansını sorun; o yüz genellikle, bedavaya sahip olabilecekleri bir algoritmik kazanca sarılmış tek haneli bir donanım kazancına çözülür — yeterince büyük bir taramada, tam olarak roofline'ın söylediği nedenlerle ve tek bir neden bile fazlasıyla değil, sahip olmaya değer.
Yazarlar
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.