1P by GN⁺ 5시간전 | ★ favorite | 댓글 1개
  • C++/CUDA 기반 LLM 추론 엔진으로, GPU 메모리 스트리밍과 NVMe 직접 입출력을 통해 Llama 70B 모델을 RTX 3090(24GB VRAM) 에서 실행 가능
  • 3단계 적응형 캐싱 구조를 사용해 VRAM, 고정 RAM, NVMe/mmap을 자동 분할하며, mmap 대비 최대 83배 속도 향상 달성
  • gpu-nvme-direct 백엔드는 CPU를 완전히 우회해 NVMe에서 GPU로 직접 데이터를 전송, PCIe 대역폭을 최대한 활용
  • Layer skipself-speculative decoding 기능으로 불필요한 연산을 줄이고, 품질 손실 없이 처리 속도를 높임
  • 소비자용 하드웨어에서 초대형 모델을 효율적으로 구동할 수 있게 해, 고성능 LLM 추론의 접근성 확대 가능성 제시

NTransformer 개요

  • 고효율 C++/CUDA LLM 추론 엔진으로, RTX 3090(24GB VRAM)에서 Llama 70B 모델을 실행
    • GPU 메모리를 통해 모델 레이어를 스트리밍하며, 선택적으로 NVMe 직접 I/O를 사용해 CPU를 완전히 우회
  • CUDA Toolkit 외 외부 의존성 없음, PyTorch나 cuBLAS 불필요
  • GGUF 모델 포맷을 지원하며, Q4_0, Q8_0, Q4_K_M, Q5_K, Q6_K, F16, F32 양자화 형식 사용 가능

성능 및 캐싱 구조

  • 3단계 적응형 캐싱(3-Tier Adaptive Caching)
    • VRAM 상주 레이어(0 I/O)
    • 고정 RAM(H2D 전송 전용)
    • NVMe/mmap 폴백
  • RTX 3090 + 48GB RAM 환경에서 mmap 대비 83배 속도 향상
  • PCIe Gen3 x8 대역폭(약 6.5 GB/s) 이 병목으로 작용
  • Q4_K_M 양자화는 VRAM에 10개 더 많은 레이어(36 vs 26)를 적재해 전송량 감소
  • Layer skip(코사인 유사도 기반)으로 80개 중 20개 레이어를 생략, 품질 손실 최소화

주요 기능

  • SLEP 스트리밍: NVMe 읽기, PCIe DMA, GPU 연산을 이중 버퍼로 중첩 처리
  • gpu-nvme-direct 백엔드: NVMe 데이터를 GPU 접근 가능한 고정 메모리로 직접 읽기
  • Self-speculative decoding: VRAM 상주 레이어를 초안 모델로 활용, 추가 모델 불필요
  • 자동 데이터 경로 선택: VRAM 상주 > 고정 RAM H2D > mmap 고정 > CPU memcpy
  • Llama 아키텍처 지원: RoPE, GQA, SwiGLU, RMSNorm, KV 캐시 포함

시스템 요구사항

  • Linux (Ubuntu, kernel 6.17+), CUDA Toolkit 13.1, gcc/g++ 14, CMake 3.24+
  • Compute Capability 8.0+ GPU (RTX 3090 테스트됨)
  • NVMe 직접 I/O 사용 시 별도 PCIe 슬롯의 NVMe SSD 및 gpu-nvme-direct 라이브러리 필요

NVMe 직접 스트리밍

  • 모델이 VRAM에 맞지 않을 경우, NVMe → GPU 직접 경로로 CPU를 완전히 배제
    • 데이터 흐름: NVMe SSD → DMA → 고정 스테이징 메모리 → PCIe H2D → GPU 버퍼 → 연산
  • NVMe를 VFIO에 바인딩해 사용자 공간에서 직접 접근
  • 각 레이어(70B Q6_K 기준 약 670MB)는 약 202ms 내 670개의 NVMe 명령으로 읽힘
  • NVMe 읽기, H2D DMA, GPU 연산이 이중 버퍼 파이프라인으로 병렬 처리

시스템 설정 및 위험 경고

  • 자동 설정 스크립트(setup_system.sh)가 GRUB, NVIDIA DKMS, CUDA 헤더, VFIO, NVMe 바인딩을 순차적으로 구성
  • IOMMU 비활성화, 커널 모듈 패치, NVMe VFIO 바인딩 등 고위험 작업 포함
  • 잘못된 설정 시 부팅 실패, NVMe 데이터 손실, 시스템 불안정 가능
  • 부트 드라이브는 절대 사용 금지, 별도 NVMe 전용 장치 필요
  • 모든 변경 사항은 백업 및 복원 스크립트 제공

