1P by GN⁺ 1일전 | ★ favorite | 댓글 1개
  • 최신 Sep 0.10.0 버전은 AMD 9950X에서 21 GB/s의 놀라운 CSV 파싱 속도를 달성함
  • AVX-512 지원 및 마스크 레지스터 이슈 극복으로 성능이 크게 향상됨
  • 새로운 AVX-512-to-256 파서가 AVX2, 기존 AVX-512 파서를 앞지르는 결과를 보임
  • 멀티스레드 환경에서 1백만 행을 72ms에 처리하며 8 GB/s 대역폭을 기록함
  • 지속적 소프트웨어 및 하드웨어 최적화로 2년 만에 약 3배의 성능 개선을 이룸

Sep 0.10.0 릴리즈와 성능 향상 개요

  • Sep는 최근 0.10.0 릴리즈에서 AVX-512 지원 CPU(예: AMD 9950X, Zen 5)에 대한 최적화를 진행했고, 벤치마크 결과가 업데이트됨
  • 최신 버전에서 낮은 수준의 CSV 파싱에서 21 GB/s라는 대단한 성과를 기록함
  • 이전 버전과 비교해 18 GB/s에서 상당한 성능이 상승된 결과임
  • 개선 내역은 Sep의 GitHub 릴리즈와 README에서 상세히 볼 수 있음
  • 본문에서는 .NET 9.0의 AVX-512 머신 코드의 비효율을 극복한 SIMD 기반 C# 코드와 x64 SIMD 어셈블리를 통한 성능 향상 과정을 설명함

Sep의 성능 발전 과정

  • Sep의 초기 0.1.0부터 0.10.0, .NET 7.0에서 9.0, AMD 5950X(Zen 3) 에서 9950X(Zen 5) 로의 발전이 시각적으로 표현됨
  • 벤치마크는 단일 스레드 기준으로, 각 릴리즈별 약간의 변동이 있을 수 있음
  • 핵심 메시지는 대규모 리팩터링(0.2.0 내장 구조 재작성)이나 작은 변경이 누적된 최적화가 꾸준히 성능 개선을 이끈 점임
  • 하드웨어와 소프트웨어 동반 발전으로 평균 2년 만에 약 3배 향상된 21 GB/s 파싱 속도를 달성함
  • 하드웨어 세대 간(5950X→9950X, 4.9→5.7GHz) 변화만으로도 1.2x 이상의 향상의 근거임

AVX-512 코드 생성과 마스크 레지스터 문제

  • Sep는 0.2.3부터 AVX-512를 지원해왔으며, AVX-512의 마스크 레지스터(k1-k8) 활용에 한계가 있었음
  • .NET 8에서는 마스크 레지스터에 대한 직접적인 지원이 없어, 정상 레지스터 간의 반복 복사 및 변환이 성능 저하 요인이었음
  • 별도의 AVX-512 지원 CPU가 없었던 초기에는 Xeon Silver 4316에서 제한적으로 테스트해 가장 빠름을 확인함

9950X 업그레이드 및 AVX-512 vs AVX2 비교

  • 최근 Zen 3(5950X)에서 Zen 5(9950X) 로 CPU를 업그레이드하면서, Sep의 벤치마크를 수행한 결과 18 GB/s에 도달함
  • AVX-512와 AVX2 파서를 직접 비교 실험한 결과, 약간 의외로 AVX2가 약 20 GB/s로 AVX-512보다 약 10% 빠름을 보여줌
  • 이는 .NET JIT의 마스크 레지스터 처리 비효율이 여전히 문제임을 시사함

