📝

Draft article

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

← Kembali ke artikel
July 7, 2026
5 menit baca

Kapan GPU Terbayar: Roofline Sweep Parameter, di Mana Headline 167x Sebenarnya adalah 27x Algoritma Kali 6.2x Hardware

Kapan GPU Terbayar: Roofline Sweep Parameter, di Mana Headline 167x Sebenarnya adalah 27x Algoritma Kali 6.2x Hardware
#algotrading
#backtest
#performa
#gpu
#roofline
#optimasi
Part 9 of 10 · Collection
High-Performance Backtest Engines

Bagian dari seri "Backtests Without Illusions".

Tangga kecepatan berakhir dengan nada yang sengaja dibuat tidak memuaskan. Kami telah membawa sweep parameter 80-kombo dari 69.9 detik pandas turun ke 0.23 detik numba paralel pada CPU laptop — terukur 298x — lalu berargumen bahwa GPU bukan anak tangga yang hilang. Kolom komentar tidak menerima ini dengan diam, dan penolakan itu memang benar. "Bukan anak tangga yang hilang" adalah klaim tentang satu beban kerja, pada satu ukuran. Ia bukan hukum alam. Maka artikel ini melakukan hal yang jujur dan menaruh GPU di bangku uji.

Hasilnya bukan sebuah vonis, melainkan sebuah kurva. Keunggulan GPU atas CPU bukan satu angka yang bisa Anda cetak di slide; ia adalah fungsi dari seberapa banyak pekerjaan yang Anda serahkan kepadanya per panggilan. Pada precompute indikator multi-timeframe kami, speedup GPU atas engine CPU berjalan dari 54.5x ketika kami memintanya satu kombinasi parameter per panggilan hingga 359.6x ketika kami meminta 61 sekaligus. Kernel yang sama, data yang sama, hardware yang sama — satu-satunya yang berubah adalah batch. Benchmark yang melaporkan salah satu angka itu dan menyembunyikan yang lain tidak sedang mengukur GPU, ia sedang memilih headline.

Dan bahkan 359.6x tidak seperti yang terlihat. Kupas lapisannya dan headline multi-timeframe besar sebesar 167x terurai menjadi 27x algoritma — penulisan ulang yang juga membuat CPU 27x lebih cepat — kali 6.2x hardware yang sesungguhnya. GPU tidak melakukan yang 27x. Matematikanya yang melakukannya. Artikel ini tentang membedakan keduanya, karena mencampuradukkan keduanya adalah cara sebuah kartu grafis seharga $2,000 dijual untuk menyelesaikan masalah yang bisa diselesaikan sebuah git commit secara gratis.

Provenance: semua angka di bawah diukur pada Apple M2 Max, fp32 pada GPU Metal via MLX versus fp64 numba pada dua belas thread CPU, dari skrip benchmark engine_multitf_gpu.py dan bench_param_sweep.py kami, masing-masing digerbangi oleh pemeriksaan ekuivalensi yang mengonfirmasi jalur GPU dan CPU menghasilkan transaksi yang sama. Tidak ada paper pendamping publik untuk yang satu ini — skripnya-lah rekamannya.

Pertanyaannya adalah roofline, bukan benchmark

Sebuah grafik roofline: langit-langit compute datar di kanan, lereng bandwidth memori yang curam di kiri, dan sebuah titik batch mendaki lereng dari sudut yang didominasi overhead menuju ridge point

Alasan mengapa "seberapa cepat GPU" tidak punya jawaban tunggal adalah roofline model (Williams, Waterman & Patterson, 2009). Performa yang bisa dicapai sebuah prosesor dibatasi oleh dua langit-langit sekaligus: satu yang datar, ditetapkan oleh compute puncak (FLOP/s), dan satu yang miring, ditetapkan oleh bandwidth memori kali intensitas aritmetika — jumlah operasi berguna yang Anda lakukan per byte yang Anda pindahkan. Pekerjaan yang murah-per-byte hidup di bawah langit-langit miring dan dibatasi bandwidth; pekerjaan yang kaya-per-byte mencapai langit-langit datar dan dibatasi compute. Langit-langit datar GPU menjulang jauh di atas milik CPU, tetapi langit-langit miringnya dan, yang krusial, biaya tetap per panggilan-nya tidak mengecil dengan sama anggunnya.