아키텍처 및 코드 구조

  • src/ 디렉터리 내 주요 구성
    • core/: 텐서, 메모리 할당, GPU 장치 관리
    • cuda/: GEMV, RMSNorm, RoPE, SwiGLU, softmax 커널
    • memory/: NVMe 및 mmap 기반 SLEP 스트리밍 엔진
    • model/: Transformer 구성, GGUF 로더, attention, FFN, normalization
    • inference/: 토크나이저, 샘플러, 엔진
  • scripts/: 시스템 설정, NVMe 바인딩 및 복원 스크립트 포함

개발 단계 로드맵

  • 1단계: Llama 8B Q8_0, 커스텀 CUDA 커널, 48.9 tok/s (완료)
  • 2단계: SLEP 스트리밍, 단일 GPU에서 70B 실행, 33배 속도 향상 (완료)
  • 3단계: Q4_K_M/Q5_K 지원, Layer skip, self-speculative decoding, F16 KV 캐시 (완료)
  • 4단계: NVMe Direct 백엔드, GPU 주도 NVMe 읽기 3.35 GB/s (완료)
  • 5단계: 추론 최적화 및 공개 C API (예정)

라이선스

  • BSD-2-Clause 라이선스 적용
Hacker News 의견들
  • CPU를 우회해 NVMe에서 GPU로 직접 전송하는 방식이 정말 영리하다고 생각함
    로컬에서 대형 모델을 돌릴 때 병목은 항상 메모리 계층 구조였는데, 이건 NVMe를 확장된 VRAM처럼 DMA로 직접 다루는 셈임
    Apple M 시리즈의 통합 메모리(unified memory) 접근법과 비교하면 어떨지 궁금함. M4 Max는 70B 모델을 전부 메모리에 올릴 수 있지만 처리량은 3090보다 낮음
    NVMe 접근법을 쓴 3090과 M4 Max의 네이티브 성능을 배치 추론(batch inference) 기준으로 비교한 벤치마크가 있으면 흥미로울 것 같음

    • M3를 가지고 있어서 Metal에서 테스트해볼 예정임
  • GPUdirect를 이용하면 스토리지 장치로 직접 DMA 전송이 가능함
    만약 m.2 스토리지가 실제로 DRAM이라면 어떨까 생각해봄. GPU에서 모델을 스필링할 때는 지속성이 필요 없으니까, 시스템 RAM을 CPU용으로 남겨둘 수 있음

    • RAM디스크를 쓰면 훨씬 좋아질 듯함. Intel Optane이 표준이 되지 못한 게 아쉬움. 이런 워크플로우에 딱 맞는 기술이었음
    • 나도 같은 생각을 했음. 예전에 Dask Summit에서 dask-cudf 관련 발표를 했는데, 병렬 SSD 어레이 → GPUDirect Storage → PCIe → A100 GPU 구조로 로그 분석을 가속화했었음. 지금은 이런 구조를 LLM이나 MoE 모델에 적용하면 재밌을 것 같음
    • 사실 DRAM 기반 m.2 스토리지는 이미 CXL(Compute Express Link) 형태로 존재함. 다만 RAM 가격이 너무 비싸서 NVMe 커넥터당 31GB/s 대역폭을 활용하기 어렵다는 게 문제임
  • 초당 0.2 토큰 속도는 채팅에는 느리지만 배치/비동기 작업에는 충분함
    나는 자동 콘텐츠 생성 파이프라인을 돌리는데, 여러 LLM 호출을 동시에 실행함. 이미지 생성이 병목이라 전체 작업이 어차피 20분쯤 걸림
    70B 모델을 로컬에서 돌릴 수 있다면 API 토큰 비용을 아낄 수 있어서 큰 비용 절감이 될 것임

    • 비용 측면에서는 효율적이지 않음. 0.5 tok/s 기준으로 시간당 3600토큰인데, 3090 시스템이 200~300W를 소비함. 같은 양의 토큰을 OpenRouter에서 llama 3.1로 돌리면 전기요금보다 훨씬 저렴함. 그래도 프라이버시 추론 측면에서는 의미 있음
    • 3090을 350W로 장시간 돌릴 때의 전력비용도 고려해야 함
  • 0.2 tok/s는 실험용으로는 괜찮지만 인터랙티브하게 쓰기엔 부족함
    대부분의 경우, 잘 양자화된 8B나 13B 모델이 더 나은 지연시간-품질 균형을 제공함

    • 나도 단순히 가능성 테스트를 해보고 싶었음. 예전에 PS2에서 클래식 트랜스포머로 초당 3000토큰을 냈는데, 이는 메모리에서 GPU로 직접 명령을 보내는 구조 덕분이었음. 일반 PC는 CPU를 거쳐야 해서 느림. 프로용 GPU는 이런 문제를 해결하지만 너무 비쌈
    • 그래도 특정 상황에서는 대형 모델의 품질이 더 중요할 때가 있음
    • CPU+GPU 조합으로 돌리는 게 더 빠름. 나는 7950X+3090 조합에서 1.5 tok/s 정도 나옴
    • 성능표를 보고 나서야 상위 항목이 8B 모델임을 이해했음. 5초/토큰은 너무 느림. 내 5950X+128GB RAM 시스템이라면 CPU와 3060 GPU 조합으로 더 빠를 듯함. 3090에서 2초/토큰이 계산 한계라는 주장도 잘 납득되지 않음
  • 정말 흥미로운 실험임. 나도 이런 걸 먼저 해봤어야 했음
    PCIe 이론 대역폭 대비 실제 처리량(throughput) 수치가 궁금함. 이게 지연(latency) 문제인지, 대역폭 문제인지 알고 싶음

    • 실제로는 대역폭 병목임. 내 B450 메인보드가 PCIe3 x8만 지원해서 GPU가 제한됨. X570으로 업그레이드하면 속도가 2~3배는 빨라질 듯함
  • 멋진 해킹이지만, 70B 모델에서 0.5 tok/s는 같은 카드로 7B 모델이 30+ tok/s 나오는 것에 비하면 느림
    NVIDIA 연구에 따르면 10B 이하 모델로도 40~70%의 에이전트 작업을 처리할 수 있고, 품질 격차도 빠르게 줄고 있음

  • 이 분야는 앞으로 실험할 가치가 큼
    장기적으로는 모델 최적화, 즉 모델의 일부를 생략해도 성능에 영향이 없는 부분을 찾는 연구가 핵심이 될 것 같음. 결국 모델도 일종의 손실 압축(lossy compression) 구조이기 때문임. 이런 방향은 AI의 민주화에도 도움이 됨

    • 압축 비유가 흥미로움. 파인튜닝도 비슷하게 볼 수 있음. 예를 들어 3B 모델을 특정 작업에 맞게 튜닝하면, 70B 모델의 범용성이 필요 없게 됨
  • 정말 멋진 프로젝트임. 이런 아이디어를 떠올리려면 어떤 시스템/하드웨어 배경지식이 필요한지 궁금함
    나는 하드웨어가 많이 추상화된 환경에서 일해서, 이런 접근을 생각하기 어려움. 단순한 창의력뿐 아니라 시스템 수준의 이해가 있어야 가능할 듯함

    • 이게 바로 그 실험임: ps2-llm 프로젝트
      PS2에서 LLM을 돌리려다 RAM 32MB, VRAM 4MB 한계에 부딪혀 레이어 스트리밍 방식을 고안했음. PS2는 VRAM이 32비트 주소를 직접 처리할 수 있어서 속도가 매우 빨랐고, 그걸 PC에서도 재현해보려 했음
    • 나도 비슷하게 생각함. 예전 콘솔은 CPU가 느려서 DMA 전송이 핵심이었음. 아마 그 경험이 이런 아이디어로 이어졌을 것임. PS2의 스마트 메모리 카드도 DMA 기능이 꽤 복잡했음
  • 나도 비슷한 걸 시도 중임. VRAM 절반 이하로 1T 모델을 돌리는 실험을 하고 있음
    SGLang의 라우팅 레이어를 수정해 Gen5 NVMe에서 GPU 메모리로 JIT 예측 기반 expert swap을 구현할 수 있을 것 같음. NVIDIA Dynamo와 NIXL 프리미티브를 활용함
    혹시 이미 시도해본 사람이 있는지 궁금함

    • 나도 그걸 보고 싶음. 3090을 하나 더 사고 PCIe3 병목을 해결하려고 마더보드 업그레이드를 고려 중임. glm 4.7~5를 q4_k_m으로 돌릴 수 있을 듯함
  • 멋진 프로젝트임. 일반 GPU에서 DKMS 패치 과정을 좀 더 자세히 알고 싶음. 나도 시도해보고 싶음

    • 문서를 업데이트해서 패치 과정과 위험 정보를 추가했음
    • NVIDIA 오픈소스 드라이버를 수정해 P2P GPU 통신이나 vGPU 분할 같은 엔터프라이즈 기능을 잠금 해제한 사례도 있음
      관련 링크: RTX4090 P2P Unlock, vGPU Unlock