Tutorial

Fearless SIMD v1.0: SIMD di Rust Tanpa Blok unsafe

Fearless SIMD v1.0: SIMD di Rust Tanpa Blok unsafe

Rust dikenal sebagai bahasa yang aman, tapi ada satu area yang sejak lama jadi pengecualian: SIMD. Hampir semua abstraksi SIMD di ekosistem Rust penuh dengan blok unsafe. Crate fearless_simd dari Linebender merilis versi 1.0 pada 22 September 2026 dengan klaim yang sangat spesifik: mengeluarkan unsafe dari SIMD.

Penulisnya, Shnatsel, menyebut proyek ini sebagai kelanjutan prototipe yang mulai delapan tahun lalu. Menurutnya, sekarang crate ini bisa melayani hampir semua kebutuhan, mulai dari autovectorization dan multiversioning, abstraksi SIMD portabel, sampai akses aman ke intrinsics.

Masalah yang coba diselesaikan

SIMD, atau single instruction multiple data, adalah teknik memproses beberapa nilai sekaligus dalam satu instruksi CPU. Untuk pekerjaan seperti pemrosesan gambar, kompresi, parsing, dan komputasi numerik, SIMD bisa memberi lompatan performa yang besar.

Masalahnya, hampir semua abstraksi SIMD di Rust terpaksa memakai unsafe. Argumen Shnatsel cukup tajam: kalau sumber kode abstraksi SIMD apa pun dicari dengan pola rg unsafe, hasilnya bisa mencapai beberapa ribu blok. Selama ini itu diterima sebagai konsekuensi wajar, karena bekerja dengan register vektor dan pointer mentah memang dianggap butuh kode tidak aman.

fearless_simd menolak asumsi itu. Klaim utamanya bukan cuma "lebih sedikit unsafe", melainkan tidak butuh unsafe ad hoc sama sekali.

Bagaimana unsafe dihilangkan

Ada dua bagian yang jadi kunci, dan keduanya sengaja dibuat kecil dan mandiri.

Pertama, makro kernel!. Makro ini bersandar pada target feature v1.1 di compiler untuk memanggil sebagian besar intrinsics SIMD tanpa unsafe. Dengan begitu, bagian terbesar dari masalah hilang di level compiler, bukan di level pembungkus manual.

Kedua, modul safe transmute. Makro kernel! belum menutup operasi load dan store SIMD yang bekerja pada pointer mentah. Di situlah modul transmute yang aman masuk. Modul ini terinspirasi crate seperti bytemuck dan zerocopy.

Alasan pendekatannya bisa dipertanggungjawabkan: intrinsics SIMD seperti _mm_loadu_epi32 terlihat istimewa, tapi sebenarnya hanya berujung pada load dan store biasa. Artinya fungsinya bisa direplikasi penuh dengan satu pembungkus yang bisa dipakai ulang. Karena itu, hanya dua blok kecil yang perlu diaudit. Selama keduanya memory-safe, seluruh sisa kode dijamin memory-safe juga.

Performa: klaim utamanya tidak mengorbankan kecepatan

Kritik yang paling sering dialamatkan ke abstraksi SIMD portabel adalah performanya kurang. Tim fearless_simd mengaku menaruh banyak usaha supaya crate ini tidak jadi penghambat, dan ada beberapa keputusan desain yang menarik di situ.

Salah satunya soal operasi yang perilakunya berbeda di kondisi tepi antar platform, seperti swizzle atau perhitungan nilai maksimum bilangan floating-point. Untuk kasus seperti itu, crate ini menyediakan dua varian: varian presisi yang hasilnya sama di semua platform, dan varian cepat yang hasilnya bergantung platform untuk dipakai ketika kondisi tepi diperkirakan tidak akan terjadi.

Selain itu, algoritma SIMD bisa dinyatakan dalam ukuran vektor native perangkat keras, sehingga kode selalu memanfaatkan perangkat sepenuhnya di mana pun ia berjalan. Ukuran vektor tetap juga tetap didukung untuk algoritma yang memang membutuhkannya.

