Soru:
Yazılım endüstrisinin fikir birliği, temiz ve basit kodun, kod tabanının ve sahibi olan kuruluşun uzun vadeli uygulanabilirliği için temel olduğu yönündedir. Bu özellikler daha düşük bakım maliyetlerine ve kod tabanının devam etme olasılığının artmasına neden olur.
Ancak, SIMD kodu genel uygulama kodundan farklıdır ve özellikle SIMD koduna uygulanan temiz ve basit kod konusunda benzer bir fikir birliği olup olmadığını bilmek istiyorum.
Sorumun arka planı.
Çeşitli görüntü işleme ve analiz görevleri için bol miktarda SIMD (tek komutlu, çoklu veri) kodu yazıyorum. Son zamanlarda, bu işlevlerin az bir kısmını bir mimariden (SSE2) diğerine (ARM NEON) taşımak zorunda kaldım.
Kod, büzülme ile sarılmış yazılım için yazılmıştır, bu nedenle MATLAB gibi sınırsız yeniden dağıtım hakları olmadan özel dillere bağlı olamaz.
Tipik kod yapısına bir örnek:
- Kullanma OpenCV 'matrisi tipi (
Mat
) tüm bellek için, tampon ve kullanım süresi yönetimi. - Girdi bağımsız değişkenlerinin boyutunu (boyutlarını) kontrol ettikten sonra, her piksel satırının başlangıç adresine işaretçiler alınır.
- Piksel sayısı ve her giriş matrisinden her piksel satırının başlangıç adresleri bazı düşük seviyeli C ++ işlevlerine geçirilir.
- Bu düşük seviyeli C ++ işlevleri , ham işaretçi adreslerinden yükleme ve ham işaretçi adreslerine kaydetme gibi SIMD intrinsics ( Intel Mimarisi ve ARM NEON için ) kullanır.
- Bu düşük seviyeli C ++ işlevlerinin özellikleri:
- Sadece tek boyutlu (hafızada ardışık)
- Bellek ayırma işlemleriyle ilgilenmez.
(Geçiciler dahil her ayırma işlemi, OpenCV olanakları kullanılarak dış kodla gerçekleştirilir.) - Sembollerin isim uzunlukları aralığı (intrinsics, değişken isimler, vb.) Kabaca 10-20 karakterdir ve bu oldukça fazladır.
(Tekno-gevezelik gibi okur.) - Derleyiciler doğru olan kod ayrıştırma oldukça arabası çünkü SIMD değişkenlerin Tekrar önerilmez değil stil kodlama "tek atama" ile yazılmış.
(Birkaç derleyici hata raporu verdim.)
SIMD programlamanın hangi yönleri tartışmanın genel durumdan farklı olmasına neden olur? Veya SIMD neden farklı?
İlk geliştirme maliyeti açısından
- İyi bir performansa sahip C ++ SIMD kodunun ilk geliştirme maliyetinin, rasgele yazılmış C ++ koduna kıyasla yaklaşık 10x - 100x (geniş bir marjla) olduğu bilinmektedir .
- Performans ile okunabilir / temiz kod arasında seçim yapma cevaplarında belirtildiği gibi ? , çoğu kod (rasgele yazılmış kod ve SIMD kodu dahil) başlangıçta ne temiz ne de hızlıdır .
- Kod performansındaki (hem skaler hem de SIMD kodunda) evrimsel iyileştirmeler önerilmez (çünkü bir tür yazılım yeniden çalışması olarak görülür ) ve maliyet ve fayda izlenmez.
Eğilim açısından
(örneğin Pareto prensibi, yani 80-20 kuralı )
- Görüntü işleme bir yazılım sisteminin sadece% 20'sini (hem kod boyutu hem de işlevsellik) içeriyor olsa bile, görüntü işleme nispeten yavaştır (harcanan CPU zamanının yüzdesi olarak bakıldığında) ve% 80'den fazla zaman alır.
- Bunun nedeni veri boyutu efektidir: Tipik bir görüntü boyutu megabayt olarak ölçülürken, görüntü olmayan verilerin tipik boyutu kilobayt olarak ölçülür.
- Görüntü işleme kodu içinde, bir SIMD programcısı, C ++ kodundaki döngü yapısını tanımlayarak sıcak noktaları içeren% 20 kodunu otomatik olarak tanıyacak şekilde eğitilir. Dolayısıyla, bir SIMD programcısının bakış açısından, "önemli olan kodun"% 100'ü performans darboğazıdır.
- Genellikle bir görüntü işleme sisteminde, birden fazla sıcak nokta bulunur ve karşılaştırılabilir oranlarda zaman alır. Örneğin, her biri toplam süreyi alan 5 sıcak nokta (% 20,% 18,% 16,% 14,% 12) olabilir. Yüksek performans artışı elde etmek için, tüm sıcak noktaların SIMD'de yeniden yazılması gerekir.
- Bu balon patlatma kuralı olarak özetlenir : bir balon iki kez patlatılamaz.
- Diyelim ki 5 tane balon var. Onları yok etmenin tek yolu onları tek tek patlatmaktır.
- İlk balon patlatıldıktan sonra, kalan 4 balon artık toplam yürütme süresinin daha yüksek bir yüzdesini içermektedir.
- Daha fazla kazanç elde etmek için, daha sonra başka bir balonu patlatmak gerekir.
(Bu kadar hiçe sayarak optimizasyon 80-20 üstünlüğü: İyi bir ekonomik sonuç aldı edilmiştir düşük-asılı meyve% 20 sonra elde edilebilir.)
Okunabilirlik ve bakım açısından
SIMD kodunun okunması zordur.
- Adlandırma, kapsülleme, sabit doğruluk (ve yan etkileri açık hale getirme), işlev ayrışması vb. Gibi her yazılım mühendisliği en iyi uygulamasını izlese bile bu doğrudur.
- Bu, deneyimli SIMD programcıları için bile geçerlidir.
Optimal SIMD kodu, eşdeğer C ++ prototip koduna kıyasla çok kıvrılmıştır (açıklamaya bakınız) .
- SIMD kodunu bükmenin birçok yolu vardır, ancak bu tür 10 denemeden yalnızca biri kabul edilebilir derecede hızlı sonuçlara ulaşacaktır.
- (Yani, yüksek geliştirme maliyetini haklı çıkarmak için 4x-10x performans kazançları arasında. Uygulamada daha yüksek kazançlar gözlemlenmiştir.)
(Not)
Bu, MIT Halide projesinin ana tezidir- makalenin başlık kelimesini alıntılamak:
"Görüntü işleme boru hatlarının kolay optimizasyonu için zamanlamalardan algoritmaları ayırmak"
İleri uygulanabilirlik açısından
- SIMD kodu kesinlikle tek bir mimariye bağlıdır. Her yeni mimari (veya SIMD kayıtlarının her genişletilmesi) bir yeniden yazma gerektirir.
- Yazılım geliştirmenin çoğundan farklı olarak, her SIMD kodu parçası genellikle hiçbir zaman değişmeyen tek bir amaç için yazılır.
(Diğer mimarilere taşıma hariç.) - Bazı mimariler mükemmel geriye dönük uyumluluk sağlar (Intel); önemsiz bir miktarda (ARM AArch64 değiştirilmesiyle bir düşüş kısa
vtbl
olanvtblq
), ancak yeterli olan bir kod derlemek için başarısız olmasına neden.
Beceri ve eğitim açısından
- Yeni bir programcıyı SIMD kodu yazmak ve korumak için uygun şekilde eğitmek için hangi bilgi ön koşullarının gerekli olduğu açık değildir.
- Okulda SIMD programlamasını öğrenen üniversite mezunları bunu pratik bir kariyer izi olarak görmezden gelir ve reddederler.
- Demontaj okuma ve düşük seviye performans profili, yüksek performanslı SIMD kodu yazmak için iki temel beceri olarak belirtilir. Ancak, programcılara bu iki beceri konusunda nasıl sistematik bir şekilde eğitim verileceği belirsizdir.
- Modern CPU mimarisi (ders kitaplarında öğretilenlerden önemli ölçüde farklılaşır) eğitimi daha da zorlaştırır.
Doğruluk ve kusurla ilgili maliyetler açısından
- Tek bir SIMD işleme fonksiyonu, şu şekilde doğruluk sağlayabilecek kadar uyumludur:
- Resmi yöntemlerin uygulanması (kalem ve kağıt ile) ve
- Çıkış tamsayı aralıklarını doğrulama (prototip kodu ile ve çalışma zamanı dışında gerçekleştirilir) .
- Bununla birlikte, doğrulama işlemi çok maliyetlidir (SIMD kodunun zaten pahalı geliştirme maliyetini üçe katlayan), kod incelemesine% 100 zaman ve prototip model kontrolüne% 100 zaman harcar.
- Bir hata bir şekilde bu doğrulama işleminden geçmeyi başarırsa, şüpheli kusurlu işlevi değiştirmek (yeniden yazmak) dışında "onarmak" (düzeltmek) neredeyse imkansızdır.
- SIMD kodu, C ++ derleyicisindeki kusurların körlenmesinden muzdariptir (kod üreteci optimize edilir).
- C ++ ifade şablonları kullanılarak oluşturulan SIMD kodu da derleyicinin kusurlarından büyük ölçüde etkilenir.
Yıkıcı yenilikler açısından
Akademiden birçok çözüm önerilmiştir, ancak çok azı yaygın ticari kullanım görmektedir.
- MIT Halide
- Stanford Karanlık Oda
- NT2 (Sayısal Şablon Araç Kutusu) ve ilgili Boost.SIMD
Yaygın ticari kullanımı olan kütüphaneler, SIMD özellikli değildir.
- Açık kaynaklı kütüphaneler SIMD için ılık görünüyor.
- Son zamanlarda, 2.4.9 sürümünden itibaren çok sayıda OpenCV API fonksiyonunun profilini oluşturduktan sonra bu ilk elden gözlemim var.
- Profillediğim diğer birçok görüntü işleme kütüphanesi de SIMD'yi yoğun bir şekilde kullanmıyor veya gerçek sıcak noktaları kaçırıyor.
- Ticari kütüphaneler SIMD'den tamamen uzak görünüyor.
- Bazı durumlarda, daha önceki bir sürümde SIMD için optimize edilmiş kodu daha sonraki bir sürümde SIMD olmayan koda döndüren görüntü işleme kitaplıklarının bile ciddi performans gerilemelerine neden olduğunu gördüm.
(Satıcının yanıtı, derleyici hatalarından kaçınmak gerektiğidir.)
- Bazı durumlarda, daha önceki bir sürümde SIMD için optimize edilmiş kodu daha sonraki bir sürümde SIMD olmayan koda döndüren görüntü işleme kitaplıklarının bile ciddi performans gerilemelerine neden olduğunu gördüm.
- Açık kaynaklı kütüphaneler SIMD için ılık görünüyor.
Bu Programcının sorusu: Düşük gecikme kodunun bazen "çirkin" olması gerekir mi? ilişkilidir ve daha önce bu soruya birkaç yıl önce bakış açımı açıklamak için bir cevap yazdım.
Ancak, bu cevap hemen hemen "erken optimizasyon" bakış açısına, yani şu bakış açısına "yatıştırmak" tır:
- Tüm optimizasyonlar tanım gereği erken (veya doğaları gereği kısa vadeli ) ve
- Uzun vadeli faydası olan tek optimizasyon basitliğe yöneliktir.
Ancak bu bakış açıları bu ACM makalesinde tartışılmaktadır .
Tüm bunlar sormamı sağlıyor:
SIMD kodu genel uygulama kodundan farklı ve SIMD kodu için temiz ve basit kodun değeri konusunda benzer bir endüstri mutabakatı olup olmadığını bilmek istiyorum.