안녕하세요! 며칠 전 BitNet 프로젝트 개같이 멸망하고 보고서만 미친듯이 작성했었어요 ㅠ
근데 아시죠? 개발자 특유의 그 찝찝함...
'아니, 진짜 A35(Exynos 1380)가 구려서 안 돌아가는 거라고? 쟤네 코드가 문제인 게 아니고??'
이 의심이 꼬리에 꼬리를 물더니 결국 다시 BitNet.cpp의 심연으로 저를 끌고 들어갔습니다.
그리고 여러분... 제가 결국 범인을 잡았습니다!! 엑시노스가 구린 게 아니라(물론 좀 구리긴 하지만)
원본 C++ 코드가 x86(PC) 환경에만 미치도록 편향되어 있었다는 사실을요!
오늘은 그 지독했던 '워드 샐러드(Word Salad)' 현상을 물리치고,
세계 최초로(아마도?) 엑시노스 모바일 환경에서 BitNet 1.58비트 연산을 성공시키기 위한 제 똥꼬쇼...
아니, 고군분투기를 공유합니다. 나아가 깃허브 공식 저장소에 당당히 PR(Pull Request)까지 날리는 과정을 담았습니다.
코드 뜯어고치기
소스 코드를 직접 집도하기로 했습니다. NEON을 확실히 끄기 위해 C++ 코드를 강제로 수정하고, 컴파일러에 인젝션 어쩌구 저쩌구 파이썬 스크립트까지 만들어서 강제로 스칼라(Scalar) 연산으로 돌려봤습니다.
그랬더니... 워드 샐러드가 멈췄습니다! The capital of France is Paris. 라는 정상적인 문장이 튀어나왔죠.
이 말은 즉슨, 엑시노스 하드웨어의 결함이 아니라 BitNet.cpp의 NEON 최적화 코드 어딘가에 치명적인 논리 오류가 숨어 있었다는 뜻입니다.
진짜 문제 발견: PC와 모바일의 '동상이몽' (1x1 커널의 진실)..

원인은 바로 텐서를 메모리에 패킹(Packing)하는 규격 차이에 있었습니다.
- PC(x86)에서 GGUF 파일로 변환할 때 데이터는 128개(QK=128) 단위로 묶입니다.
- 그런데 모바일 ARM NEON 최적화 코드(기존 코드)는 자꾸 64개(QK=64) 기준으로 데이터를 꺼내서 읽으려고 하더군요.
주소가 엇갈리니 당연히 값이 엉망진창으로 계산되고 텐서가 썩어 문드러질 수밖에 없었던 겁니다.
게다가 비트 추출 순서도 AVX2(PC)와 NEON(모바일) 간에 미세하게 달랐습니다.
그래서 ggml_vec_dot_i2_i8_s_1x1 (가장 핵심이 되는 1x1 행렬 곱셈 함수)를 완전히 뜯어고쳤습니다.
QK=128로 강제 고정하고, AVX2와 100% 동일한 로직으로 비트를 쪼개도록 리팩토링했습니다.
코드가 어떻게 변했는지 궁금하시죠? (너무 길어서 요약본만 보여드립니다 ㅋㅋ)
#elif defined(__ARM_NEON)
// [수정 핵심] GGUF 파일은 PC에서 패킹되므로 QK=128을 강제로 따릅니다.
// 기존의 하드코딩 루프를 제거하고 메모리 오프셋 충돌을 방지합니다.
const int QK = 128;
const int nb = n / QK;
// ... (이후 AVX2와 동일한 언패킹 및 DotProd 가속 로직 적용) ...
쓸데없는 if/else 분기문을 싹 날리고 블록(128) 단위로 깔끔하게 떨어지게 만들었습니다.
DotProd 가속기(__ARM_FEATURE_DOTPROD)를 지원하면 미친 속도로 점곱을 수행하게 하고, 아니면 FMA 연산으로 폴백하도록 안전망까지 쳤습니다.
코드를 수정했으니, 이제 다시 엑시노스의 모든 코어를 막아두고(taskset -c 0) 오직 1개의 스레드로 방금 고친 1x1 커널만 통과하도록 테스트해봤습니다.

빌드중..두구두구...
결과는?! (두구두구두구...)

성공...!!!!!!!!

1x1 함수를 타게 했더니 성공했습니다.
이제 1:N N:1 도 모두 타게 수정해서 진행하겠습니다.
감사합니다.

NEON = 1인데도 돌은 모습!!!

진짜성공!!!!!!

너무끼버요 ㅠㅠㅠㅠ초보개발자, 코딩독학에 또 SI 개하청의 하청의 하청의 하청 초급단가받으면서 겨우 목숨연명하는 삶인데도
이렇게 코드를 수정하고 돌리고 직접 검증까지 할 수 있다니... 연봉 3600받는 개발자들은 얼마나 더 뛰어날까...!!!!
'AI Project > Edge AI Agent - LLM(연구,분석,검증)' 카테고리의 다른 글
| [실전/도전-3] 엑시노스 1380이 증명한 1-bit LLM의 가능성 : 진정한 모바일 엣지 AI (0) | 2026.04.26 |
|---|---|
| [실전/도전-2] BitNet.cpp 병렬 연산(1xN, Nx1) NEON 커널 수정: 엑시노스 풀 스레드 봉인 해제 (0) | 2026.04.26 |
| [기술 분석 보고서] ARM64 모바일 환경에서의 1.58-bit 양자화 모델 추론 붕괴 원인 분석 및 C++ 커널 역공학을 통한 해결 (1) | 2026.04.25 |
| [BitNet.Cpp] llama.cpp의 이스터에그 발견과 NEON=1로그의 진실! (0) | 2026.04.25 |
| [분석/검증-3] BitNet.cpp ARM 커널 재작성 : 스칼라 폴백구현을 통한 최종 검증 (0) | 2026.04.25 |
댓글