NEON'da Stream Compaction: copy_if Elle Nasıl Vektörleştirilir
NEON'un compress komutu eksikliği yüzünden compiler'ın vektörleştiremediği copy_if döngüsü, tbl tablo araması ve önceden hesaplanmış indeks tablolarıyla 30 kat hızlandırılıyor.
Bir dizideki koşulu sağlayan elemanları boşluksuz şekilde başka bir diziye kopyalamak (copy_if) basit görünse de derleyiciler için ciddi bir engel taşır: çıkış imleci veri bağımlı olduğundan clang bunu ne induction ne de reduction olarak sınıflandırabilir ve döngüyü vektörleştiremez. Apple M5 üzerinde yapılan ölçümler, koşulsuz kopyalamanın 112 GB/s bant genişliğine ulaşırken, dallanma tahmini kötü olan (yüzde 50 olasılıklı) bir if koşulunun bunu 2.6 GB/s'ye kadar düşürdüğünü gösteriyor.
Sorunun kökü NEON mimarisinin x86'daki compress benzeri bir talimata sahip olmamasıdır. Yazı, bu eksikliği tbl (table lookup) komutuyla telafi eden bir teknik sunuyor: maske register'ı önce bir sayıya (idx) dönüştürülüyor, ardından derleme zamanında hesaplanmış 16 farklı indeks ve sayaç tablosu kullanılarak seçilen float değerleri register içinde öne toplanıyor. Bu sayede tbl komutu, x86'daki pshufb'a benzer şekilde byte düzeyinde permütasyon yaparak compress işlevini emüle ediyor.
Sonuç olarak elde edilen compress_neon fonksiyonu, hem seçilen eleman sayısını hem de sıkıştırılmış register'ı döndürerek copy_if döngüsünü tamamen vektörleştirilebilir hale getiriyor. Bu yaklaşım, mobil ve Apple Silicon çekirdeklerinde yaygın olan NEON SIMD kümesinde branch-heavy filtreleme kodlarının performansını önemli ölçüde artırmak isteyen sistem programcıları için pratik bir referans niteliğinde.