7 / 24 · 개념
누적 폭·반올림·포화
9개 signed int8 곱의 합을 담는 데 18비트 signed가 충분한가요? 바이어스는 0이라고 가정하세요.
내용은 무료로 볼 수 있습니다. 수강 신청하면 학습 기록을 저장할 수 있어요.
출력 폭과 누적 폭은 다릅니다
8비트 입력과 8비트 가중치가 8비트 결과를 낸다고 해서 누적기까지 8비트로 만들 수는 없습니다. 부호 있는 8비트 코드의 절댓값은 최대 128입니다. zero point가 0이고 L개의 항을 누적한다면 보수적인 절댓값 경계는 L×128×128입니다. 바이어스의 절댓값도 더합니다. 이 경계를 담는 signed 누적기는 양수 최댓값이 경계 이상인 폭으로 선택합니다. 부호 비트가 필요한 점을 잊지 마세요.
폭 계산 예제
C=3,R=S=3이면 L=27입니다. 모든 입력과 가중치가 −128인 경우 곱은 +16384이고 총합은 442368입니다. 19비트 signed 최댓값은 262143이므로 부족합니다. 20비트 signed 최댓값 524287은 이 양의 경계를 담습니다. 바이어스 절댓값 1000을 포함한 경계 443368도 들어갑니다. 실제 입력 범위가 좁으면 더 작은 폭을 증명할 수 있지만 대표 입력 몇 개만 보고 폭을 줄이는 것은 증명이 아닙니다.
uint8 코드에 z=0이면 중심값은 0부터 255이므로 위의 128 경계를 쓸 수 없습니다. 두 중심값의 절댓값 범위를 먼저 구해야 합니다. 일반적으로 A=max(abs(qmin−zₓ),abs(qmax−zₓ)), B도 같은 방식으로 구해 L×A×B+abs(b)를 사용합니다. 중심값이 원래 저장 폭보다 넓어질 수 있으므로 뺄셈 결과 신호의 폭도 확인해야 합니다.
마지막 변환에서 순서 고정하기
정수 누적 A를 출력으로 바꾸는 multiplier는 sₓsᵥ/sᵧ입니다. 예를 들어 multiplier 0.5,zᵧ=128인 누적 9는 4.5를 짝수 4로 반올림해 출력 132를 만듭니다. 누적 11은 5.5를 6으로 반올림해 134입니다. 누적 −3은 −1.5를 −2로 반올림합니다. 단순 절삭, 0 쪽 절삭과 음수의 산술 시프트는 같은 연산이 아닙니다. JavaScript의 기본 Math.round도 음수 절반에서 이 계약과 다를 수 있으므로 실습에서는 별도 함수를 사용합니다.
범위가 int8이면 반올림한 300은 127로, −300은 −128로 포화합니다. 비트만 잘라내면 각각 44와 −44처럼 값이 뒤집힐 수 있습니다. 포화 전후 값과 포화 발생 횟수를 검증 로그에 남기세요. ReLU를 연결할 때 출력 zero point가 표현하는 0과 비교해야 하며 단계의 순서도 계약에 포함됩니다.
검증 기준
최대 양수 합, 큰 음수 합, 정확한 반올림 절반, 포화 직전·직후와 바이어스가 큰 경우를 모두 준비합니다. 넓은 기준 모델과 제한된 RTL 폭 모델의 차이를 의도적으로 재현하면 폭 오류를 쉽게 찾을 수 있습니다. 다음 실습의 예제는 값이 작은 안전한 정수 안에서 계산합니다. 큰 범위로 확장할 때는 기준 언어 자체의 정수 정확도도 검토해야 합니다.
직접 생각해 보기
9개 signed int8 곱의 합을 담는 데 18비트 signed가 충분한가요? 바이어스는 0이라고 가정하세요.
해설 보기
보수적인 양수 경계는 9×16384=147456입니다. 18비트 최댓값 131071보다 크므로 부족합니다. 19비트는 262143까지 담습니다.