Untuk sweep parameter, sebuah term ketiga mendominasi sisi kiri grafik: overhead peluncuran dan transfer. Setiap panggilan GPU membayar harga yang kurang lebih tetap — men-dispatch kernel, memindahkan input melintasi batas memori (unified di Apple Silicon, tapi tidak gratis), memindahkan hasil kembali. Modelkan wall time untuk batch berisi BB kombinasi sebagai

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

di mana OO adalah overhead tetap itu, bb adalah biaya marginal GPU per kombo, dan aa adalah milik CPU. Speedup-nya kemudian menjadi

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

Satu pecahan ini menjelaskan seluruh artikel. Pada BB kecil, OO di penyebut menghancurkan rasionya — Anda membayar untuk membangunkan GPU dan nyaris tidak memakainya. Seiring BB tumbuh, Anda mengamortisasi OO di lebih banyak kombo dan speedup menanjak menuju asimtotnya a/ba/b, rasio hardware yang sejati. Titik separuh jalannya berada di B=O/bB = O/b: sebuah "ridge point" di ruang batch yang memberi tahu Anda seberapa lebar sweep yang dibutuhkan sebelum GPU bahkan mencapai separuh dari kemampuannya. Sweep beberapa lusin kombo duduk jauh di kiri ridge itu. Sweep ribuan kombo duduk di bagian datar, tempat GPU akhirnya memperoleh langit-langitnya.

Jadi pertanyaan yang benar tidak pernah "apakah GPU lebih cepat". Pertanyaannya adalah "apakah sweep saya berada di kanan ridge, dan apakah pekerjaan per-kombo saya cukup compute-bound untuk mencapai langit-langit datar begitu sampai di sana". Keduanya harus benar. Sisa artikel ini mengukur di mana ambang-ambang itu sebenarnya jatuh.

Vonis single-timeframe: GPU menang tipis

Dua bar untuk sweep single-timeframe 80-kombo yang sama: pool CPU dua belas core pada 246 kombo per detik di samping GPU pada 779, selisih sederhana 3.2x alih-alih jurang

Mulailah dari beban kerja yang dipakai tangga kecepatan: sweep HMA/HMA3 single-timeframe, 80 kombinasi di atas 150,000 bar. Kami menambahkan anak tangga keenam ke tangga itu — M5, indikator pada GPU Apple via MLX, transaksi tetap diekstraksi pada CPU. Dipanaskan lebih dulu, best of three, gerbang ekuivalensi hijau:

Metode Wall vs pandas Kombo/dtk
M0 pandas + loop 287.08s 1.0x 0.3
M2 numba (1 core) 2.02s 142x 39.7
M4 mp + numba (12 core) 0.33s 883x 245.9
M5 MLX GPU (fp32) 0.10s 2796x 779.2

Terhadap baseline serial naif, GPU tampak heroik — 2,796x. Tapi itu perbandingan yang tidak seharusnya dibuat siapa pun yang jujur: ia mengadu implementasi GPU yang bagus melawan implementasi CPU yang terburuk. Sejajarkan GPU dengan CPU yang benar-benar akan Anda deploy — kernel yang sama di seluruh dua belas core, M4 — dan kemenangannya runtuh menjadi 3.2x yang bersahaja (779 versus 246 kombo per detik). Satu kartu grafis utuh, menjalankan seluruh sweep, mengalahkan pool CPU dua belas core dengan faktor tiga.

Tiga koma dua bukannya tanpa arti. Tapi ia juga bukan alasan siapa pun membeli GPU. Dan ia persis seperti yang diprediksi roofline untuk sweep sesempit ini: 80 kombo berada di kiri ridge. Overhead peluncuran-dan-transfer tetap OO masih merupakan porsi yang berarti dari pekerjaan 0.10 detik, jadi kita tidak pernah mencapai asimtot a/ba/b. Lebih buruk lagi, sebagian biaya per-kombo adalah pass ekstraksi transaksi O(n), yang sengaja kami tinggalkan di CPU — sebuah term yang sama sekali tidak bisa dipercepat GPU (lebih lanjut tentang alasannya di bagian berikutnya). Untuk loop riset single-timeframe seukuran ini, vonis asli tangga kecepatan tetap berdiri: GPU bukan anak tangga yang hilang. Numba paralel sudah menempatkan Anda di 0.23–0.33 detik, dan memangkasnya ke 0.10 bukanlah hal yang membebaskan seorang peneliti dari hambatan. Orkestrasi di sekitar sweep-lah yang membebaskannya.

