prima.cpp 로컬 LLM 벤치마크: llama.cpp보다 15% 더 빠름
요약
로컬 LLM 추론 엔진인 prima.cpp와 llama.cpp의 성능을 비교한 벤치마크 결과입니다. RTX 4090 및 Apple M2 Max 환경에서 테스트한 결과, prima.cpp가 llama.cpp보다 약 15% 더 빠른 추론 속도를 보여주었습니다.
핵심 포인트
- prima.cpp가 llama.cpp 대비 약 15% 향상된 추론 속도 제공
- RTX 4090 및 Apple M2 Max 등 실제 소비자용 하드웨어 기반 테스트
- AI 에이전트 및 로컬 LLM 최적화 시 초당 토큰 수(t/s)의 중요성 강조
- GGUF 형식 및 Q4_K_M 양자화 모델을 활용한 성능 비교
이 기사는 원래 BuildZn에 게시되었습니다.
모두가 로컬에서 LLM (Large Language Models)을 실행하는 것에 대해 이야기하지만, 추론 엔진 (inference engines) 간의 실제 속도 비교를 찾으려 하면 대부분 일화적인 이야기들에 막히게 됩니다. 저는 FarahGPT 및 다른 AI 에이전트 파이프라인을 위해 7B에서 70B에 이르는 수십 개의 모델을 실행하며 이 작업을 해왔습니다. 이것은 실제 소비자용 하드웨어에서 llama.cpp와 비교한 저의 prima.cpp 로컬 LLM 벤치마크 (local llm benchmark)입니다. 군더더기 없이 숫자만 보여드리겠습니다.
왜 당신의 로컬 LLM 추론 엔진이 중요한가
보세요, 만약 당신이 AI 에이전트로 진지한 무언가를 구축하고 있다면, 곧 추론 비용 문제에 직면하게 됩니다. 클라우드 API는 훌륭하지만, 반복적인 개발, 에이전트 추론 루프 (agent reasoning loops), 또는 개인정보 보호가 중요한 애플리케이션을 위해서는 빠른 로컬 LLM 추론 (fast local llm inference)이 필수적입니다. 저는 NexusOS와 9개 에이전트로 구성된 YouTube 자동화 파이프라인의 성능을 최적화해야 했기 때문에 이 문제에 깊이 파고들었습니다. 하루에 수천 개의 토큰을 생성할 때는 초당 토큰 수 (tokens/second) 하나하나가 중요합니다.
Llama 3 70B와 같은 모델을 RTX 4090에서 실행할 때조차 하드웨어의 한계를 밀어붙이게 됩니다. 10-20%의 속도 향상은 더 빠른 반복 작업, 낮은 전기 요금, 그리고 로컬에 배포할 경우 더 빠릿한 사용자 경험으로 직결됩니다. 이것이 제가 단순히 llama.cpp 너머를 살펴보기 시작한 이유입니다. llama.cpp가 원조(OG)라는 점은 의심의 여지가 없지만, prima.cpp와 같은 새로운 플레이어들이 등장하여 특히 현대적인 GPU에서 더 나은 성능을 주장하고 있습니다. 이것은 단순한 이론이 아닙니다; 초당 얼마나 많은 에이전트 단계 (agent steps)를 실행할 수 있는지에 직접적인 영향을 미칩니다.
prima.cpp vs llama.cpp: 가감 없는 벤치마크
문제는 이렇습니다 — 저는 몇 주 동안 다양한 설정, 모델 양자화 (model quantizations), 그리고 생소한 플래그 (flags)들과 씨름했습니다. 추측하는 것에 지쳤기 때문에 prima.cpp vs llama.cpp에 대한 구체적인 데이터가 필요했습니다. 제 목표는 간단했습니다: 개발자들이 실제로 소유한 하드웨어에서 일반적인 LLM에 대해 어떤 도구가 더 나은 초당 토큰 수 (tokens/second)를 제공하는지 알아내는 것이었습니다.
저는 두 가지 주요 설정에서 이 벤치마크를 실행했습니다:
- 데스크톱 (Desktop): RTX 4090 (24GB VRAM), AMD Ryzen 7 7800X3D, 64GB DDR5 RAM, Ubuntu 22.04.
- 노트북 (Laptop): Apple M2 Max (32GB Unified Memory), 12코어 CPU, macOS Sonoma 14.5.
모델의 경우, 저는 일반적인 GGUF 형식을 고수했으며, 특히 llm inference home devices (로컬 LLM 추론 홈 디바이스)를 위해 품질과 성능 사이에서 최적의 균형을 제공한다고 생각하는 Q4_K_M 양자화 (quantization)를 사용했습니다.
- Llama 3 8B Instruct (Q4_K_M): 현재 소형 모델의 제왕.
- Mixtral 8x7B Instruct (Q4_K_M): 47B 밀집 (dense) 모델처럼 동작하는, 널리 채택된 대규모 희소 전문가 혼합 (sparse mixture-of-experts) 모델. 이는
optimizing local llm(로컬 LLM 최적화)을 위한 진정한 시험대입니다. - Llama 3 70B Instruct (Q4_K_M): 헤비급 모델. 이를 로컬에서 원활하게 실행할 수 있다면 모든 준비가 된 것입니다.
저의 방법론은 일관되었습니다:
- 프롬프트 (Prompt): 고정된 512토큰 프롬프트: "전문 AI 아키텍트로서, 실시간 주식 시장 분석 및 거래를 위한 멀티 에이전트 시스템을 설계하십시오. 최소 5개의 서로 다른 에이전트의 역할, 통신 프로토콜, 데이터 소스 및 의사 결정 로직을 상세히 기술하십시오. 시장 변동성을 처리하는 방법과 자동 매매에 대한 윤리적 고려 사항을 논의하십시오. 이러한 시스템을 위한 기술 스택, 배포 전략 및 모니터링 메커니즘을 상세히 설명하십시오. 출력물은 CTO에게 발표할 수 있는 포괄적인 개요를 목표로 하는 상세한 기술 사양이어야 합니다."
- 생성 목표 (Generation Target): 256토큰.
- 실행 (Runs): 각 모델/엔진/하드웨어 조합에 대해 5회 연속 실행. 첫 번째 실행은 제외(웜업, warm-up)하였으며, 이후 4회 실행의 평균 초당 토큰 수 (tokens/second)를 기록했습니다.
- 보고 (Reporting): 초당 토큰 수 (tok/s) 및 최대 메모리 (Peak Memory) (4090의 경우 VRAM, M2 Max의 경우 Unified RAM).
상세 내역은 다음과 같습니다:
RTX 4090 벤치마크 (Benchmarks)
| 모델 (Model) | 엔진 (Engine) | 초당 토큰 수 (Tokens/sec, 평균) | 최대 VRAM (GB) | 비고 (Notes) |
|---|---|---|---|---|
| Llama 3 8B Instruct | llama.cpp | 42.1 tok/s | 7.2 | 기준 성능 (Baseline performance). |
| ... | ||||
RTX 4090을 위한 핵심 통찰 (Key Insight for RTX 4090): prima.cpp는 특히 모델 크기가 커질수록 일관되게 더 높은 초당 토큰 수 (tokens/second)를 제공했습니다. 8B 모델의 경우 17%의 확실한 이득을 보였으며, Mixtral의 경우 20% 이상 향상되었습니다. 70B 모델이 시스템 RAM으로 스왑(swap)해야 하는 상황에서도 prima.cpp는 약 17%의 우위를 간신히 유지해냈습니다. 이는 이론적인 수치가 아닙니다. 에이전트 루프 (agent loops)에서 직접 체감할 수 있는 실제 성능입니다. |
M2 Max 벤치마크 (M2 Max Benchmarks)
| 모델 (Model) | 엔진 (Engine) | 초당 토큰 수 (Tokens/sec, 평균) | 최대 RAM (GB) | 비고 (Notes) |
|---|---|---|---|---|
| Llama 3 8B Instruct | llama.cpp | 28.7 tok/s | 12.1 | 통합 그래픽 (integrated graphics) 대비 우수한 성능. |
| ... | ||||
M2 Max를 위한 핵심 통찰 (Key Insight for M2 Max): prima.cpp가 작은 모델에서 약간의 우위를 보였지만, llama.cpp는 여전히 Apple Silicon에서 놀라울 정도로 잘 버텨냈습니다. Llama 3 70B의 경우, prima.cpp가 실제로는 더 느렸습니다. 이는 llama.cpp의 Metal 백엔드 (backend)가 고도로 최적화되어 있거나, prima.cpp의 Metal 지원이 아직 CUDA 성능 수준에 미치지 못함을 시사합니다. |
나의 설정 및 방법론 (My Setup and Methodology)
이 환경을 구축하는 것은 단순한 한 줄의 명령어로 끝나지 않았습니다. prima.cpp 로컬 LLM 벤치마크 (prima.cpp local llm benchmark)를 위해서는 제대로 빌드해야 합니다.
llama.cpp 빌드하기
이 부분은 표준적입니다. 나의 Ubuntu 머신의 경우, make -j CXXFLAGS="-O3 -DGGML_CUDA_MMQ" LLAMA_CUDA=1을 사용했습니다. M2 Max의 경우, make -j LLAMA_METAL=1을 사용했습니다. 나는 llama.cpp 커밋 2b957e8을 사용했습니다.
llama.cpp로 모델 실행하기:
# CUDA (RTX 4090) 환경에서 Llama 3 8B 실행 예시
./llama.cpp/build/bin/main \
-m /path/to/models/Meta-Llama-3-8B-Instruct-Q4_K_M.gguf \
...
prima.cpp 빌드하기
이 부분이 흥미로운 지점입니다. prima.cpp는 특정 백엔드 (backends)에 초점을 맞춰 빌드됩니다. CUDA의 경우, 일반적으로 그들의 리포지토리 (repo)를 클론(clone)하고 PRIMA_CUDA=1로 빌드합니다. 나는 prima.cpp 커밋 b1c4e7f를 사용했습니다.
CUDA용 (RTX 4090) prima.cpp 클론 및 빌드
git clone https://github.com/primamodels/prima.cpp.git
cd prima.cpp
...
prima.cpp로 모델 실행하기:
# CUDA (RTX 4090) 환경에서의 Llama 3 8B 예시
# 참고: prima.cpp의 CLI는 약간 다를 수 있으며, 이는 일반적인 호출 방식을 시뮬레이션한 것입니다.
./prima.cpp/build/bin/prima-cli \
...
명령어는 유사하지만, 근본적인 최적화 방식은 다릅니다. prima.cpp는 RTX 카드의 최신 아키텍처를 더 잘 활용하는 더 특화된 CUDA 커널 (kernels)을 보유하고 있는 것으로 보입니다.
내가 처음에 실수했던 것들
솔직히 말해서, 이 벤치마크를 수행하는 과정은 골칫거리였습니다. 몇 가지 초보적인 실수를 저질렀습니다:
prima.cpp가 바로 사용할 수 있는 바이너리(drop-in binary)라고 가정함: 처음에는 CUDA 지원이 포함되지 않은 사전 빌드된prima.cpp바이너리를 다운로드했습니다. 첫 실행 결과는 처참했으며, CPU 추론 (inference) 속도를 보여주었습니다. 알고 보니 NVIDIA GPU를 대상으로 하는 경우PRIMA_CUDA=1을 명시적으로 설정하여 직접 빌드해야만 했습니다. 저는Error: No CUDA capable GPU found by prima.cpp backend, falling back to CPU.라는 에러를 여러 번 마주했습니다. 이는 빌드나 환경 변수 (environment variables) 설정을 잘못했다는 명확한 신호였습니다.- 일관되지 않은
-ngl플래그:llama.cpp의 경우,--n-gpu-layers 999설정을 잊어버리면 (또는prima.cpp의 경우n_gpu_layers) 모델의 일부가 CPU에서 실행되어 결과가 크게 왜곡되었습니다. 8B 모델에서는 괜찮은 수치가 나오다가 Mixtral에서 수치가 급격히 떨어지는 것을 보고, 모든 레이어 (layers)를 GPU로 넘기는 것을 잊었다는 사실을 깨달았습니다. - 프롬프트 (Prompt) 변동: 비교 실행 시 정확히 동일한 프롬프트와
n_predict길이를 사용하는 것을 잊었습니다. 아주 미세한 차이라도, 특히 온도 샘플링 (temperature sampling)이 포함된 경우 토큰 생성 시간 (token generation times)에 차이를 줄 수 있습니다. 모든 실행에서 일관성을 보장하기 위해 Python 스크립트를 작성해야 했습니다.
GPU 메모리 미삭제: 프로세스를 재시작하거나 GPU 메모리를 삭제(nvidia-smi -r 또는 Linux의 경우 재부팅)하지 않고 여러 번의 벤치마크를 연속해서 실행하면, 때때로 메모리 사용량이 부풀려지거나 이후 실행의 성능이 약간 저하되는 현상이 발생했습니다. 메모리 파편화 (Memory fragmentation) 때문일까요? 어쨌든 각 벤치마크 세트 전에 새로 시작하는 것이 중요했습니다.
이러한 문제들은 로컬 LLM 최적화 (optimizing local llm) 설정을 할 때, 특히 서로 다른 추론 엔진 (inference engines)을 다룰 때 흔히 발생합니다.
속도 최적화 (및 OOM 방지)
적절한 엔진을 선택하는 것 외에도, 성능을 더 짜내거나 더 큰 모델을 맞추기 위한 방법은 항상 존재합니다.
- 양자화 (Quantization): 모든 모델에 Q4_K_M을 사용했습니다. 이는 종종 최적의 지점 (sweet spot)이 됩니다. 더 낮게 설정하면 (예: Q2_K) 속도를 높이고 VRAM을 절약할 수 있지만 품질이 떨어집니다. 더 높게 설정하면 (Q8) 품질은 높아지지만 속도와 VRAM 절약 효과가 급격히 감소합니다. 저의 AI 에이전트(AI agents)의 경우, 속도 향상을 위해 Q4_K_M의 약간의 품질 저하는 수용 가능한 수준입니다.
- 컨텍스트 크기 (Context Size):
--ctx-size플래그(prima.cpp의 경우context_size)는 모델이 처리할 수 있는 컨텍스트 양을 결정합니다. 컨텍스트가 커질수록 더 많은 VRAM이 필요합니다. 24GB VRAM 환경에서 70B 모델을 사용할 경우, 특히LLM 추론용 홈 디바이스 (llm inference home devices)에서는 완전한 메모리 부족 (OOM, Out-of-Memory) 오류를 피하기 위해 이를 2048-4096 토큰 정도로 유지하는 것이 필요한 경우가 많습니다. - 배치 크기 (Batch Size): 단일 턴 추론 (single-turn inference)의 경우 배치 크기는 큰 요인이 아니지만, 여러 프롬프트를 동시에 처리하는 경우 (예: 여러 에이전트가 동시에 LLM에 질의하는 경우), 배치 크기를 늘리면 처리량 (throughput)을 크게 개선할 수 있습니다. 특히 더 나은 배치 커널 (batching kernels)을 보유한 것으로 보이는
prima.cpp에서 더욱 그렇습니다. - 모델 로딩 (Model Loading): 모델이 빠른 SSD에 있는지 확인하세요. 70B GGUF 모델을 HDD(spinning disk)에서 로드하면 시간이 꽤 걸릴 수 있습니다. 당연한 소리처럼 들리겠지만, 개발자들이 이를 간과하는 것을 본 적이 있습니다.
한 가지 팁을 드리자면, VRAM/RAM을 적극적으로 모니터링하십시오. Linux에서는 watch -n 0.5 nvidia-smi가 가장 유용한 도구입니다. macOS에서는 활성 상태 보기(Activity Monitor)나 sudo powermetrics --samplers cpu_power,gpu_power -i 1000 -o output.log를 통해 통찰을 얻을 수 있지만, 직접적인 방식은 아닙니다. 메모리 병목 현상이 어디에서 발생하는지 이해하는 것이 로컬 LLM 최적화 (optimizing local llm)의 핵심입니다.
FAQ (자주 묻는 질문)
prima.cpp는 모든 GGUF 모델과 호환되나요?
일반적으로 그렇습니다. prima.cpp는 llama.cpp와 마찬가지로 GGUF 모델과 호환되도록 설계되었습니다. 하지만 최신 프로젝트인 만큼, 더 큰 커뮤니티와 긴 개발 역사를 가진 llama.cpp가 먼저 지원하는 특정하고 덜 일반적인 GGUF 변형이나 모델 아키텍처가 있을 수 있습니다. 최신 지원 모델 및 기능은 항상 해당 프로젝트의 GitHub를 확인하십시오.
AMD GPU에서도 prima.cpp를 사용할 수 있나요?
네, prima.cpp는 AMD GPU를 위한 ROCm 지원을 포함하고 있습니다. 즉, ROCm 스택이 설치된 호환 가능한 AMD 그래픽 카드가 있다면, PRIMA_ROCM=1로 prima.cpp를 빌드하여 NVIDIA CUDA에서와 유사한 성능 이점을 얻을 수 있습니다. 물론 성능은 GPU 세대와 ROCm 드라이버의 안정성에 따라 달라질 것입니다.
최신 GPU에서 llama.cpp 대비 prima.cpp의 주요 장점은 무엇인가요?
주요 장점은 일반적으로 최신 NVIDIA GPU(RTX 30xx 및 40xx 시리즈와 같은 Ampere 아키텍처 이후 모델)에서 더 빠른 추론 속도를 제공한다는 점입니다. prima.cpp는 이러한 현대적 아키텍처에 더 최적화된 특화된 CUDA 커널(CUDA kernels)과 메모리 액세스 패턴(memory access patterns)을 활용하는 것으로 보이며, 이는 llama.cpp의 보다 범용적인 CUDA 백엔드(CUDA backend)에 비해 더 높은 초당 토큰 수(tokens/second)로 이어집니다. 구형 GPU나 Apple Silicon의 경우, 이득이 미미하거나 오히려 성능이 저하될 수도 있습니다.
나의 결론 (My Verdict)
이 모든 것을 종합했을 때, 저의 결론은 명확합니다. RTX 4090이나 그와 유사한 최신 NVIDIA GPU를 사용하여 llm 추론 (llm inference) 홈 디바이스를 구동하는 분들이라면, prima.cpp는 컴파일에 드는 추가적인 노력을 들일 가치가 충분합니다. 8B 및 Mixtral 모델에서의 성능 향상은 매우 유의미하며, 특히 에이전트 루프 (agentic loops)를 통해 LLM을 집중적으로 사용하는 경우 실질적인 차이를 만들어냅니다. 솔직히 말해서, 왜 이것이 최신 NVIDIA 카드에서의 빠른 로컬 LLM 추론 (fast local llm inference) 기본 설정이 아닌지 이해가 되지 않을 정도입니다. Apple Silicon의 경우, llama.cpp가 여전히 더 성숙하고 종종 더 나은 성능을 보여주는 선택지로 느껴집니다. 하지만 4090이 장착된 저의 주력 개발용 머신에서는, 헤비한 작업(heavy lifting)을 위한 기본 도구로서 llama.cpp 대신 prima.cpp를 사용하고 있습니다. 한 번 시도해 보세요. 다만 소스 코드로부터 직접 빌드(build from source)할 준비는 되어 있어야 합니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기