Fearless SIMD v1.0 is hier

fearless_simd haalt unsafe uit SIMD.

Het is een lange weg geweest sinds het oorspronkelijke prototype van acht jaar geleden. We zijn er nu van overtuigd dat Fearless SIMD aan al je behoeften kan voldoen, of het nu gaat om eenvoudige autovectorisatie en multiversionering, volledige portable SIMD-abstracties, of simpelweg veilige toegang tot intrinsics.

In plaats van het changelog te parafraseren, wil ik deze gelegenheid gebruiken om te reflecteren op de doelstellingen van Fearless SIMD, hoe deze worden behaald en wat het onderscheidt van andere SIMD-abstracties.

Prestaties

Een veelgehoord punt van kritiek op portable SIMD-abstracties is dat ze niet performant genoeg zijn. Daarom hebben we veel inspanningen geleverd om ervoor te zorgen dat Fearless SIMD je nooit in de weg staat.

Wanneer we bijvoorbeeld portable abstracties implementeren voor operaties die op verschillende platforms verschillend gedrag vertonen in edge-cases (zoals swizzles of floating-point maximum), bieden we twee opties aan:

  • Een nauwkeurige variant die op alle platforms hetzelfde resultaat geeft.
  • Een snelle variant die een platformafhankelijk resultaat teruggeeft, voor gebruik in situaties waarin je verwacht dat edge-cases nooit voorkomen.

Daarnaast hebben we het eenvoudig gemaakt om SIMD-algoritmen uit te drukken in termen van de native vectorgrootte van de hardware. Hierdoor profiteert je code altijd optimaal van de hardware, ongeacht waar deze op draait. Voor algoritmen die dit vereisen, worden ook vaste vectorgroottes ondersteund.

We hebben veel zorg besteed aan het optimaliseren van de implementaties van onze portable SIMD-operaties en hebben zelfs verbeteringen aangebracht in de upstream-bronnen, zowel voor Rust als LLVM.

Mocht je een instructie nodig hebben die niet door portable abstracties wordt gedekt, of wil je meer controle, dan kun je veilig overstappen naar platform-intrinsics zonder overhead voor de delen van je code die dit nodig hebben, terwijl je de rest eenvoudig en portable houdt. Dankzij de veilige toegang tot intrinsics is er geen plafond voor de prestaties.

Veiligheid

Als je in de broncode van andere SIMD-abstracties kijkt, zul je zien dat deze vol staan met onveilige code. Een zoekopdracht naar unsafe levert vaak duizenden unsafe-blokken op.

Dat is niet het geval bij Fearless SIMD. De crate is zorgvuldig ontworpen zodat ad-hoc unsafe-code niet nodig is.

Een onderdeel van de oplossing is de kernel! macro, die gebruikmaakt van target feature v1.1 in de compiler om de meeste SIMD-intrinsics aan te roepen zonder unsafe.

Dit verwijdert het grootste deel van de ad-hoc onveilige code, maar dekt geen SIMD-load/store-operaties die werken met ruwe pointers. Daar komt onze safe transmute-module om de hoek kijken, geïnspireerd door crates zoals bytemuck en zerocopy.

SIMD-intrinsics zoals mmloadu_epi32 lijken speciaal, maar veranderen achter de schermen in gewone loads en stores. Je kunt hun functionaliteit dus volledig repliceren met een enkele, herbruikbare wrapper.

Dankzij de kracht van het type-systeem van Rust hoeven we slechts deze twee kleine, zelfstandige bouwstenen te controleren. Zolang deze geheugenveilig zijn, is de rest van de codebase gegarandeerd eveneens geheugenveilig. Eindelijk kan SIMD in Rust echt "fearless" zijn.

Ergonomie

Functiemultiversionering is complex.

Eerdere oplossingen vereisten ofwel het toevoegen van #[inline(always)]-annotaties (waarbij men de implicaties hiervan moet begrijpen), of ze veroorzaakten een kleine overhead bij elke functieaanroep. Dat laatste is meestal acceptabel, maar verslechtert de prestaties bij zeer kleine functies, waardoor je alsnog chirurgisch #[inline(always)] moet toevoegen om dit te omzeilen.

Beide zijn "lekkende abstracties" — je moet nog steeds nadenken over wat er onder de motorkap gebeurt.

Samen met fearlesssimd v1.0 lanceren we fearlesssimd_macros v0.1, die een niet-lekkende abstractie biedt: de #[simd] macro. Hiermee hoef je helemaal niet meer na te denken over de interne werking. Plaats de macro op elke SIMD-functie en het werkt simpelweg.

Hoewel dit een grote stap vooruit is voor het ecosysteem, is er nog steeds sprake van enige boilerplate. We willen dit verder verminderen, eventueel via compiler-ondersteuning via de Struct Target Features RFC om de #[simd] annotatie volledig te elimineren, of via andere technieken die we in de toekomst zullen verkennen.

Voor wie geen gebruik wil maken van procedurele macro's, blijft de oude methode beschikbaar, hoewel deze minder convenient is.

Ergonomie is het enige gebied waar we verwachten dat er nog evolutie plaatsvindt. Dit tast echter de stabiliteitsgaranties van de core fearless_simd crate niet aan; code die vandaag is geschreven, met of zonder de #[simd] macro, zal onbeperkt blijven werken.

Stabiliteit

Fearless SIMD is hier om te blijven. We bieden drie jaar lang beveiligingsupdates voor v1.0 en alle latere versies.

Hoewel we de toekomst niet kunnen voorspellen, zijn er levensvatbare paden om zowel nabije Rust-functies (zoals het f16 type) als langetermijnfuncties (zoals SVE en RISC-V Vector Extension) te ondersteunen wanneer deze hardware-extensies relevant worden, zonder dat dit leidt tot API-brekende wijzigingen.

Relatie tot std::simd

We zouden graag zien dat std::simd gestabiliseerd wordt, maar dat zou Fearless SIMD niet overbodig maken.

De Rust-standaardbibliotheek implementeert alleen de onderdelen die er absoluut in moeten zitten. De rest (bijv. multiversionering, hardware-breedte vectoren) wordt overgelaten aan ecosystem-crates.

fearlesssimd bevat een equivalent van std::simd die werkt op stabiele Rust, maar dat is slechts een onderdeel van een groter geheel. Zodra std::simd is gestabiliseerd, zullen we Fearless SIMD hiernaartoe migreren om veel aangepaste code te verwijderen en ondersteuning te krijgen voor diverse obscure platforms. De behoefte aan ecosystem-crates zoals fearlesssimd zal echter blijven bestaan.

Adoptie

Het maakt niet uit hoe briljant je crate is als niemand hem gebruikt.

Fearless SIMD wordt al gebruikt door 30 andere crates als directe afhankelijkheid, en wordt indirect gebruikt door meer dan duizend crates! Het vormt al de basis voor een aanzienlijk deel van het Rust-ecosysteem, en we hopen dat v1.0 dit verder zal uitbreiden.

Als je Fearless SIMD in je project wilt gebruiken, raadpleeg dan de documentatie en voorbeelden, en stel gerust je vragen op Zulip!