Yang juga layak dicatat: tim ini mengklaim sudah menyumbang perbaikan ke hulu, baik ke Rust maupun ke LLVM, supaya implementasi operasi SIMD portabel mereka setara dengan yang terbaik. Dan kalau ada instruksi yang tidak tercakup abstraksi portabel, pengguna bisa turun ke platform intrinsics secara aman tanpa overhead, untuk bagian kode yang memang butuh. Karena akses ke intrinsics-nya aman, klaim mereka, tidak ada plafon performa.

Ergonomics: dari #[inline(always)] ke atribut #[simd]

Function multiversioning, yaitu kemampuan menyediakan beberapa implementasi fungsi untuk level instruksi CPU berbeda lalu memilih yang sesuai saat runtime, selama ini merepotkan. Solusi sebelumnya, menurut penulisnya, punya dua kelemahan: ada yang mengharuskan menambahkan anotasi #[inline(always)] plus memahami implikasinya, ada yang membebankan sedikit overhead di setiap pemanggilan fungsi.

Overhead kecil biasanya tidak masalah, tapi jadi masalah untuk fungsi yang sangat pendek, dan tetap menuntut penambahan #[inline(always)] secara manual untuk menghindarinya. Penulisnya menyebut keduanya sebagai abstraksi bocor, karena pengguna masih harus memikirkan apa yang terjadi di balik layar.

Bersamaan dengan fearless_simd v1.0, dirilis juga fearless_simd_macros v0.1 yang menyediakan atribut #[simd]. Cara pakainya sesederhana menempelkan atribut itu pada fungsi SIMD. Bentuk penandaannya kurang lebih seperti ini, dan detail lengkapnya ada di dokumentasi crate:

// multiversioning ditangani compiler, pengguna cukup menandai fungsinya
#[simd]
fn proses(data: &mut [f32]) {
    // implementasi SIMD
}

Penulisnya tetap jujur soal batasnya. Masih ada sejumlah boilerplate yang terlibat, dan mereka ingin menguranginya lebih jauh, salah satunya lewat dukungan compiler melalui Struct Target Features RFC supaya anotasi #[simd] tidak perlu sama sekali. Ergonomics disebut sebagai satu-satunya area yang kemungkinan masih akan berkembang, tapi itu tidak mengorbankan jaminan stabilitas crate intinya. Kode yang ditulis hari ini, dengan atau tanpa makro #[simd], disebut akan terus berjalan tanpa batas waktu.

Adopsi: 30 crate langsung, lebih dari seribu tidak langsung

Bagian ini yang sering menentukan apakah sebuah crate layak dipakai di proyek produksi. Penulisnya sendiri menulis, tidak peduli seberapa cerdas crate-mu kalau tidak ada yang memakainya.

Angka yang disebut: fearless_simd sudah dipakai 30 crate lain sebagai dependensi langsung, dan diandalkan secara tidak langsung oleh lebih dari seribu crate. Menurut penulisnya, crate ini sudah menopang sebagian nyata dari ekosistem Rust, dan rilis 1.0 diharapkan memperluasnya lagi.

Stabilitas dan jalur ke depan

Linebender berkomitmen menyediakan tiga tahun pembaruan keamanan untuk v1.0 dan semua versi setelahnya. Mereka juga menyebut ada jalur yang layak untuk mendukung fitur Rust jangka pendek seperti tipe f16, dan fitur jangka panjang seperti SVE serta RISC-V Vector Extension, tanpa perubahan API yang merusak.

Soal hubungan dengan std::simd di pustaka standar Rust, posisinya cukup jelas. Tim ini ingin std::simd segera stabil, tapi menurut mereka itu tidak membuat fearless_simd usang. Alasannya, pustaka standar Rust hanya mengimplementasikan bagian yang benar-benar harus ada di sana, sementara sisanya seperti multiversioning dan vektor selebar perangkat keras diserahkan ke crate ekosistem.

fearless_simd sendiri menyertakan padanan std::simd yang bekerja di Rust stable, tapi itu hanya satu bagian dari keseluruhan yang lebih besar. Setelah std::simd stabil, mereka berencana mem-port Fearless SIMD ke sana untuk menghapus banyak kode kustom dan mendapat dukungan untuk platform-platform yang jarang. Kebutuhan akan crate ekosistem seperti ini disebut tetap ada.

Apa artinya untuk pengguna Rust sehari-hari

