- Phiên bản mới nhất Sep 0.10.0 đạt tốc độ phân tích cú pháp CSV ấn tượng 21 GB/s trên AMD 9950X
- Hiệu năng được cải thiện đáng kể nhờ hỗ trợ AVX-512 và khắc phục vấn đề thanh ghi mask
- Trình phân tích AVX-512-to-256 mới cho kết quả vượt qua AVX2 và trình phân tích AVX-512 trước đây
- Trong môi trường đa luồng, xử lý 1 triệu dòng trong 72ms và ghi nhận băng thông 8 GB/s
- Nhờ tối ưu hóa phần mềm và phần cứng liên tục, hiệu năng đã cải thiện gần 3 lần sau 2 năm
Tổng quan về bản phát hành Sep 0.10.0 và cải thiện hiệu năng
- Trong bản phát hành 0.10.0 gần đây, Sep đã tối ưu cho các CPU hỗ trợ AVX-512 (ví dụ: AMD 9950X, Zen 5) và cập nhật kết quả benchmark
- Ở phiên bản mới nhất, công cụ ghi nhận thành tích ấn tượng 21 GB/s trong phân tích cú pháp CSV cấp thấp
- So với phiên bản trước, đây là mức tăng đáng kể từ 18 GB/s
- Có thể xem chi tiết các thay đổi trong GitHub release và README của Sep
- Bài viết giải thích quá trình cải thiện hiệu năng bằng mã C# dựa trên SIMD và assembly SIMD x64 để vượt qua sự kém hiệu quả của mã máy AVX-512 trong .NET 9.0
Quá trình phát triển hiệu năng của Sep
- Sự tiến hóa của Sep từ 0.1.0 ban đầu đến 0.10.0, từ .NET 7.0 lên 9.0, và từ AMD 5950X (Zen 3) sang 9950X (Zen 5) được thể hiện trực quan
- Benchmark được đo theo đơn luồng và có thể có dao động nhỏ giữa các bản phát hành
- Thông điệp cốt lõi là cả những lần refactor lớn (viết lại cấu trúc nội bộ ở 0.2.0) lẫn các thay đổi nhỏ tích lũy đều liên tục thúc đẩy cải thiện hiệu năng
- Nhờ sự phát triển song hành của phần cứng và phần mềm, tốc độ phân tích đạt 21 GB/s, tương đương mức cải thiện gần 3 lần trong khoảng 2 năm
- Chỉ riêng thay đổi giữa các thế hệ phần cứng (5950X→9950X, 4.9→5.7GHz) cũng đã là cơ sở cho mức cải thiện hơn 1.2x
Sinh mã AVX-512 và vấn đề thanh ghi mask
- Sep đã hỗ trợ AVX-512 từ phiên bản 0.2.3, nhưng gặp giới hạn trong việc tận dụng các thanh ghi mask (k1-k8) của AVX-512
- Trong .NET 8, chưa có hỗ trợ trực tiếp cho thanh ghi mask, nên việc sao chép và chuyển đổi lặp đi lặp lại giữa các thanh ghi thông thường làm giảm hiệu năng
- Ở giai đoạn đầu khi chưa có CPU hỗ trợ AVX-512 riêng, tác giả chỉ có thể thử nghiệm hạn chế trên Xeon Silver 4316 và xác nhận nó là nhanh nhất
Nâng cấp lên 9950X và so sánh AVX-512 với AVX2
- Gần đây, sau khi nâng cấp CPU từ Zen 3 (5950X) lên Zen 5 (9950X), benchmark của Sep đã đạt 18 GB/s
- Khi so sánh trực tiếp trình phân tích AVX-512 và AVX2, kết quả hơi bất ngờ là AVX2 đạt khoảng 20 GB/s, nhanh hơn AVX-512 khoảng 10%
- Điều này cho thấy sự kém hiệu quả trong xử lý thanh ghi mask của JIT .NET vẫn là một vấn đề
Mã parser, phân tích assembly và trình phân tích AVX-512-to-256 mới
- Tất cả parser của Sep đều xử lý char span theo khối 16K và sử dụng các phép so sánh dựa trên thanh ghi SIMD (như Vector256)
- SIMD được dùng để nhanh chóng xác định các ký tự đặc biệt (xuống dòng, dấu ngoặc kép, dấu phân cách, v.v.) rồi chuyển thành bitmask để tối ưu các phép toán tập hợp
- Parser dựa trên AVX-512 có nhiều phép toán dư thừa do phải di chuyển lặp lại giữa thanh ghi mask (k1, v.v.) và thanh ghi thông thường (zmm, v.v.)
- Trong 0.10.0, lời gọi MoveMask được đưa lên sớm hơn để giảm tối đa việc chuyển đổi mask không cần thiết, từ đó giảm số lượng lệnh assembly
- Parser AVX2 không có thanh ghi mask nên cấu trúc đơn giản hơn nhiều, và trên thực tế nhanh hơn AVX-512
- Trình phân tích AVX-512-to-256 mới đọc dữ liệu bằng AVX-512 rồi dùng lệnh chuyển đổi 256-bit để né hẳn vấn đề xử lý mask, giúp cách triển khai gọn hơn và đạt hiệu năng trên 21 GB/s
Tổng hợp benchmark của nhiều loại parser
- Khi dùng biến môi trường để so sánh benchmark của mọi loại parser, parser AVX-512-to-256 là nhanh nhất với 21.5 GB/s
- Các parser dựa trên AVX2 và Vector256 cũng cho hiệu năng rất sát, chỉ chênh trong khoảng 5%
- Các parser Vector128 và Vector512 chậm hơn AVX2 từ 5~10%; đặc biệt parser Vector512 còn chậm hơn cả Vector128
- Parser IndexOfAny chậm hơn rõ rệt so với các parser SIMD khác. Vector64 không được tăng tốc trên 9950X nên hiệu năng rất thấp
- Các parser SIMD dựa trên AVX-512 và AVX2 chứng minh hiệu năng áp đảo so với các parser CSV cùng loại
Benchmark cấp cao hơn: so sánh 5950X và 9950X
- Với dữ liệu 1 triệu dòng tài sản package, Sep_MT ghi nhận 72ms (8GB/s) trên 9950X và 119ms (4.9GB/s) trên 5950X
- Ngay cả với dữ liệu tải thực tế (như float), hệ thống vẫn đạt băng thông ~8GB/s trên 9950X trong chế độ đa luồng
- Sự thay đổi thế hệ (5950X→9950X) mang lại mức cải thiện khoảng 1.5~1.6 lần trong các tác vụ phân tích cú pháp ứng dụng thực tế
- So với các thư viện CSV cạnh tranh (Sylvan, ReadLine, CsvHelper, v.v.), Sep cho thấy thông lượng vượt trội và mức cấp phát tài nguyên tối thiểu
Kết luận và tóm tắt
- Sep 0.10.0 vượt qua giới hạn hiệu năng phân tích cú pháp CSV nhờ sự kết hợp giữa tối ưu hóa phần mềm và tính năng phần cứng hiện đại (AVX-512, xung nhịp cao)
- Thiết kế thuật toán SIMD hiện đại cùng các cải tiến trong mã JIT .NET và cấu trúc assembly là trọng tâm của bước tiến này
- Hiệu quả của cải thiện hiệu năng tích lũy trong thời gian ngắn cùng với thay đổi thế hệ kiến trúc là rất ấn tượng
- Sep đang cho thấy một chuẩn mực thực tế hàng đầu ngành về hiệu năng cao, đa nền tảng và khả năng mở rộng trong lĩnh vực phân tích cú pháp CSV
1 bình luận
Ý kiến Hacker News
'\n','\r',';','“') rồi ba phép or, có thể dùng một mẹo phổ biến để chỉ cần 1 lần shuffle, 1 lần so sánh và 0 phép or; tôi đã viết một bài blog giới thiệu mẹo này nên có thể tham khảo; mà ngay trong bài này họ cũng đã giảm số phép or bằngvpternlogdvàvpor