Kata yang menarik dalam vonis itu adalah seukuran ini. Bergeraklah ke kanan sepanjang sumbu batch dan ceritanya berubah.

Di mana biayanya sebenarnya berada

Sebelum kita memperbesar batch, lihat dulu apa yang sebenarnya kita bayar, karena roofline hanya memberi imbalan jika bagian yang mahal bersifat compute-bound. Profilkan sweep-nya dan hampir semuanya adalah satu hal: konvolusi weighted-moving-average. Satu HMA adalah tiga WMA; satu HMA3 adalah empat; setiap kombinasi menjalankan ulang semuanya di sepanjang seluruh deret. Ekstraksi transaksi — menyusuri dua array indikator, menemukan sign flip dari hma - hma3, mencatat fill — adalah satu pass O(n) yang murah. Sweep ini adalah beban kerja konvolusi yang mengenakan kostum strategi trading.

Pembagian itu persis dua rezim roofline:

  • Konvolusi bersifat compute-bound. Setiap harga dibaca ke dalam banyak window sum yang saling tumpang tindih, sehingga intensitas aritmetikanya — operasi per byte yang dipindahkan — tinggi. Pekerjaan ini menggapai langit-langit compute yang datar, dan langit-langit datar milik GPU-lah yang menjulang. Lebih baik lagi, window-nya tumpang tindih lintas kombinasi: sebuah WMA panjang 40 berguna bagi puluhan kombo, sehingga precompute yang di-batch membagikannya sekali alih-alih menghitung ulang per kombo. Batching tidak hanya mengamortisasi overhead peluncuran; ia menaikkan intensitas aritmetika dengan menggunakan ulang load. Inilah bagian yang tempatnya memang di GPU.
  • Ekstraksi transaksi bersifat bandwidth-bound dan penuh cabang. Satu pass sekuensial, cabang yang bergantung pada data di setiap crossing, praktis tanpa reuse. Intensitas aritmetikanya nyaris menyentuh lantai, dan control flow-nya bermusuhan dengan perangkat SIMD. Mendorongnya ke GPU akan menghasilkan sedikit dan berbiaya banyak; ia tetap di CPU. Yang berarti ia adalah ekor serial hukum Amdahl dari pembagian ini — lantai tetap yang tidak akan pernah bisa ditembus speedup GPU, dan sebagian dari alasan mengapa angka single-TF jenuh di 3.2x.

Ada pelajaran kedua yang lebih tajam bersembunyi di versi multi-timeframe kernel ini, dan inilah sumber dari 27x yang terus kami janjikan untuk dijelaskan. Engine multi-TF menyelaraskan HMA timeframe-lebih-tinggi ke indeks basis 1-menit tanpa look-ahead. Ditulis dengan cara yang paling jelas, itu adalah pekerjaan O(length^1.5) per bar — menghitung ulang moving average timeframe-lebih-tinggi di setiap bar basis. Tapi HMA yang diselaraskan itu linear terhadap buffer pendek berisi beberapa candle timeframe-lebih-tinggi terakhir yang sudah tertutup plus running close, sehingga seluruh komputasi per-bar runtuh menjadi satu vektor bobot tetap: satu conv1d di atas deret candle yang sudah tertutup, diikuti satu gather O(n). Ratusan juta operasi redundan menjadi satu konvolusi di atas deret yang jauh lebih pendek.

Peruntuhan itu adalah kemenangan algoritmik, bukan hardware. Ia adalah formula yang lebih baik. Ia berjalan di GPU, dan ia berjalan sama baiknya di CPU — np.correlate plus gather, dalam fp64. Pegang itu baik-baik: faktor tunggal terbesar dalam headline multi-TF adalah penulisan ulang yang tersedia bagi mesin tanpa GPU sama sekali. Ketika kita akhirnya mengurai 167x itu, inilah yang 27x.

Keunggulannya tumbuh seiring ukuran batch

Kurva menanjak speedup GPU-versus-CPU terhadap ukuran batch, menyapu dari 54.5x pada satu kombo hingga melewati 359.6x pada enam puluh satu, dengan satu cekungan pada tiga puluh dua yang dianotasi sebagai artefak batas chunk

