- Sep เวอร์ชันล่าสุด 0.10.0 ทำความเร็วการแยกวิเคราะห์ CSV ได้สูงถึง 21 GB/s บน AMD 9950X
- ประสิทธิภาพดีขึ้นอย่างมากจากการรองรับ AVX-512 และการแก้ปัญหาเกี่ยวกับ mask register
- ตัวแยกวิเคราะห์ AVX-512-to-256 แบบใหม่ให้ผลลัพธ์เหนือกว่า AVX2 และตัวแยกวิเคราะห์ AVX-512 แบบเดิม
- ในสภาพแวดล้อมแบบ มัลติเธรด สามารถประมวลผล 1 ล้านแถวได้ใน 72ms พร้อมแบนด์วิดท์ 8 GB/s
- ด้วย การปรับแต่งซอฟต์แวร์และฮาร์ดแวร์อย่างต่อเนื่อง ทำให้ประสิทธิภาพดีขึ้นราว 3 เท่าในช่วง 2 ปี
ภาพรวมการออก Sep 0.10.0 และการเพิ่มขึ้นของประสิทธิภาพ
- Sep ได้ทำการปรับแต่งสำหรับ CPU ที่รองรับ AVX-512 (เช่น AMD 9950X, Zen 5) ในรีลีส 0.10.0 ล่าสุด และมีการอัปเดตผลเบนช์มาร์ก
- ในเวอร์ชันล่าสุด ทำผลงานที่โดดเด่นด้วยความเร็ว 21 GB/s ในการแยกวิเคราะห์ CSV ระดับล่าง
- เป็นการเพิ่มประสิทธิภาพอย่างชัดเจนเมื่อเทียบกับเวอร์ชันก่อนหน้าที่ทำได้ 18 GB/s
- รายละเอียดการปรับปรุงสามารถดูได้จาก GitHub release และ README ของ Sep
- เนื้อหานี้อธิบายกระบวนการเพิ่มประสิทธิภาพผ่าน โค้ด C# ที่อาศัย SIMD และแอสเซมบลี x64 SIMD ซึ่งใช้เพื่อหลีกเลี่ยงความไม่มีประสิทธิภาพของ machine code แบบ AVX-512 ใน .NET 9.0
เส้นทางการพัฒนาประสิทธิภาพของ Sep
- มีการนำเสนอภาพรวมเชิงภาพตั้งแต่ Sep รุ่นแรก 0.1.0 ถึง 0.10.0, จาก .NET 7.0 ถึง 9.0 และจาก AMD 5950X (Zen 3) ไปสู่ 9950X (Zen 5)
- เบนช์มาร์กอ้างอิงจากการทำงานแบบเธรดเดียว และอาจมีความผันผวนเล็กน้อยในแต่ละรีลีส
- ประเด็นสำคัญ คือทั้งการรีแฟกเตอร์ขนาดใหญ่ (การเขียนโครงสร้างภายในใหม่ใน 0.2.0) และการปรับปรุงเล็ก ๆ ที่สะสมต่อเนื่อง ล้วนช่วยผลักดันประสิทธิภาพให้ดีขึ้นอย่างสม่ำเสมอ
- ด้วย การพัฒนาร่วมกันของฮาร์ดแวร์และซอฟต์แวร์ ทำให้บรรลุความเร็วแยกวิเคราะห์ 21 GB/s ซึ่งดีขึ้นราว 3 เท่าในเวลาเฉลี่ย 2 ปี
- เพียงการเปลี่ยนรุ่นฮาร์ดแวร์ (5950X→9950X, 4.9→5.7GHz) ก็เป็นเหตุผลรองรับการเพิ่มขึ้นมากกว่า 1.2x แล้ว
การสร้างโค้ด AVX-512 และปัญหา mask register
- Sep รองรับ AVX-512 มาตั้งแต่ 0.2.3 แต่มีข้อจำกัดในการใช้งาน mask register (k1-k8) ของ AVX-512
- ใน .NET 8 ยังไม่มีการรองรับ mask register โดยตรง ทำให้ต้องคัดลอกและแปลงข้อมูลซ้ำ ๆ ระหว่างรีจิสเตอร์ทั่วไป ซึ่งกลายเป็นปัจจัยที่ทำให้ประสิทธิภาพลดลง
- ในช่วงแรกที่ยังไม่มี CPU ที่รองรับ AVX-512 โดยเฉพาะ ผู้พัฒนาได้ทดสอบแบบจำกัดบน Xeon Silver 4316 และยืนยันว่าเร็วที่สุด
การอัปเกรดเป็น 9950X และการเปรียบเทียบ AVX-512 กับ AVX2
- เมื่อไม่นานมานี้มีการอัปเกรด CPU จาก Zen 3 (5950X) เป็น Zen 5 (9950X) และเมื่อรันเบนช์มาร์กของ Sep ก็ทำได้ถึง 18 GB/s
- ผลการทดลองเปรียบเทียบตัวแยกวิเคราะห์ AVX-512 กับ AVX2 โดยตรงพบว่า AVX2 ทำได้ ราว 20 GB/s และเร็วกว่า AVX-512 ประมาณ 10% อย่างน่าประหลาดใจเล็กน้อย
- สิ่งนี้ชี้ให้เห็นว่าความไม่มีประสิทธิภาพของ การจัดการ mask register ใน .NET JIT ยังคงเป็นปัญหาอยู่
โค้ดตัวแยกวิเคราะห์ การวิเคราะห์แอสเซมบลี และตัวแยกวิเคราะห์ AVX-512-to-256 แบบใหม่
- ตัวแยกวิเคราะห์ทั้งหมดของ Sep ประมวลผล char span ทีละ 16K และใช้การเปรียบเทียบที่อิงกับรีจิสเตอร์ SIMD (เช่น Vector256)
- ใช้ SIMD เพื่อตรวจจับอักขระพิเศษอย่างรวดเร็ว เช่น ตัวขึ้นบรรทัดใหม่ เครื่องหมายอัญประกาศ และตัวคั่น แล้วแปลงเป็น bitmask เพื่อให้การดำเนินการแบบเซ็ตมีประสิทธิภาพสูงขึ้น
- ตัวแยกวิเคราะห์ที่อิง AVX-512 มีโอเปอเรชันส่วนเกินจำนวนมาก เนื่องจากต้องย้ายข้อมูลซ้ำไปมาระหว่าง mask register (เช่น k1) กับรีจิสเตอร์ทั่วไป (เช่น zmm)
- ใน 0.10.0 มีการเลื่อนการเรียก MoveMask ให้เร็วขึ้น เพื่อลด การแปลง mask ที่ไม่จำเป็น และลดจำนวนคำสั่งแอสเซมบลี
- ตัวแยกวิเคราะห์ AVX2 ไม่มี mask register จึงมีโครงสร้างที่เรียบง่ายกว่ามาก และในทางปฏิบัติจึงเร็วกว่า AVX-512
- ตัวแยกวิเคราะห์ AVX-512-to-256 แบบใหม่อ่านข้อมูลด้วย AVX-512 แล้วใช้คำสั่งแปลงเป็น 256 บิตเพื่อหลบเลี่ยงปัญหาการจัดการ mask โดยตรง ทำให้การอิมพลีเมนต์กระชับขึ้นและทำความเร็วได้เกิน 21 GB/s
สรุปเบนช์มาร์กของตัวแยกวิเคราะห์หลายแบบ
- จากการเปรียบเทียบเบนช์มาร์กของตัวแยกวิเคราะห์ทุกประเภทผ่านตัวแปรสภาพแวดล้อม พบว่า ตัวแยกวิเคราะห์ AVX-512-to-256 เร็วที่สุดที่ 21.5 GB/s
- ตัวแยกวิเคราะห์ที่อิง AVX2 และ Vector256 ก็ทำผลงานใกล้เคียงกันมาก โดยต่างกันไม่เกิน 5%
- ตัวแยกวิเคราะห์ที่อิง Vector128 และ Vector512 ช้ากว่า AVX2 ราว 5~10% โดยเฉพาะ Vector512 ที่ช้ากว่า Vector128 เสียอีก
- ตัวแยกวิเคราะห์ IndexOfAny ช้ากว่าตัวแยกวิเคราะห์ SIMD อื่นอย่างเห็นได้ชัด ส่วน Vector64 ไม่มีการเร่งความเร็วบน 9950X จึงให้ประสิทธิภาพต่ำมาก
- ตัวแยกวิเคราะห์ SIMD ที่อิง AVX-512 และ AVX2 พิสูจน์ให้เห็นถึงประสิทธิภาพที่เหนือกว่าตัวแยกวิเคราะห์ CSV ประเภทเดียวกันอย่างชัดเจน
เบนช์มาร์กระดับบน: เปรียบเทียบ 5950X กับ 9950X
- อ้างอิงจากข้อมูล 1 ล้านแถวของ package asset, Sep_MT ทำเวลาได้ 72ms (8GB/s) บน 9950X และ 119ms (4.9GB/s) บน 5950X
- แม้กับข้อมูลโหลดจริง (เช่น float) ก็ยังทำแบนด์วิดท์แบบมัลติเธรดได้ ~8GB/s บน 9950X
- การเปลี่ยนผ่านรุ่น (5950X→9950X) ให้ผลการปรับปรุงราว 1.5~1.6 เท่าในงานแยกวิเคราะห์จริง
- เมื่อเทียบกับไลบรารี CSV คู่แข่ง (Sylvan, ReadLine, CsvHelper เป็นต้น) ก็พิสูจน์ได้ว่ามี throughput สูงกว่ามากและมีการจัดสรรทรัพยากรต่ำมาก
บทสรุปและสรุปย่อ
- Sep 0.10.0 ก้าวข้ามข้อจำกัดของ ประสิทธิภาพการแยกวิเคราะห์ CSV ด้วยการผสาน การปรับแต่งซอฟต์แวร์ เข้ากับ ความสามารถของฮาร์ดแวร์รุ่นใหม่ (AVX-512, clock สูง)
- หัวใจของนวัตกรรมคือการออกแบบ อัลกอริทึม SIMD รุ่นใหม่, การปรับปรุงโค้ด .NET JIT และโครงสร้างแอสเซมบลี
- ผลของ การปรับปรุงประสิทธิภาพแบบสะสมและการเปลี่ยนรุ่นสถาปัตยกรรม ในช่วงเวลาสั้น ๆ นั้นน่าประทับใจ
- Sep นำเสนอ ประสิทธิภาพสูง รองรับหลายแพลตฟอร์ม และขยายต่อได้จริง ในงานแยกวิเคราะห์ CSV ในระดับชั้นนำของอุตสาหกรรม
1 ความคิดเห็น
ความเห็นจาก Hacker News
vpternlogdและvporเพื่อลดจำนวนการทำ orprotobufก็ไม่ได้เป็นฟอร์แมตที่ยากอะไรนัก แต่กลับไม่ค่อยมีการนำมาใช้