1 poin oleh GN⁺ 2025-05-11 | Belum ada komentar. | Bagikan ke WhatsApp
  • Sep 0.10.0 mencapai 21 GB/s dalam parsing CSV level rendah berkat optimasi untuk CPU yang mendukung AVX-512 seperti AMD 9950X (Zen 5), lebih cepat dari sebelumnya sekitar 18 GB/s
  • Peningkatan performa berasal dari perubahan struktur parser untuk mengurangi bottleneck akibat bolak-balik register mask dalam pembuatan kode AVX-512 di .NET 9.0
  • Parser AVX-512-to-256 baru memuat char dalam 512-bit lalu mengubahnya menjadi vektor byte 256-bit, sehingga menghindari biaya pemrosesan mask dan permutasi terpisah
  • Performa parsing level rendah Sep meningkat sekitar 3×, dari sekitar 7 GB/s pada 5950X/.NET 7.0 di versi 0.1.0 tahun 2023 menjadi sekitar 21 GB/s pada 9950X/.NET 9.0 di versi 0.10.0
  • Dalam benchmark tingkat atas, Sep multithread di 9950X memproses 1 juta baris package assets dalam 72,213 ms, sekitar 8,0 GB/s, dan data floats juga mencatat sekitar 8,1 GB/s

Tujuan dan hasil Sep 0.10.0

  • Sep 0.10.0 dirilis pada 22 April 2025, dan mencakup optimasi untuk CPU yang mendukung AVX-512 seperti AMD 9950X (Zen 5) serta benchmark 9950X
  • Berdasarkan parsing CSV level rendah, Sep mencapai 21 GB/s di 9950X
    • Sebelum 0.10.0, pada 9950X yang sama angkanya sekitar 18 GB/s
  • Cakupan analisis adalah parsing Rows level rendah pada data CSV package assets, dan semua angka berdasarkan single thread
  • Angka benchmark dapat berubah beberapa poin persentase, sehingga regresi kecil bisa terlihat pada rilis tertentu

Perubahan performa dari 0.1.0 hingga 0.10.0

  • Performa Sep meningkat bertahap melalui kombinasi perubahan kode, perubahan versi .NET, dan perubahan generasi CPU
  • Alur performa representatifnya sebagai berikut
    • 0.1.0, 5950X, .NET 7.0: sekitar 7 GB/s
    • 0.3.0, 5950X, .NET 8.0: sekitar 12 GB/s
    • 0.6.0, 5950X, .NET 9.0: sekitar 13 GB/s
    • 0.9.0, 9950X, .NET 9.0: sekitar 18 GB/s
    • 0.10.0, 9950X, .NET 9.0: sekitar 21 GB/s
  • Sejak Sep dipublikasikan pada Juni 2023, kecepatannya naik sekitar dalam waktu sedikit kurang dari 2 tahun
  • Jika membandingkan penggunaan Sep 0.9.0 di 5950X dengan Sep 0.10.0 di 9950X, peningkatannya sekitar 1,6×
    • Boost clock 9950X adalah 5,7 GHz, sedangkan 5950X adalah 4,9 GHz
    • Perbedaan clock ini saja diperkirakan dapat menjelaskan sekitar 1,2×

Bottleneck register mask pada pembuatan kode AVX-512 .NET

  • Sep mendukung AVX-512 sejak 0.2.3, tetapi saat itu .NET 8 belum mendukung register mask k1-k8 AVX-512 secara eksplisit
  • Dalam pembuatan kode AVX-512 lama, hasil perbandingan masuk ke register mask, lalu dipindahkan ke register umum, kemudian kembali lagi ke register mask
  • Setelah upgrade ke 9950X, Sep 0.9.0 mencatat sekitar 18 GB/s dalam parsing CSV level rendah, sekitar 1,4× lebih cepat dari 5950X
  • Ketika parser diubah lewat variabel lingkungan untuk perbandingan, parser AVX2 di 9950X mencatat sekitar 20 GB/s, sekitar 10% lebih cepat dari parser AVX-512 lama
  • Selisih ini memastikan bahwa pemrosesan register mask AVX-512 masih memengaruhi performa