파서 코드, 어셈블리 분석 및 새로운 AVX-512-to-256 파서

  • Sep의 모든 파서는 16K 단위의 char span을 처리하며 SIMD 레지스터(Vector256 등) 기반의 비교 연산을 활용함
  • SIMD로 특수 문자(개행, 따옴표, 구분자 등)를 빠르게 판별하고 비트마스크로 변환하여 집합 연산 최적화를 실현함
  • AVX-512 기반 파서는 마스크 레지스터(k1 등)와 일반 레지스터(zmm 등) 간 반복 이동으로 인해 잉여 연산이 많았음
  • 0.10.0에서는 MoveMask 호출을 앞당겨 불필요한 마스크 변환 최소화로 어셈블리 명령 수를 줄임
  • AVX2 파서는 마스크 레지스터가 없어서 구조가 훨씬 단순, AVX-512보다 실질적으로 빨랐음
  • 새로운 AVX-512-to-256 파서는 AVX-512로 데이터를 읽고 256비트 전환 명령으로 마스크 처리 문제 자체를 우회, 구현이 간명해졌고, 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에서 가속되지 않아 매우 저조한 성능
  • AVX-512 및 AVX2 기반의 SIMD 파서가 동종 CSV 파서 대비 압도적인 성능을 입증함

상위 벤치마크: 5950X와 9950X 비교

  • 1백만 패키지 자산 행 기준으로 Sep_MT는 9950X에서 72ms(8GB/s), 5950X에서 119ms(4.9GB/s)를 기록함
  • 실부하 데이터(float 등)에서도 9950X에서 멀티스레드로 ~8GB/s 대역폭을 달성함
  • 세대 변화(5950X→9950X)로 실제 응용 파싱에서 약 1.5~1.6배의 개선 효과가 나타남
  • 경쟁 CSV 라이브러리(Sylvan, ReadLine, CsvHelper 등) 대비 현격한 처리량, 최소 자원 할당량을 입증함

결론 및 요약

  • Sep 0.10.0은 소프트웨어 최적화최신 하드웨어 기능(AVX-512, 높은 클럭) 의 결합으로 CSV 파싱 성능 한계를 극복함
  • 최신 SIMD 알고리듬 설계, .NET JIT 코드 및 어셈블리 구조 개선이 혁신의 핵심임
  • 짧은 시간 내 누적 성능 개선과 아키텍처 세대 변화의 효과가 인상적임
  • Sep는 CSV 파싱 영역에서 실질적으로 업계 최고 수준의 고성능, 멀티플랫폼, 확장성을 제시함
