1 puan yazan GN⁺ 2025-05-11 | Henüz yorum yok. | WhatsApp'ta paylaş
  • Sep 0.10.0, AMD 9950X (Zen 5) gibi AVX-512 destekli CPU optimizasyonlarıyla düşük seviyeli CSV ayrıştırmada 21 GB/s’ye ulaşarak önceki yaklaşık 18 GB/s seviyesini aştı
  • Performans artışı, .NET 9.0’ın AVX-512 kod üretiminde oluşan maske register gidiş-dönüşü darboğazını azaltacak şekilde ayrıştırıcı yapısının değiştirilmesinden geliyor
  • Yeni AVX-512-to-256 ayrıştırıcı, char verilerini 512 bit olarak yükleyip ardından 256 bit bayt vektörüne dönüştürerek maske işleme ve ayrı permütasyon maliyetinden kaçınıyor
  • Sep’in düşük seviyeli ayrıştırma performansı, 2023’te 0.1.0 sürümünde 5950X/.NET 7.0 ile yaklaşık 7 GB/s iken, 0.10.0’da 9950X/.NET 9.0 ile yaklaşık 21 GB/s’ye çıkarak yaklaşık 3 kat iyileşti
  • Üst seviye benchmark’larda da 9950X çok iş parçacıklı Sep, 1 milyon satırlık package assets verisini 72.213 ms’de, yaklaşık 8.0 GB/s hızla işledi; floats verisinde de yaklaşık 8.1 GB/s kaydetti

Sep 0.10.0’ın hedefi ve sonuçları

  • Sep 0.10.0, 22 Nisan 2025’te yayımlandı ve AMD 9950X (Zen 5) gibi AVX-512 destekli CPU optimizasyonları ile 9950X benchmark’larını içeriyor
  • Düşük seviyeli CSV ayrıştırma ölçütünde Sep, 9950X’te 21 GB/s’ye ulaşıyor
    • 0.10.0’dan önce aynı 9950X’te yaklaşık 18 GB/s idi
  • Analiz kapsamı, package assets CSV verisinin düşük seviyeli Rows ayrıştırmasıdır ve tüm değerler tek iş parçacığı bazındadır
  • Benchmark değerleri birkaç yüzde puanı oynayabildiğinden, belirli bir sürümde küçük gerilemeler görülebilir

0.1.0’dan 0.10.0’a performans değişimi

  • Sep performansı; kod değişiklikleri, .NET sürümü değişimleri ve CPU nesli değişimleri birlikte etkili olarak kademeli biçimde iyileşti
  • Temsili performans akışı şöyle:
    • 0.1.0, 5950X, .NET 7.0: yaklaşık 7 GB/s
    • 0.3.0, 5950X, .NET 8.0: yaklaşık 12 GB/s
    • 0.6.0, 5950X, .NET 9.0: yaklaşık 13 GB/s
    • 0.9.0, 9950X, .NET 9.0: yaklaşık 18 GB/s
    • 0.10.0, 9950X, .NET 9.0: yaklaşık 21 GB/s
  • Sep’in Haziran 2023’te duyurulmasından bu yana iki yıldan biraz kısa sürede yaklaşık 3 kat hızlandı
  • 5950X’te Sep 0.9.0 kullanımı ile 9950X’te Sep 0.10.0 kullanımı karşılaştırıldığında yaklaşık 1.6 kat iyileşme görülüyor
    • 9950X’in boost saat hızı 5.7 GHz, 5950X’inki 4.9 GHz
    • Yalnızca bu saat hızı farkının yaklaşık 1.2 katı açıklayabileceği değerlendiriliyor

.NET AVX-512 kod üretiminde maske register darboğazı

  • Sep, 0.2.3’ten itibaren AVX-512 destekliyordu; ancak o dönem .NET 8, AVX-512’nin k1-k8 maske register’larını açıkça desteklemiyordu
  • Mevcut AVX-512 kod üretiminde karşılaştırma sonucu maske register’ına giriyor, ardından genel register’a taşınıyor ve tekrar maske register’ına dönüyordu
  • 9950X’e yükseltmeden sonra Sep 0.9.0, düşük seviyeli CSV ayrıştırmada yaklaşık 18 GB/s kaydetti; bu, 5950X’ten yaklaşık 1.4 kat hızlıydı
  • Ortam değişkeniyle ayrıştırıcılar değiştirilip karşılaştırıldığında, 9950X’te AVX2 ayrıştırıcı yaklaşık 20 GB/s’ye ulaşarak mevcut AVX-512 ayrıştırıcıdan yaklaşık %10 hızlı çıktı
  • Bu fark, AVX-512 maske register işlemenin performansı hâlâ etkilediğini doğruladı

Sep ayrıştırma döngüsünün temel yapısı

  • Sep’in tüm ayrıştırıcıları aynı temel yapıyı izler ve tek bir Parse jenerik metodu, tırnak işleme durumuna göre iki farklı yolu destekler
    • ParseColInfos: tırnak işleme sırasında kullanılır ve daha fazla durum takibi gerektirir
    • ParseColEnds: tırnak işleme olmadığında kullanılır
  • Ayrıştırma, diziden alınan char span’leri üzerinde yapılır; örnekte boyut 16K’dır
    • Bu boyut CPU önbelleğine sığacak kadar küçüktür ve sonrasında verimli çok iş parçacıklı çalışmaya da avantaj sağlar
  • Döngü, SIMD register’ına 16 bit karakter verisini yükler, bunu bayt SIMD register’ına dönüştürür ve ardından CSV özel karakterleriyle karşılaştırır
    • Karşılaştırma hedefleri arasında \n, \r, ", ; gibi karakterler bulunur
  • Karşılaştırma sonucu bit maskesine dönüştürülür ve maskede ayarlı bitler sırayla ayrıştırılır
  • Performans farkı, bu SIMD C# kodunun .NET tarafından nasıl makine koduna JIT derlendiğine büyük ölçüde bağlıdır

