포스트

Bitnet 논문 번역

fp16, fp8, int4도 아닌 1비트 추론을 하면서 성능에는 손실이 없다는 논문. BitNet이 궁금했다. CPU를 타겟으로 해서 아직 GPU도 지원 안한다는 것 같은데 자세히 알아보자

MS Research팀에서 발표한 논문인데 우선 저자들은 모두 중국인인 것 같다. 팀에도 중국인이 많나보다 했는데 이미 유명대학에는 중국인 교수들이 많아서 자연스레 중국인 석, 박사생도 많고 기업으로 연결까지 된다고 한다.

Abstract

BitNet과 BitNet b1.58과 같은 발전한 최근의 1-bit 대규모 자연어처리 모델들(LLMs)은 속도와 에너지 소비 측면에서 LLM들의 효율성을 향상시키는 유망한 접근법들을 다루고 있다. 덕분에 직접 local에서 다양한 장비에 LLM을 배포하는 장비 종류에 구애받지 않는 시대에 한 발짝 가까워졌다. 본 논문에서 우리는 bitnet.cpp를 소개한다. bitnet.cpp는 1-bit LLM 모델들의 잠재력을 모두 끌어낼 수 있는 잘 정제된 소프트웨어 스택이다. 특히, 우리는 몇 가지 커널들을 개발해 BitNet b1.58 LLM들이 CPU에서 삼진(3가지로 표현하는 ternary)으로 빠르고 손실 없는 추론을 구현했다. 더 나아간 실험들에서 bitnet.cpp가 다양한 크기의 모델들에 테스트했을 때 상당한 속도 향상을 보인 것으로 나타났는데 x86 CPU에서는 2.37배에서 최대 6.17배까지 향상시켰고 ARM 계열 CPU에서는 1.37배에서 5.07배까지 향상시켰다.

(그림 1: 다양한 크기의 BitNet b1.58 모델들에 대해 Apple M2 Ultra (ARM CPU)에서 llama.cpp(fp16)을 사용했을 때와 bitnet.cpp를 사용했을 때의 추론 속도와 에너지 소비 비교표이다. 결과에서 볼 수 있 듯 bitnet.cpp가 인간이 읽는 속도를 따라잡은 것을 볼 수 있는데 심지어 이는 100B 모델을 단 하나의 CPU에서 추론한 결과이다. 주목할만한 것은 bitnet.cpp는 다양한 크기의 모델들 모두에서 에너지 소비를 확연히 줄였다는 것이다.)

1. bitnet.cpp

bitnet.cpp는 1-bit LLM들을 위한, (예를 들면 BitNet b1.58 모델들) 추론 프레임워크이다. bitnet.cpp는 속도와 에너지 소비를 둘 다 최적화하면서 손실 없는 추론을 제공한다. bitnet.cpp의 초기 버젼은 CPU에서의 추론을 제공한다.

위에 그림1에서 언급했듯, bitnet.cpp는 ARM계열 cpu에서 1.37 ~ 5.07 배의 속도 향상을 달성했고 모델의 크기가 클수록 더 큰 폭의 성능 향상을 얻었다. 추가적으로 에너지 소비를 55.4% ~ 70.0% 까지 줄이며 전반적인 효율성을 증진했다. x86 계열 CPU에서는 속도 향상은 2.37 ~ 6.17배였고 에너지 절감량은 71.9% 에서 82.2%까지 늘렸다. 게다가 bitnet.cpp는 100B BitNet b1.58 모델을 단 하나의 싱글 CPU에서 구동할 수 있으며 인간의 읽기 속도와 유사한 수준인 5-7토큰을 달성했다. 이로써 로컬 장비에서 LLM을 구동할 수 있는 중대한 잠재력을 입증했다.

bitnet.cpp를 이용해 추론하려면 다음 단계를 따르라.

2. Optimized Kernels for 1.58-bit Models

bitnet.cpp는 최적화된 커널 모음을 제공하는데 이는 I2_S, TL1과 TL2를 포함한다. 커널들은 1.58-bit 모델들이 x86과 ARM 아키텍쳐에서 빠르고 손실 없이 추론할 수 있게 고안됐다

| Unpack | Pack | | —— | —- | | -1 | 00 | | 0 | 01 | | 1 | 10 | (Table 1: I2_S 커널은 변환 각각의 full-precision 가중치를 2-bit로 변환해 메모리와 대역폭을 아낀다. 연산을 수행할 때 2-bit 가중치는 분해돼 원본 값으로 다시 돌아온다.)