Sekarang pengukuran yang disuruh roofline untuk kita lakukan. Ambil sumbu yang mahal — precompute HMA timeframe-lebih-tinggi yang diselaraskan pada deret basis 1-menit, aliran candle terpanjang yang kami miliki — dan suapi GPU dengan jumlah kombinasi panjang yang terus meningkat per panggilan, B=1,2,4,,61B = 1, 2, 4, \dots, 61. Baseline CPU di sini adalah engine produksi yang jujur: numba dengan prange di seluruh dua belas core. Untuk setiap batch kami mengukur keduanya dan mengambil rasionya.

Batch BB (kombo/panggilan) Speedup GPU vs engine CPU 12-core
1 54.5x
2 102.5x
4 129.5x
8 187.4x
16 267.4x
32 245.0x
61 359.6x

Ini adalah S(B)=aB/(O+bB)S(B) = aB/(O + bB) yang digambar dalam pengukuran nyata. Pada B=1B = 1 GPU sudah unggul 54.5x — karena perbandingan ini terhadap engine per-bar naif, sehingga peruntuhan algoritmik sudah terpanggang di dalamnya bahkan pada satu kombo — tapi ia masih jauh dari langit-langitnya: overhead tetap masih mendominasi panggilan satu-kombo. Gandakan batch-nya dan speedup nyaris berlipat dua menjadi 102.5x; pada B=16B = 16 ia 267.4x; pada B=61B = 61 ia 359.6x dan terlihat masih menanjak. Keunggulannya tumbuh seiring ukuran masalah. Itulah kalimat tunggal terpenting tentang GPU dan sweep parameter, dan ia adalah kebalikan persis dari cara speedup GPU biasanya dikutip — seolah-olah ia properti konstan dari chip.

Dua catatan kejujuran, karena ini adalah seri Backtests Without Illusions dan tabel monoton yang bersih selalu layak dicurigai.

Pertama, cekungannya: B=32B = 32 terbaca 245.0x, di bawah 267.4x pada B=16B = 16. Itu bukan noise untuk disapu ke bawah karpet — itu adalah artefak batas chunk. conv1d kami mengemas 32 panjang ke dalam satu chunk kernel, sehingga B=32B = 32 mengisi persis satu chunk tanpa sisa, sementara B=61B = 61 meluber ke chunk kedua yang kebetulan menjenuhkan device dengan lebih baik. Inti dari roofline adalah tren-nya, dan device sungguhan punya anak tangga kuantisasi di dalamnya; kami melaporkan goyangan itu alih-alih memilih-milih data untuk menghindarinya.

Kedua, dan lebih penting: 54.5x dan 359.6x sama-sama terhadap engine CPU naif, dan tidak satu pun adalah kemenangan hardware. Kedua angka itu masih mengandung peruntuhan algoritmik 27x. Jika Anda menukar baseline CPU dengan algoritma hasil peruntuhan yang berjalan di CPU — formula yang sama, fp64, kedua sisi dioptimasi — setiap baris akan menyusut kira-kira sebesar faktor itu. Yang persis merupakan dekomposisi yang dibuat eksak oleh bagian berikutnya.

Dekomposisi yang jujur: 27x algoritma kali 6.2x hardware

Satu bar 167x terbelah menjadi dua faktor bertumpuk — 27x besar berlabel algoritma, tersedia juga bagi CPU, dan 6.2x lebih kecil berlabel hardware, satu-satunya bagian yang benar-benar disumbangkan GPU

Untuk memisahkan algoritma dari silikon, Anda harus mengukur tiga jalur pada grid multi-timeframe yang sama, bukan dua. Jadi benchmark ini menjalankan:

  1. cpu-engine — engine numba produksi, HMA diselaraskan per-bar di seluruh core. Baseline yang naif-tapi-paralel.
  2. cpu-collapsed — vektor bobot hasil peruntuhan, np.correlate plus gather, fp64, di CPU. Hardware yang sama dengan (1), algoritma yang lebih baik.
  3. gpu-mlx — bobot hasil peruntuhan sebagai conv1d batch di GPU Metal, fp32. Algoritma yang sama dengan (2), hardware yang berbeda.

Sejajarkan ketiganya dan headline multi-timeframe penuh terfaktorkan dengan bersih:

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}}

Faktor kiri, 27x, adalah algoritma — peruntuhan per-bar-menjadi-konvolusi dari bagian sebelumnya. Ia tidak ada hubungannya dengan GPU. Implementasikan dalam numpy dan CPU laptop Anda menjadi 27x lebih cepat pada beban kerja ini, seharga sebuah refactor. Faktor kanan, 6.2x, adalah hardware — kemenangan yang jujur dan setara dari GPU Metal atas algoritma teroptimasi yang sama pada dua belas core CPU. 6.2x itu adalah satu-satunya bagian yang benar-benar membutuhkan GPU untuk didapat.