Mevcut AVX-512 ayrıştırıcı ve 0.10.0’daki ayarlama

  • 0.9.0’daki SepParserAvx512PackCmpOrMoveMaskTzcnt, iki adet 512 bit SIMD register’ına ayrı ayrı 32’şer char yükler, bunları tek bir 512 bit bayt vektörüne paketleyerek döngü başına 64 karakter işler
  • Paketlenen verinin sırası karışık olduğundan PermuteVar8x64 ile yeniden düzenlenmesi gerekir
  • .NET 9.0 assembly’sinde her Vec.Equals, vpcmpeqb ve vpmovm2b olmak üzere iki komuta dönüşüyordu; k1 gibi maske register’ları ile zmm genel vektör register’ları arasında taşıma tekrarlanıyordu
  • Sep 0.10.0’da MoveMask çağrısı daha erkene alınarak maske register’ı ile genel register arasındaki gidiş-dönüş sayısı azaltıldı
    • Diğer ayrıştırıcılarda, “özel karakter yok” hızlı yolunda komut sayısını azaltmak için MoveMask yalnızca gerektiğinde çağrılır
  • Ayarlamadan sonra da maske register’ından genel register’a taşıma devam etse de toplam assembly komutu sayısı azaldı

AVX2 ve yeni AVX-512-to-256 ayrıştırıcı

  • AVX2 tabanlı SepParserAvx2PackCmpOrMoveMaskTzcnt assembly’si maske register içermediği için daha doğrusal bir yapıya sahiptir
  • Bu yapı sayesinde AVX2 ayrıştırıcı, mevcut 0.9.0 AVX-512 ayrıştırıcıdan daha hızlıydı
  • 0.10.0’daki yeni SepParserAvx512To256CmpOrMoveMaskTzcnt, AVX-512 komutlarıyla char yükledikten sonra ConvertToVector256ByteWithSaturation ile 256 bit bayt vektörü oluşturur
    • Gerçek komut vpmovuswb’dir
    • Döngü başına iş hacmi “yalnızca” 32 char olsa da yapı daha basittir
  • Bu yöntem 512 bit maske register sorunundan kaçınır; paketlenen veri zaten ymm4 içinde doğru sırada olduğundan ayrı permütasyon da gerekmez
  • Yeni ayrıştırıcı, 9950X’te Sep ayrıştırma performansını yaklaşık 21 GB/s’ye çıkardı

Ayrıştırıcı bazında 9950X düşük seviyeli benchmark’ları

  • AMD 9950X’te tüm ayrıştırıcılar ortam değişkeniyle çalıştırılıp karşılaştırıldığında, yeni AVX-512-to-256 ayrıştırıcı en hızlısı oldu
  • Başlıca sonuçlar şöyle:
    • SepParserAvx512To256CmpOrMoveMaskTzcnt: 21597.7 MB/s, 27.0 ns/row, 1.351 ms
    • SepParserVector256NrwCmpExtMsbTzcnt: 20608.5 MB/s, 28.3 ns/row, 1.416 ms
    • SepParserAvx2PackCmpOrMoveMaskTzcnt: 20599.3 MB/s, 28.3 ns/row, 1.417 ms
    • SepParserAvx512PackCmpOrMoveMaskTzcnt: 19944.3 MB/s, 29.3 ns/row, 1.463 ms
  • Vector256 tabanlı çapraz platform ayrıştırıcı, AVX2 ile neredeyse aynı seviyeye ulaştı
  • Vector128 ve Vector512 tabanlı çapraz platform ayrıştırıcılar hâlâ hızlı olsa da %5-10 daha yavaştı; Vector512, Vector128’den daha yavaştı
  • SepParserIndexOfAny, 2787.0 MB/s ile belirgin biçimde geride kaldı; Vector64 ise 9950X’te hızlandırılmadığından 459.9 MB/s’de kaldı

5950X ve 9950X’in üst seviye benchmark’ları

  • package assets verisinde 1 milyon satır işleme sonuçlarında 9950X, 5950X’ten belirgin biçimde hızlıydı
    • 5950X Sep_MT: 119.430 ms, 4888.1 MB/s
    • 9950X Sep_MT: 72.213 ms, 8084.1 MB/s
  • 9950X’te tek iş parçacıklı Sep, 1 milyon satırlık package assets verisini 291.979 ms’de, 1999.4 MB/s hızla işledi
  • Aynı 9950X package assets benchmark’ında karşılaştırılan diğer seçeneklerin performansı şöyleydi:
    • Sylvan: 413.265 ms, 1412.6 MB/s
    • ReadLine_: 377.033 ms, 1548.4 MB/s, ayırma miktarı 1991.04 MB
    • CsvHelper: 1005.323 ms, 580.7 MB/s
  • floats verisinde de 9950X’in çok iş parçacıklı Sep’i 25.000 satırı 2.497 ms’de, 8136.8 MB/s hızla işledi
  • 5950X’ten 9950X’e geçişte üst seviye benchmark iyileşmesi, düşük seviyeli benchmark’lara benzer şekilde yaklaşık 1.5-1.6 kattır

Henüz yorum yok.

Henüz yorum yok.