I2_S 커널은 바닐라 multiply-then-addition(가장 단순한 일반적 형태의 “곱 이후 더하기”) 를 사용해 행렬곱을 계산한다. Table 1에 나와있는 것처럼, 각 full-precision 가중치들을 2비트 표현으로 바꾼다. 연산을 하며 커널은 변환된 가중치를 기존 원본 가중치 값으로 되돌리고 바닐라 GEMV 연산을 수행한다. (GEMV 연산은 행렬-벡터의 일반화된 연산을 의미하며 GEneral Matrix Vector multiplication이다.) 우리는 충분한 스레드 여유가 있을 때 사용하기를 추천하는데 컴파일러로 하여금 효율적으로 구성된 지시 순서를 구성해 동작하기 때문이다.

| Unpack | | Pack | | —— | — | —- | | -1 | -1 | 0000 | | -1 | 0 | 0001 | | -1 | 1 | 0010 | | 0 | -1 | 0011 | | 0 | 0 | 0100 | | 0 | 1 | 0101 | | 1 | -1 | 0110 | | 1 | 0 | 0111 | | 1 | 1 | 1000 | (Table 2: TL1 커널은 full-precision 가중치 2개를 쌍으로 묶어 4-bit 인덱스로 변환하고 LUT(Lookup Table) 연산을 수행한다.)

TL1 커널은 모든 full-precision 가중치를 2개씩 묶어 4-bit index로 전처리하고 이에 대응하는 활성화에 맞게 사전연산한다. 이 연산은 3^2로 9개 값을 갖게 된다. 인덱스-값 쌍은 LUT 연산을 위해 lookup table에 저장된다. GEMV 처리는 int16 LUT와 덧셈 가산을 통해 수행된다. 우리는 큰 모델을 서빙할 때 제한된 수의 스레드를 활용하길 추천한다.

(Table 3: TL2 커널은 모든 full-precision 가중치 3개를 쌍으로 묶어 1-bit sign (0 혹은 1)로 압축하고 4-bit index 또한 만든다.)

TL2 커널은 TL 1과 유사하다. 주된 차이점은 모든 full-precision 가중치 3개를 쌍으로 묶어 5-bit index로 만든다는 것이다. 그래서 TL1이 가중치 2개마다 4-bit index로 만드는 것과 대조된다. 그러므로 TL2는 TL1 보다 더 높은 압축률을 갖는다. 우리는 제한된 메모리와 대역망을 가진 환경에서 사용하기 추천하는데 왜냐하면 TL2는 TL1 커널에 비해 LUT를 다뤄 모델 크기를 1/6로 만들기에 요구하는 대역망을 낮춘다.

3. Evaluation

3.1 Inference Performance

우리는 추론 속도와 에너지 소모 측면에서 bitnet.cpp를 검정했다. 125M에서 100B까지 다양한 파라미터 사이즈의 모델들에 포괄적인 테스트들을 시행했다. 각 모델을에 대한 config 구성들은 부록 A에 기술돼있다. 이런 크기들은 대중적인 LLM config을 표현한다. 추가적으로 시스템적인 테스트들 또한 ARM과 x86 계열에 수행되었다. ARM에서 우리는 Mac Studio와 Apple M2 Ultra 프로세서를 사용했고 각 end-to-end 테스트에는 64GB 메모리를 사용했다. x86에서는 Surface Laptop Studio 2와 Intel Core i7-13700H 프로세서 (14코어, 20스레드)와 64GB 메모리를 사용했다.

우리는 각 장비에 대해 두 가지 시나리오로 테스트했다: 하나는 2개 스레드로 제한된 상태에서의 추론이고 다른 하나는 스레드의 제한이 없는 상태에서의 추론이며 이 상태에서 각각 최적의 추론 속도를 기록했다. 그리고 이는 로컬 장비의 제한된 스레드 가용성을 고려한 것인데 BitNet b1.58의 로컬 환경에서의 더 정교한 성능 평가를 제공한다.

Inference Speed: 아래 표현된 Table 4와 Table 5에서는 ARM(Apple M2)와 x86 (Intel i7-13700H) 두 아키텍처 모두에서 bitnet.cpp가 llama.cpp와 비교해서 압도적인 성능 차이가 있음을 보여주고 있다. 특히 모델의 크기가 커질수 bitnet이 더욱더 압도한다. bitnet.cpp는 일관되게 llama.cpp보다 우위에 있으며 모델과 아키텍쳐에 따라 1.37배에서 6.46배까지 넘어선다. apple M2에서는 스레드 제한이 없는 시나리오에서 5.07배의 속도 향상 절정을 기록한 반면 Intel i7에서의 bitnet.cpp는 제한된 스레드 시나리오에서 6.46배를 기록했다. 이렇듯 자원이 제한된 로컬 추론을 특히 효과적으로 만들 수 있다는 것이다.