Struktur dasar loop parsing Sep

  • Semua parser Sep mengikuti struktur dasar yang sama, dan mendukung dua jalur dengan perilaku penanganan tanda kutip berbeda melalui satu metode generik Parse
    • ParseColInfos: digunakan saat menangani tanda kutip dan membutuhkan pelacakan status lebih banyak
    • ParseColEnds: digunakan ketika tidak ada penanganan tanda kutip
  • Parsing dilakukan per span char yang diambil dari array, dengan contoh berukuran 16K
    • Ukuran ini cukup kecil untuk masuk ke cache CPU, dan juga menguntungkan untuk multithreading yang efisien setelahnya
  • Loop memuat data karakter 16-bit ke register SIMD, mengubahnya menjadi register SIMD byte, lalu membandingkan karakter khusus CSV
    • Target perbandingan mencakup \n, \r, ", ;, dan lainnya
  • Hasil perbandingan diubah menjadi bitmask, dan hanya bit yang disetel dalam mask yang di-parse secara berurutan
  • Perbedaan performa sangat bergantung pada bagaimana kode SIMD C# ini dikompilasi JIT menjadi machine code oleh .NET

Parser AVX-512 lama dan penyesuaian di 0.10.0

  • SepParserAvx512PackCmpOrMoveMaskTzcnt pada 0.9.0 memuat masing-masing 32 char ke dua register SIMD 512-bit, lalu mengemasnya menjadi satu vektor byte 512-bit untuk memproses 64 karakter per loop
  • Data yang sudah dikemas memiliki urutan yang tercampur, sehingga perlu disusun ulang dengan PermuteVar8x64
  • Dalam assembly .NET 9.0, setiap Vec.Equals diterjemahkan menjadi dua instruksi, vpcmpeqb dan vpmovm2b, dan perpindahan antara register mask seperti k1 dan register vektor umum zmm terjadi berulang kali
  • Pada Sep 0.10.0, pemanggilan MoveMask dimajukan untuk mengurangi jumlah bolak-balik antara register mask dan register umum
    • Di parser lain, MoveMask hanya dipanggil saat diperlukan untuk mengurangi jumlah instruksi pada fast path “tanpa karakter khusus”
  • Setelah penyesuaian, perpindahan dari register mask ke register umum masih tersisa, tetapi jumlah instruksi assembly secara keseluruhan berkurang

AVX2 dan parser AVX-512-to-256 baru

  • Assembly dari SepParserAvx2PackCmpOrMoveMaskTzcnt berbasis AVX2 memiliki struktur yang lebih lurus karena tidak ada register mask
  • Berkat struktur ini, parser AVX2 lebih cepat daripada parser AVX-512 lama di 0.9.0
  • SepParserAvx512To256CmpOrMoveMaskTzcnt baru di 0.10.0 memuat char dengan instruksi AVX-512 lalu membuat vektor byte 256-bit menggunakan ConvertToVector256ByteWithSaturation
    • Instruksi aktualnya adalah vpmovuswb
    • Throughput per loop “hanya” 32 char, tetapi strukturnya lebih sederhana
  • Pendekatan ini menghindari masalah register mask 512-bit, dan karena data yang dikemas sudah berada dalam urutan yang benar di ymm4, permutasi terpisah juga tidak diperlukan
  • Parser baru ini menaikkan performa parsing Sep di 9950X hingga sekitar 21 GB/s

Benchmark level rendah parser di 9950X

  • Hasil perbandingan menjalankan semua parser melalui variabel lingkungan di AMD 9950X menunjukkan bahwa parser AVX-512-to-256 baru adalah yang tercepat
  • Hasil utamanya sebagai berikut
    • 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
  • Parser cross-platform berbasis Vector256 mencapai level yang hampir sama dengan AVX2
  • Parser cross-platform berbasis Vector128 dan Vector512 masih cepat tetapi 5–10% lebih lambat, dan Vector512 lebih lambat daripada Vector128
  • SepParserIndexOfAny tertinggal jauh pada 2787,0 MB/s, dan Vector64 tidak diakselerasi di 9950X sehingga hanya berada di 459,9 MB/s

Benchmark tingkat atas 5950X dan 9950X

  • Pada data package assets, hasil pemrosesan 1 juta baris menunjukkan 9950X jauh lebih cepat daripada 5950X
    • 5950X Sep_MT: 119,430 ms, 4888,1 MB/s
    • 9950X Sep_MT: 72,213 ms, 8084,1 MB/s
  • Di 9950X, Sep single thread memproses 1 juta baris package assets dalam 291,979 ms, 1999,4 MB/s
  • Dalam benchmark package assets yang sama di 9950X, pembanding menunjukkan performa berikut
    • Sylvan: 413,265 ms, 1412,6 MB/s
    • ReadLine_: 377,033 ms, 1548,4 MB/s, alokasi 1991,04 MB
    • CsvHelper: 1005,323 ms, 580,7 MB/s
  • Pada data floats, Sep multithread di 9950X juga memproses 25.000 baris dalam 2,497 ms, 8136,8 MB/s
  • Besaran peningkatan benchmark tingkat atas dari 5950X ke 9950X mirip dengan benchmark level rendah, yaitu sekitar 1,5–1,6×

Belum ada komentar.

Belum ada komentar.