Článek
Když absolutní vítěz nestačí: Jak bot na ARMv8 hledá nejen nejrychlejší kernel, ale i nejrychlejší řetězec kernelů
(praktický článek bez metafor a omáčky – jen realita, čísla a postup krok za krokem)
---
1 | Problém, který řešíme
Každou výpočetní úlohu (FFT, maticové násobení, konvoluci…) lze spustit několika způsoby:
CPU-NEON, OpenCL-GPU, Vulkan Compute, DSP/NNAPI…
V benchmarku obvykle vybereme jeden vítězný kernel (nejkratší čas v ms).
Jenže někdy je rychlejší rozdělit úlohu na více menších kroků a každý poslat tam, kde se mu daří nejlíp – i když některý z těch kroků není individuální vítěz.
---
2 | Benchmark na reálném zařízení
Zařízení Snapdragon 730 (Cortex-A76/55 + Adreno 618 GPU + Hexagon 688 DSP)
Úlohy MatMul 512², 1D FFT 4096, 2D FFT 1024², Conv 3×3 720p, SHA-256
Operace NEON OpenCL Vulkan DSP 🥇 Monolitický vítěz
MatMul 512² 41 ms 18 ms 14 ms — Vulkan
1D FFT 4096 1,9 ms 0,63 ms 0,71 ms 0,28 ms DSP
2D FFT 1024² 37 ms 9,4 ms 8,8 ms — Vulkan
Conv 3×3 720p 24 ms 7,1 ms 5,9 ms 8,4 ms Vulkan
SHA-256 1 MiB 188 MB/s — — 410 MB/s DSP
30 iterací, průměr; všechna data v sdíleném AHardwareBuffer.
---
3 | Když „monolit“ není nejrychlejší
Příklad 1 MatMul 512²
Varianta Čas (ms)
Monolitický Vulkan kernel 14,0
Kompozitní řetězec<br>① DSP dlaždice 128² (4,0 ms)<br>② NEON add mezisoučtů (2,4 ms)<br>③ GPU fuse (4,8 ms) 11,2
Příklad 2 FFT 2D 1024²
Varianta Čas (ms)
Monolitický Vulkan 2D FFT 8,8
Kompozitní řetězec<br>① DSP FFT 1D horizontálně (0,56 ms)<br>② DSP FFT 1D vertikálně (0,56 ms)<br>③ GPU filtr + transpozice (5,9 ms) 7,0
Ušetřeno 20–25 % díky paralelní práci různých jednotek a nižší frekvenční penalizaci.
---
4 | Jak bot rozhoduje, kdy složit řetězec
1. Benchmark uloží časy všech variant do results.json.
2. Graph Planner pro každou operaci vygeneruje malé DAG-y (1 → 3 kroků).
3. Pro každý DAG spočte
T_total = Σ(T_krok + T_přenos)
– zahrnuje i latenci předávání přes sdílené buffery.
4. Vybere monolit nebo kompozit s nejmenším T_total.
5. Výsledek zapíše do manifestu, např.:
{
„matmul_512": {
„winner": „vulkan_matmul.spv“,
„combo": [
{"op":"tile_mul_128“,“backend":"dsp"},
{"op":"tile_add“,"backend":"neon"},
{"op":"fuse","backend":"gpu"}
],
"t_winner": 14.0,
"t_combo": 11.2
}
}
---
5 | Generování finální APK
1. CodeGen načte manifest, do projektu přidá jen ty moduly, které manifest zmiňuje.
2. GlueLayer přidá kód pro předávání AHardwareBuffer mezi DSP ↔ GPU bez kopírování do RAM.
3. Gradle task assembleDeviceOptimized kompiluje, odřízne nevyužité back-endy (R8) a podepíše originálním klíčem.
---
6 | Reálný dopad v pipeline (video-analýza 720p)
Krok CPU-only Monolit Kompozit
2 × FFT 1D 3,8 ms 1,4 ms (DSP) 0,56 ms
Conv 3×3 24 ms 5,9 ms (GPU) 5,2 ms
SHA-256 5,6 ms 1,3 ms (DSP) 1,3 ms
Celkem / snímek 33,4 ms 8,6 ms 7,1 ms
FPS: 30 → 116
Baterie: –45 % → –29 % za 2 hodiny kontinuální analýzy.
---
7 | Co ohlídat
Riziko Ochrana v botech
Přenos > zisk Planner schvaluje řetězec jen, pokud T_přenos / T_total < 15 %.
DSP fronta plná Vkládá semaphore_wait; CPU připraví další blok.
Throttling Monitoruje GPU freq; při poklesu > 20 % přehodnotí plán.
Soft-fail Pokud jakýkoli krok chybí (staré SoC), fallback na čistý vítězný monolit.
---
8 | Shrnutí
Nejrychlejší kernel ≠ nejrychlejší pipeline.
Benchmark + Graph Planner umí vybrat buď monolit, nebo krátký řetězec dílčích vítězů / dobrých sekundantů.
Na reálném ARMv8 může kompozitní strategie ušetřit 10–25 % navíc oproti už tak rychlému monolitickému kernelu.
Praktické doporučení:
> Měřte vše, dovolte botovi skládat a nechte ho předběžně spočítat latence předávání dat.
Nakonec generujte APK, které na každém zařízení spustí buď absolutního vítěze, nebo nejrychlejší kombinaci kroků – podle tvrdých čísel, ne pocitu.