Inilah seluruh moral artikel ini, dinyatakan sebagai aritmetika. Ketika benchmark vendor, README sebuah library, atau kolega yang bersemangat menunjukkan "167x di GPU" kepada Anda, refleksnya harus satu pertanyaan: apa baseline CPU-nya? Jika baseline-nya adalah implementasi naif — dan hampir selalu begitu, karena baseline yang lambat membuat slide yang lebih bagus — maka sebagian besar headline itu adalah kemenangan algoritmik yang juga menjadi hak CPU, dan hanya residunya yang hardware. Di sini residunya 6.2x. Kutipan 167x melebih-lebihkan kontribusi hardware kira-kira 27 kali lipat.

Dan perhatikan bagaimana faktor hardware-nya sendiri bergerak seiring ukuran masalah. Pada sweep single-timeframe yang kecil, kemenangan sejati GPU-versus-CPU-terbaik adalah 3.2x. Pada precompute multi-timeframe yang lebih besar, ia 6.2x — dua chip yang sama, keunggulan hardware yang nyaris berlipat dua, murni karena beban kerja yang lebih besar mendorong lebih jauh ke atas roofline menuju langit-langit compute datar GPU sebelum CPU sempat mengimbangi. Keunggulan hardware juga bukan sebuah konstanta. Ia adalah titik pada kurva menanjak yang sama, dan cara Anda bergerak ke kanan pada kurva itu adalah membuat batch lebih besar dan pekerjaan per-kombo lebih kaya.

Panduan keputusan: seberapa lebar sweep yang dibutuhkan?

Alur keputusan sederhana: sweep kecil atau pekerjaan per-kombo yang tipis diarahkan ke CPU, sweep lebar berisi ribuan kombo padat-compute diarahkan ke GPU, dengan gerbang paritas fp32 berdiri di cabang GPU

Lipat roofline kembali menjadi keputusan yang bisa Anda ambil sebelum mengeluarkan uang. GPU terbayar ketika kedua syarat roofline terpenuhi sekaligus: sweep Anda berada di kanan ridge batch (BO/bB \gg O/b, sehingga overhead peluncuran-dan-transfer yang tetap teramortisasi), dan pekerjaan per-kombo Anda compute-bound (intensitas aritmetika cukup kaya untuk mencapai langit-langit datar, bukan pass O(n) yang tipis). Konkretnya, dari yang kami ukur:

  • Beberapa lusin kombo dari strategi single-timeframe: lewati GPU. Anda berada di kiri ridge; kemenangan jujur atas numba paralel ~3.2x pada pekerjaan yang sudah hanya memakan sepersepuluh detik. Bottleneck-nya bukan kernel, melainkan segala sesuatu di sekitarnya.
  • Ribuan kombo, atau precompute yang benar-benar multi-timeframe / multi-indikator: GPU layak mendapat tempatnya. Overhead-nya teramortisasi, konvolusi bersama menaikkan intensitas aritmetika, dan kemenangan hardware menanjak ke 6.2x dan terus naik seiring batch. Inilah rezim di mana GPU mengubah sweep semalaman menjadi rehat kopi.
  • Daki tangga CPU lebih dulu — lebih murah dan memang urutannya lebih dulu. 298x pada CPU dan peruntuhan algoritmik 27x itu gratis atau nyaris gratis, dan keduanya adalah prasyarat, bukan alternatif: 6.2x milik GPU berada di atas algoritma hasil peruntuhan, yang toh memang harus Anda tulis. GPU yang dibaut ke pipeline naif sebagian besar hanya mengukur kenaifannya.

