AMD 9950X पर SIMD के साथ CSV parsing में 21 GB/s हासिल
(nietras.com)- Sep 0.10.0 ने AMD 9950X (Zen 5) जैसे AVX-512 समर्थित CPU के लिए optimization के साथ low-level CSV parsing में 21 GB/s हासिल किया, जो पहले के लगभग 18 GB/s से तेज है
- performance improvement parser structure को बदलने से आया, ताकि .NET 9.0 के AVX-512 code generation में होने वाली mask register round-trip bottleneck कम हो सके
- नया AVX-512-to-256 parser 512-bit में
charलोड करने के बाद उसे 256-bit byte vector में बदलता है, जिससे mask handling और अलग permutation cost से बचा जाता है - Sep की low-level parsing performance 2023 के 0.1.0 में 5950X/.NET 7.0 पर लगभग 7 GB/s से बढ़कर 0.10.0 में 9950X/.NET 9.0 पर लगभग 21 GB/s हो गई, यानी लगभग 3 गुना सुधार
- higher-level benchmark में भी 9950X multi-threaded Sep ने package assets की 10 लाख rows को 72.213ms, लगभग 8.0 GB/s पर process किया, और floats data में भी लगभग 8.1 GB/s दर्ज किया
Sep 0.10.0 का लक्ष्य और नतीजे
- Sep 0.10.0 22 अप्रैल 2025 को रिलीज़ हुआ, और इसमें AMD 9950X (Zen 5) जैसे AVX-512 समर्थित CPU के लिए optimization और 9950X benchmarks शामिल हैं
- low-level CSV parsing के आधार पर Sep ने 9950X पर 21 GB/s हासिल किया
- 0.10.0 से पहले उसी 9950X पर यह लगभग 18 GB/s था
- analysis का दायरा package assets CSV data की low-level
Rowsparsing तक सीमित है, और सभी आँकड़े single-thread आधार पर हैं - benchmark numbers कुछ percentage points तक बदल सकते हैं, इसलिए किसी खास release में छोटे regression दिख सकते हैं
0.1.0 से 0.10.0 तक performance में बदलाव
- Sep की performance code changes, .NET version changes और CPU generation changes के संयुक्त असर से धीरे-धीरे बेहतर हुई
- representative performance flow इस प्रकार है
- 0.1.0, 5950X, .NET 7.0: लगभग 7 GB/s
- 0.3.0, 5950X, .NET 8.0: लगभग 12 GB/s
- 0.6.0, 5950X, .NET 9.0: लगभग 13 GB/s
- 0.9.0, 9950X, .NET 9.0: लगभग 18 GB/s
- 0.10.0, 9950X, .NET 9.0: लगभग 21 GB/s
- जून 2023 में Sep के सार्वजनिक होने के बाद लगभग 2 साल से थोड़ा कम समय में यह लगभग 3 गुना तेज हुआ
- 5950X पर Sep 0.9.0 और 9950X पर Sep 0.10.0 की तुलना करें तो लगभग 1.6 गुना सुधार दिखता है
- 9950X की boost clock 5.7GHz है, जबकि 5950X की 4.9GHz है
- माना गया है कि सिर्फ इस clock difference से लगभग 1.2 गुना तक की व्याख्या हो सकती है
.NET AVX-512 code generation में mask register bottleneck
- Sep ने 0.2.3 से AVX-512 support दिया था, लेकिन उस समय .NET 8 में AVX-512 के
k1-k8mask registers का explicit support नहीं था - पुराने AVX-512 code generation में comparison result पहले mask register में जाता था, फिर general register में ले जाया जाता था, और फिर वापस mask register में लौटता था
- 9950X पर upgrade के बाद Sep 0.9.0 ने low-level CSV parsing में लगभग 18 GB/s दर्ज किया, जो 5950X की तुलना में लगभग 1.4 गुना तेज था
- environment variable से parser बदलकर तुलना करने पर 9950X पर AVX2 parser ने लगभग 20 GB/s दर्ज किया, जो पुराने AVX-512 parser से लगभग 10% तेज था
- इस अंतर से पुष्टि हुई कि AVX-512 mask register handling अभी भी performance को प्रभावित कर रही थी
Sep parsing loop की बुनियादी संरचना
- Sep के सभी parsers एक ही मूल संरचना का पालन करते हैं, और एक
Parsegeneric method के जरिए quote handling के हिसाब से दो paths को support करते हैंParseColInfos: quote handling होने पर उपयोग होता है और इसमें अधिक state tracking चाहिएParseColEnds: quote handling न होने पर उपयोग होता है
- parsing array से लाए गए
charspan units पर होती है, और उदाहरण आकार 16K है- यह आकार इतना छोटा है कि CPU cache में समा सके, और बाद में efficient multithreading के लिए भी फायदेमंद है
- loop SIMD registers में 16-bit character data लोड करता है, उसे byte SIMD registers में बदलता है, और फिर CSV special characters से तुलना करता है
- comparison targets में
\n,\r,",;आदि शामिल हैं
- comparison targets में
- comparison results को bitmask में बदला जाता है, और mask में set bits को ही क्रम से parse किया जाता है
- performance difference काफी हद तक इस बात पर निर्भर करता है कि यह SIMD C# code .NET में किस machine code में JIT compile होता है
पुराना AVX-512 parser और 0.10.0 के बदलाव
- 0.9.0 का
SepParserAvx512PackCmpOrMoveMaskTzcntदो 512-bit SIMD registers में 32-32charलोड करता है, उन्हें एक 512-bit byte vector में pack करता है, और हर loop में 64 characters process करता है - packed data का क्रम गड़बड़ होता है, इसलिए
PermuteVar8x64से उसे फिर से reorder करना पड़ता है - .NET 9.0 assembly में हर
Vec.Equalsके बादvpcmpeqbऔरvpmovm2bदो instructions आती थीं, औरk1जैसे mask registers तथाzmmgeneral vector registers के बीच movement बार-बार होता था - Sep 0.10.0 में
MoveMaskcalls को और पहले खिसकाया गया, ताकि mask registers और general registers के बीच round-trip count कम हो सके- दूसरे parsers में “special character नहीं है” वाले fast path में instruction count घटाने के लिए
MoveMaskसिर्फ जरूरत पड़ने पर ही call किया जाता है
- दूसरे parsers में “special character नहीं है” वाले fast path में instruction count घटाने के लिए
- बदलाव के बाद भी mask register से general register में movement बना रहता है, लेकिन कुल assembly instruction count घट जाता है
AVX2 और नया AVX-512-to-256 parser
- AVX2 आधारित
SepParserAvx2PackCmpOrMoveMaskTzcntकी assembly में mask registers नहीं होते, इसलिए इसकी संरचना अधिक सीधी है - इसी वजह से AVX2 parser पुरानी 0.9.0 AVX-512 parser implementation से तेज था
- 0.10.0 का नया
SepParserAvx512To256CmpOrMoveMaskTzcntAVX-512 instructions सेcharलोड करता है औरConvertToVector256ByteWithSaturationसे 256-bit byte vector बनाता है- वास्तविक instruction
vpmovuswbहै - हर loop में throughput “सिर्फ” 32
charका है, लेकिन संरचना अधिक सरल है
- वास्तविक instruction
- यह तरीका 512-bit mask register समस्या से बचता है, और packed data पहले से सही क्रम में
ymm4में होने के कारण अलग permutation की भी जरूरत नहीं पड़ती - नए parser ने 9950X पर Sep parsing performance को लगभग 21 GB/s तक पहुँचा दिया
parser-वार 9950X low-level benchmarks
- AMD 9950X पर environment variable से सभी parsers चलाकर तुलना करने पर नया AVX-512-to-256 parser सबसे तेज निकला
- मुख्य नतीजे इस प्रकार हैं
SepParserAvx512To256CmpOrMoveMaskTzcnt: 21597.7 MB/s, 27.0 ns/row, 1.351msSepParserVector256NrwCmpExtMsbTzcnt: 20608.5 MB/s, 28.3 ns/row, 1.416msSepParserAvx2PackCmpOrMoveMaskTzcnt: 20599.3 MB/s, 28.3 ns/row, 1.417msSepParserAvx512PackCmpOrMoveMaskTzcnt: 19944.3 MB/s, 29.3 ns/row, 1.463ms
Vector256आधारित cross-platform parser लगभग AVX2 के बराबर पहुँच गयाVector128औरVector512आधारित cross-platform parsers अभी भी तेज थे, लेकिन 5~10% धीमे रहे, औरVector512,Vector128से भी धीमा थाSepParserIndexOfAny2787.0 MB/s पर काफी पीछे रहा, औरVector64को 9950X पर acceleration नहीं मिला, इसलिए यह 459.9 MB/s पर ही रहा
5950X और 9950X के higher-level benchmarks
- package assets data में 10 लाख rows process करने के नतीजों में 9950X, 5950X से काफी तेज था
- 5950X
Sep_MT: 119.430ms, 4888.1 MB/s - 9950X
Sep_MT: 72.213ms, 8084.1 MB/s
- 5950X
- 9950X पर single-thread
Sepने package assets की 10 लाख rows को 291.979ms, 1999.4 MB/s पर process किया - उसी 9950X package assets benchmark में comparison targets की performance इस प्रकार रही
Sylvan: 413.265ms, 1412.6 MB/sReadLine_: 377.033ms, 1548.4 MB/s, allocation 1991.04MBCsvHelper: 1005.323ms, 580.7 MB/s
- floats data में भी 9950X का multi-threaded Sep 25,000 rows को 2.497ms, 8136.8 MB/s पर process करता है
- 5950X से 9950X पर higher-level benchmark improvement भी low-level benchmark की तरह लगभग 1.5~1.6 गुना है
अभी कोई टिप्पणी नहीं है.