Bagi sebagian besar developer Rust, SIMD terdengar seperti wilayah yang hanya relevan untuk orang yang menulis codec video atau mesin render. Anggapannya tidak sepenuhnya salah, tapi ada beberapa situasi yang lebih dekat ke pekerjaan sehari-hari:

  • Pemrosesan teks dan parsing. Mencari pola, memvalidasi UTF-8, atau memecah baris pada file besar adalah pekerjaan yang sudah lazim dipercepat dengan SIMD.
  • Operasi numerik pada data besar. Perhitungan statistik, transformasi matriks, dan agregasi pada dataset besar sering terhambat di loop yang bisa divektorisasi.
  • Pemrosesan gambar dan audio. Konversi warna, resampling, dan filtering adalah kandidat klasik karena polanya seragam dan datanya besar.
  • Kriptografi dan hashing. Banyak implementasi hash modern sudah memakai jalur SIMD untuk batch kecil input.

Selama ini, masuk ke SIMD praktis berarti menerima salah satu dari dua hal: kode unsafe yang harus diaudit sendiri, atau abstraksi yang hasilnya tidak pasti. Rilis ini menawarkan jalur ketiga, yaitu memakai abstraksi portabel sambil tetap bisa turun ke intrinsics secara aman saat butuh.

Konteks historisnya juga layak dicatat. Prototipe Fearless SIMD dimulai delapan tahun lalu, dan desain makro kernel! dijelaskan penulisnya di tulisan terpisah. Artinya ini bukan proyek yang muncul tiba-tiba menjelang rilis, melainkan sesuatu yang digarap bertahun-tahun sebelum dianggap cukup stabil untuk diberi label 1.0. Crate-nya juga tersedia dengan dokumentasi dan contoh, dan pertanyaan bisa diajukan lewat Zulip.

Yang menarik untuk diperhatikan ke depan adalah arah std::simd. Kalau itu akhirnya stabil, bagian padanan std::simd di fearless_simd akan di-port ke sana dan sejumlah kode kustom bisa dihapus. Tapi kebutuhan akan multiversioning dan vektor selebar perangkat keras tetap tidak akan ditangani pustaka standar, jadi ruang untuk crate seperti ini tetap ada.

Yang perlu diperhatikan sebelum dipakai

Beberapa hal yang wajar dicek dulu sebelum menjadikan crate ini bagian dari jalur kritis:

  • Angka adopsi datang dari pihak pembuat crate. Klaim 30 dependensi langsung dan lebih dari seribu tidak langsung belum diverifikasi independen di artikel ini. Cara paling murah memeriksanya adalah lewat halaman crate dan grafik dependensi di crates.io.
  • Ergonomics masih bergerak. Atribut #[simd] baru di v0.1 dan penulisnya sendiri menyebut area ini kemungkinan masih berubah. Crate intinya stabil, tapi lapisan makro-nya masih muda.
  • Klaim performa bersifat kualitatif di pengumuman. Tulisan itu menyebut implementasi mereka setara dengan yang terbaik dan sudah disumbangkan ke hulu, tapi tidak menyajikan benchmark angka. Kalau performa jadi alasan utama adopsi, ukur sendiri dengan beban kerja Anda.
  • Jaminan tiga tahun pembaruan keamanan adalah komitmen yang berguna, dan sekaligus alasan untuk memastikan proyek Anda memang masih dirawat dalam rentang itu.

Untuk tim yang selama ini menghindari SIMD di Rust karena tidak nyaman dengan jumlah unsafe di abstraksinya, rilis ini menawarkan jalur yang cukup berbeda. Pendekatannya bukan mengurangi kode tidak aman, melainkan memindahkan bagian tidak aman ke dua blok kecil yang bisa diaudit, lalu menutup sisanya dengan jaminan tipe Rust. Kalau klaim itu bertahan di pengujian nyata, itu perubahan yang cukup berarti untuk cara penulisan kode numerik di Rust.

Sumber

Catatan: seluruh klaim teknis, angka adopsi, dan komitmen dukungan dalam artikel ini bersumber dari tulisan pengumuman Linebender dan belum diverifikasi lewat pengujian independen. Contoh kode di atas hanya menunjukkan bentuk penandaannya, bukan API lengkap.

💬 Komentar (0)

Belum ada komentar. Jadilah yang pertama! 💬

Komentar akan muncul setelah moderasi.