Ada juga pajak di cabang GPU yang sama sekali tidak berhubungan dengan kecepatan, dan Anda harus memperhitungkannya dalam harga: GPU Metal milik Apple sama sekali tidak punya fp64. Semuanya berjalan dalam fp32, presisi relatif ~1.2e-7. Itu membunuh trik buku teks untuk moving average cepat — WMA prefix-sum O(n) — karena pada skala harga sekitar 30,000 sepanjang 150k bar, running sum-nya mencapai ~1e14, tujuh orde magnitudo melewati rentang integer aman fp32; kami mengukur error relatif hingga ~2e2 (faktor dua ratus, bukan dua persen). Formulasi yang bekerja adalah konvolusi windowed langsung, di mana setiap window sum adalah sejumlah terbatas term berukuran sebanding dan fp32 tetap akurat hingga ~8e-7. Bahkan dengan itu, strategi yang mengambil keputusan dari tanda hma - hma3 sesekali akan membalik sebuah crossing pada bar ambang di mana kedua kurva nyaris bersentuhan, karena pembulatan fp32 menjungkitkan situasi yang nyaris seri. Itulah mengapa jalur GPU dikirim bersama gerbang ekuivalensi yang mengukur seberapa jauh transaksinya menyimpang — delta PnL dalam basis point, pergeseran relatif jumlah transaksi — alih-alih menegaskan output bit-identik yang tidak akan pernah bisa ia berikan. Pada run kami, divergensi itu adalah 90 fill yang bergeser dari 479,016 (0.019%), jauh di dalam toleransi, tetapi bebannya nyata: pergi ke GPU berarti memiliki cerita paritas numerik, bukan sekadar clock yang lebih cepat. Biaya engineering itu juga bagian dari titik break-even.

Angka-angkanya khas Apple; kurvanya tidak

Setiap angka di atas adalah Apple M2 Max: perangkat unified-memory di mana GPU dan CPU berbagi satu pool, dan GPU yang hanya fp32 tanpa double precision sama sekali. Kartu NVIDIA atau AMD diskrit mengubah konstantanya, dan layak dinyatakan eksplisit ke arah mana masing-masing bergerak, karena bentuk argumennya bertahan meski angkanya tidak.

  • Overhead transfer OO menjadi lebih buruk, bukan lebih baik. Kartu diskrit duduk di belakang PCIe, sehingga input dan hasil melakukan copy sungguhan melintasi bus — hal yang dihindari unified memory. Itu mendorong ridge batch O/bO/b ke kanan — Anda butuh sweep yang bahkan lebih lebar sebelum GPU diskrit mengamortisasi peluncurannya. Tepi kiri roofline lebih curam pada perangkat PCIe, bukan lebih landai.
  • Langit-langit datar a/ba/b menjadi lebih tinggi. GPU data-center punya FLOP/s dan bandwidth jauh lebih besar daripada GPU terintegrasi, sehingga kemenangan hardware asimtotik pada sweep yang menjenuhkan lebih besar dari 6.2x kami. Imbalan untuk mencapai sisi kanan kurva tumbuh; ongkos untuk duduk di sisi kiri juga tumbuh.
  • fp64 kembali, dan bersamanya trik prefix-sum. Pada kartu dengan double precision sungguhan, WMA prefix-sum O(n) kembali layak pakai dan gerbang paritas bisa dikencangkan menuju kecocokan bit-eksak. Pajak fp32 spesifik yang kami bayar — konvolusi langsung alih-alih prefix sum, gerbang pengukur divergensi alih-alih assert — adalah detail Apple Silicon, bukan hukum.

Tidak satu pun dari ini mengubah tesisnya. Pada perangkat apa pun, S(B)=aB/(O+bB)S(B) = aB/(O + bB): overhead tetap yang harus Anda amortisasi, asimtot yang hanya bisa Anda dekati dari kanan. Konstantanya adalah hardware; kurvanya adalah aritmetika. Ukur OO, aa, dan bb milik Anda sendiri dengan sweep batch lima baris sebelum mempercayai headline siapa pun — termasuk milik kami.

Ke mana ini terhubung

Ini adalah pengukuran keempat dalam sub-seri kecil tentang dari mana kecepatan backtest sebenarnya berasal, dan potongan-potongannya menyatu menjadi satu argumen tentang apa yang harus dioptimasi sebelum Anda mengeluarkan uang:

  • Tangga kecepatan mendaki dari pandas ke numba paralel untuk 298x pada CPU saja, dan meninggalkan GPU sebagai pertanyaan terbuka. Artikel ini menjawabnya: GPU adalah anak tangga kelima yang nyata tapi bersyarat, bernilai 3.2x–6.2x di atas anak tangga CPU teratas, dan hanya setelah sweep cukup lebar untuk mendaki roofline.
  • Pajak IPC melakukan langkah yang sama ke arah sebaliknya — mengukur berapa biaya meninggalkan proses — dan sampai pada bentuk kesimpulan yang sama: batasnya (sebuah socket, sebuah peluncuran GPU) itu murah; pajaknya ada pada seberapa sering dan seberapa cerewet Anda menyeberanginya. Batch panggilan GPU Anda untuk alasan yang sama Anda mem-batch IPC: untuk mengamortisasi biaya tetap per penyeberangan.
  • Cache parquet teragregasi adalah versi sisi-CPU dari apa yang dilakukan precompute GPU — hitung indikator bersama sekali, gunakan ulang di setiap kombo. GPU hanya membawa prinsip reuse-dan-batch itu ke silikon.
  • Dan gerbang paritas fp32 adalah masalah paritas backtest-live dalam miniatur: begitu jalur cepat Anda menghitung sesuatu yang sedikit berbeda dari referensi Anda, Anda berutang penjelasan divergensi yang terkuantifikasi, bukan lambaian tangan.