모델의 크기에 비례해 성능 차이는 더 벌어지는데 비교적 큰 모델들(13B 이상 급)은 bitnet.cpp의 최적화의 수혜를 가장 많이 보고 있다. Intel i7에서 bitnet.cpp는 어마어마한 속도 향상을 제공해 x86 구조에 완벽히 들어맞았으며 스레드 제한이 있는 상황에서도 좋은 성능을 보였다. 반면에 작은 모델들(125M에서 1B) 또한 의미있는 성능 향상을 얻었으나 bitnet.cpp의 진가는 크고 복잡한 모델에서 요구하는 워크로드를 효율적으로 다룰 때 발휘된다. 관측된 성능 차이에 덧붙이면 여러 대역망 제한 또한 여러 아키텍쳐에서 bitnet.cpp의 다양한 효율성에 중요한 영향을 미치게 되는데 특히 Apple M2와 Intel i7에서 비교했을 때 그렇다. Apple M2의 큰 대역망 덕분에 Intel i7에 비해 큰 모델을 돌릴 때 특히 상당한 차이의 빠른 속도 향상을 달성할 수 있었다.

(Table 4: 다양한 CPU들 (Unit: Tokens/Second)에 걸친 추론 속도 비교. 스레드 설정 제한이 없는 상태이고 “N/A”는 시험한 CPU가 주어진 커널로 명시된 크기의 모델을 호스팅 할 수 없음을 나타낸다.)

(Table 5: 다양한 CPU들 (Unit: Tokens/Second)에 걸친 추론 속도 비교. 스레드 설정 제한을 둔 상태이고 가용한 추론 스레드는 2개로 설정돼있다. “N/A”는 시험한 CPU가 주어진 커널로 명시된 크기의 모델을 호스팅 할 수 없음을 나타낸다.)

Energy Cost: 우리는 700M, 7B 그리고 70B 모델들을 구동해서 에너지 비용(토큰당 줄 에너지)을 보고했는데 스레드 설정 제한 없는 상태의 최고 추론 속도일 때를 기준으로 테스트했다. Table 6는 에너지 소비 감소에 있어 bitnet.cpp의 확실한 이점을 보여준다. Apple M2에서 bitnet.cpp는 모델 크기에 따라 상이하지만 에너지 사용량을 55.4%부터 70%까지도 줄였다. 모델 크기가 커질수록 bitnet.cpp의 에너지 효율성은 더 큰 폭으로 증가했다. 가장 큰 모델(70B)는 llama.cpp와 에너지 소비 감소량을 비교했을 때 70%를 보였다. 이는 bitnet.cpp가 큰 규모의 추론을 속도와 에너지 측면에서 더 효율적으로 할 수 있고 이로써 모바일 장비나 엣지 컴퓨팅과 같은 에너지가 제한된 환경에서의 배포 능력을 강조해 보여준다.

인텔 i7에서 bitnet.cpp를 활용한 에너지 절약은 더 극적인데 7B모델까지 71.9%에서 82.2% 범위까지 해냈다. 비록 70B 모델을 활용한 에너지 소비 데이터를 뽑기엔 CPU 상황이 여의치 않았지만 조금 작은 모델들에서는 확실히 bitnet.cpp가 큰 폭으로 LLM의 고성능 멀티코어 프로세서들을 활용한 추론에 있어 에너지 요구사항들을 감소시킨 것을 볼 수 있다.

(Table 6: CPU에 따른 에너지 비용 비교 에너지 비용은(토큰당 줄 에너지), “N/A”는 시험한 CPU가 주어진 커널로 명시된 크기의 모델을 호스팅 할 수 없음을 나타낸다.)

3.2 Inference Accuracy

bitnet.cpp 프레임워크는 손실없는 추론이 가능한 3비트 BitNet b1.58 LLM들이다. 추론 정확도를 평가하기 위해 우리는 임의로 WildChat에서 1000개의 프롬프트를 추출했고 bitnet.cpp와 llama.cpp (FP32 커널로 생성됨)의 생성 결과를 비교했다. 평가는 token-by-token에 기반해 이뤄졌고 최대 모델의 출력 100 토큰마다 수행됐으며 full-precision 출력 결과와 완전히 일치하는 것을 완전한 손실없는 상태라고 가정했다.

이 평가에서는 700M BitNet b1.58 모델을 사용했으며 결과는 bitnet.cpp가 정확하고 손실없는 1-bit LLM으로써 추론하는 것을 입증했다.

(Table 7: llama.cpp와 bitnet.cpp의 추론 정확도 비교표. TQ1_0과 TQ2_0은 llama.cpp의 커널들이고 TL1과 TL2는 bitnet.cpp의 커널들이다. 정확도는 손실없이 추론한 샘플들의 비율을 나타내는데 출력 결과가 full-precision으로 했을 때와 완전히 일치하는 정도이다.)


이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.