Hacker News 의견
  • 인텔이 소비자용 제품에서 AVX-512 지원을 위해 칩 면적까지 수년 동안 투자함에도 불구하고, 이제 라이브러리들이 점점 더 이를 사용하기 시작한 시점에 오히려 AVX-512를 소비자 SKU에서 제거한 상황이 매우 어이없음, AMD가 AVX-512 지원이 더 좋다는 것도 아니고, 단지 인텔이 투자했던 것을 스스로 포기했기 때문에 AMD의 소비자 CPU엔 AVX-512가 들어가게 된 아이러니한 흐름임
    • 인텔은 항상 기술 시장을 구축하고(Optane), 또 갑작스러운 철수(Depth Cameras)로 소비자를 혼란에 빠뜨리는 패턴 반복 중임, 새로운 기술에 한 번에 몰아넣고 uptake 없으면 바로 관둠, Optane 지원이 리눅스 커널에서 이제 성숙해지려 할 때 중단, 이상한 비용절감 전략도 있음, 역사를 거슬러 올라가면 Intel iAPX 432 때부터 같은 실수를 반복하고 있음
    • 이번 기사에서는 AMD CPU로 오리지널: 18GB/s, AVX2: 20GB/s, AVX512: 21GB/s 속도를 확인함, AVX-512가 AVX2 대비 이점이 거의 없음, 인텔 소비자 CPU는 E-코어에서도 AVX2 지원, 벤치마크는 싱글스레드, 인텔은 더 많은 코어를 위해 칩에서 AVX-512를 뺐고 그 결과 최상급은 24코어, AMD는 16코어임, AVX2→AVX512 차이가 미미하므로 멀티스레드에서는 코어 수가 더 많은 쪽이 이길 수 있음, 실제 워크로드 대다수에선 AVX-512 대신 코어 수 증가 쪽 이점이 큼, 일부 아주 특정 작업 제외하면 인텔의 결정이 합리적이었다고 봄
    • 곧 AVX-10이 등장 예정이며, AVX-512와 거의 비슷한 기능을 가질 예정임(차이가 뭔진 나도 모르겠음)
    • 이번 기사에서 가장 흥미로웠던 점은, AMD 9950X에서 AVX2 파서가 AVX-512 기반 파서보다 약 10% 빨랐다는 부분임(20GB/s 대 21GB/s), 결국 AVX-512가 실제 소비자에겐 큰 도움이 아닌 것으로 보임, CSV 파싱 20GB/s만 되어도 불만 없음, 어셈블리 매니아만이 지원 여부에 민감함
    • 인텔이 멍청하게 굴고 있는 게 정말 황당함
    • 위로가 된다면, Sep는 가능할 때마다 별도 설정 없이도 AVX-512를 사용함, JIT 런타임에서 잘 돌아가서 본의 아니게 최저 성능 기준을 타겟팅해도 손해볼 일 없음
    • 인텔은 소프트웨어 지원도 별로임, 내 노트북 iGPU도 꽤 괜찮지만 PyTorch 등에서 제대로 지원 안 돼서 아쉬움, llama.cpp와 Vulkan 추론은 잘 돼서 다른 소프트웨어도 이런 식 지원 해줬으면 하는 바람임
  • 각 문자별로 네 번의 비교(‘\n’, ‘\r’, ‘;’, ‘“’) 후 세 번의 or 연산을 하지 않고, 흔한 트릭으로 셔플 1회, 비교 1회, or 연산 0회를 할 수 있음, 이 트릭을 블로그로 소개했으니 참고, 그나저나 이 기사에서도 ‘vpternlogd’와 ‘vpor’ 연산으로 or 연산을 줄였음
  • 인텔이 소비자용 CPU에서 느린 코어 넣어야 한다거나, ‘멀티펌핑’ 고려도 없이 AVX-512 다 빼버리는 결정은 꼴불견임
    • 이 선택의 주요 원인은 10nm 공정 문제 때문임, 불량률 높고 비용이 너무 비싸니까 칩 최대한 잘라서 Atom 계열 코어/저전력 마케팅으로 수익 뽑으려 노력함, 고가 제품은 크기 키우고 마진 줄여서 서버/클라우드 시장 지키려 함, 수익성은 결국 떨어졌고 점유율도 잃었지만 어쨌든 해보려고 하긴 했음
  • Sep 출시(2023년 6월) 이후 2년 만에 약 3배의 속도 향상을 기록했다는 주장은 하드웨어 점프도 감안하면 논란 있음
    • 동일 하드웨어에서 소프트웨어(0.9.0과 0.10.0) 향상폭은 17%고, 0.9.0의 13088에 17% 더하면 15375, 0.1.0의 7335와 비교하면 약 2.1배 향상임
    • 동일 하드웨어 상에서 sep의 이전 버전 대비 3GB/s 향상이라 주장, 실제 속도와 하드웨어 정보도 투명하게 기재되어 있음
    • 요즘은 무어의 법칙 같은 시대도 지났기 때문에 하드웨어만으로 3x 속도 향상 기대하기 어렵고, 이 정도라도 현대엔 충분히 인상적인 성과라고 생각함
    • 분명히 하드웨어 점프 고려 없이 3배 향상이라 주장하는 건 논쟁의 여지 있지만, 그래도 연도별 소프트웨어 실성능을 보는 하나의 관점으로 흥미로움
    • 벤치마크 차트가 CPU 세대를 4개나 건너뛰고 갑자기 ‘대성능 향상’처럼 보이게 해서 신뢰성 없음
  • Arthur Whitney가 이 결과에 자극받아 1줄 코드로 이를 뛰어넘거나, shakti 엔진 업데이트와 함께 1줄로 기록 깨는 모습 혹은 뉴스 업데이트를 기대함, 발전을 기대함
  • 누가 천만 라인의 CSV를 이 속도로 처리해야 하는지 생각만 해도 아찔함
    • 나 또한 그런 경험 있음, 초반엔 작은 데이터 양에 맞춰 CSV 선택, 비개발자-특히 Excel 잘 다루는 사람들이 읽기 쉬워서 로그/프로세스도 CSV로 깔끔하게 처리, 그런데 데이터가 10배 100배로 불어나게 되면 억단이 넘는 CSV를 최적화해서 빠르게 ingest하는 게 실질적인 필요가 됨, 이런 최적화로 내부 프로세스를 점점 더 적합한 포맷으로 이전할 시간을 버는 셈임
    • CSV는 내부에서도 생각보다 흔하게 쓰이는 포맷이고 압축(디플레이트)도 쉽다는 장점 있음, 예전에 CSV가 NIC 카드 속도로 Netflow 데이터를 쏟아내던 코드를 다뤄본 적 있음, 개인적으로 그렇게 복잡한 처리를 할거면 차라리 프로토콜 버퍼 쓰면 좋겠다고 생각함, protobuf가 그리 어려운 포맷도 아닌데 도입이 잘 안됨
    • 21GB/s 수준 CSV를 처리한 결과물을 저장한다는 의미가 더 무섭게 느껴짐, 아무리 유용한 집계라도 이 정도 속도라면 결국 어딘가에는 쌓여야 할 텐데 궁금증 생김
    • 많은 단점에도 불구하고 아직까지 CSV가 가장 흔한 데이터 교환 포맷이라고 생각함
    • 금융권에서는 CSV는 다들 공유 가능하고, 텍스트 기반이라 아무 데나 집어넣고 처리 가능함
    • 회계 부서에서 연말에 보내주는 cartesian product 파일을 예로 들 수 있음
    • 실제로 이런 오래된 방식의 CSV를 다뤄야 해서 고생하는 처지임
    • 거의 모든 경우 HDF5가 CSV보다 좋음, 그럼에도 그냥 무지, 게으름, 또는 '잘 되니까'란 이유 밖에 설명이 어려움
  • 어셈블리 코드를 기대하고 들어왔는데 C#이라서 놀랍고 인상적임, 멋진 결과임
    • 최신 .NET은 SIMD와 벡터 인트린직스를 가장 깊게 통합한 ‘고급 언어’임, Microsoft의 Tanner Gooding이 많은 발전을 이끌었고, 관련 블로그 글도 훌륭함
  • 본문에서 21GB/s 코드가 정확히 뭘 하는지 명확히 정의되어 있지 않다는 점이 혼란스러움, 예를 들어 파싱 포맷이 구체적으로 뭐고(예: CSV에서 쿼터 처리 등), 파싱 후 어떻게 결과를 사용하는지(데이터 구조에 넣는지 등) 불분명함
    • 기사 내 계산된 ns/row가 약 27ns/row(초당 37,000 row 정도)인데, 만약 21GB/s라면 row 당 570KB 수준이니까 너무 비정상적인 벤치마크 같음
  • 내 경험상 커스텀 SIMD 코드로 현대 컴파일러의 자동 벡터화 대비 큰 이득 얻기 어려웠음(특히 벡터 친화적인 코드에선), 다만 JSON 파싱처럼 특이한 경우는 좀 다름
  • 최근 300GB CSV 추출본을 작업했는데, 조작과 무결성 검증 등에 너무 많은 시간이 소요되어 이런 빠른 CSV 파서가 절실히 필요함
    • 왜 부동소숫점 데이터 저장에 특화된 포맷을 안 쓰는지 이해 불가, HDF5가 훨씬 좋은 대안임