Disiplin yang menghubungkan semuanya adalah disiplin yang didorong seluruh seri ini: ukur hal yang sebenarnya sedang dijual kepada Anda. Speedup adalah rasio, dan rasio punya pembilang dan penyebut. Sebagian besar kekecewaan GPU berasal dari penyebut — baseline CPU — yang dipilih untuk menyanjung, dan sebagian besar pemborosan GPU berasal dari menjalankan sweep yang terlalu kecil untuk meninggalkan tepi kiri roofline.

Poin-poin Kunci

  1. Speedup GPU adalah kurva, bukan angka. Pada precompute multi-timeframe kami, keunggulan atas CPU berjalan dari 54.5x pada satu kombo per panggilan hingga 359.6x pada enam puluh satu — chip yang sama, data yang sama. Angka tunggal mana pun adalah satu titik pada kurva itu; tanyakan pada ukuran batch berapa ia diukur.
  2. Selalu interogasi baseline CPU-nya. Headline multi-timeframe 167x terfaktorkan bersih menjadi 27x algoritma (peruntuhan per-bar-menjadi-konvolusi, yang mempercepat CPU sama banyaknya) kali 6.2x hardware sesungguhnya. Kemenangan adil GPU-versus-CPU-terbaik di sini 3.2x untuk single-timeframe, 6.2x untuk multi — bukan 167x.
  3. Keunggulannya tumbuh seiring ukuran masalah, begitu pula faktor hardware-nya. Batch lebih besar dan pekerjaan per-kombo lebih kaya mendorong Anda ke atas roofline: kemenangan hardware yang jujur itu sendiri naik dari 3.2x ke 6.2x murni dengan memperbesar beban kerja. Sweep kecil duduk di kiri ridge dan nyaris tidak diuntungkan.
  4. Perbaiki algoritmanya dan daki tangga CPU lebih dulu — kemenangan GPU duduk di atas keduanya, bukan menggantikannya. 6.2x itu diukur terhadap algoritma hasil peruntuhan yang toh memang harus Anda tulis. Baut GPU ke pipeline naif dan sebagian besar yang Anda ukur adalah kenaifannya, bukan silikonnya.
  5. Pergi ke GPU berarti memiliki cerita paritas numerik. Tidak ada fp64 di Metal, trik WMA prefix-sum mati pada skala harga (error relatif ~2e2), dan strategi berbasis tanda crossing membalik pada bar ambang. Kirimkan gerbang ekuivalensi yang mengkuantifikasi divergensinya dalam basis point; hitung biaya engineering itu dalam break-even Anda.

Ketika seseorang memberi tahu Anda GPU membuat backtest-nya seratus kali lebih cepat, ia nyaris tidak memberi tahu Anda apa-apa. Tanyakan ukuran batch dan baseline CPU-nya, dan yang seratus itu biasanya terurai menjadi kemenangan hardware satu-digit yang membungkus kemenangan algoritmik yang bisa mereka dapatkan secara gratis — layak dimiliki, pada sweep yang cukup besar, persis karena alasan-alasan yang dikatakan roofline dan tidak satu alasan pun lebih.

Penafian: Informasi yang disediakan dalam artikel ini hanya untuk tujuan edukasi dan informasi serta tidak merupakan nasihat keuangan, investasi, atau trading. Trading mata uang kripto mengandung risiko kerugian yang signifikan.

Penulis

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

Selangkah Lebih Maju dari Pasar

Berlangganan newsletter kami untuk wawasan AI trading eksklusif, analisis pasar, dan pembaruan platform.

Kami menghormati privasi Anda. Berhenti berlangganan kapan saja.