모든 이야기

반올림 경계 검증: 백만 번의 통과보다 세 입력이 더 유용한 순간

부동소수점 덧셈기에서 수백만 개의 임의 입력을 비교했는데 오류가 없었다고 하자. 반올림 로직도 충분히 검증했다고 말할 수 있을까? 검사한 숫자의 수만으로는 판단하기 어렵다. 답이 바뀌는 경계의 바로 아래, 정확한 경계, 바로 위를 실제로 통과했는지가 더 직접적인 정보다.

반올림 경계 검증은 오차가 큰 숫자를 찾는 일과 다르다. 거의 같은 정확한 결과들이 서로 다른 출력 비트열로 갈리는 지점을 겨냥한다. 대부분의 입력에서는 같은 답을 내는 잘못된 조건식도 이 지점에서 모습을 드러낸다.

1 다음의 숫자 사이를 겨냥한다

binary32에서 1보다 바로 큰 표현 가능 값은 1+2^-23이다. 여기서는 최근접, 정확히 가운데라면 유효숫자의 끝 비트가 짝수인 쪽을 고르는 nearest-even 반올림을 사용하자. 두 값의 정확한 가운데는 1+2^-24다.

a=1에 다음 세 입력 b를 더하면 경계의 세 위치를 의도적으로 만든다. b 자체도 모두 binary32로 정확하게 표현할 수 있다.

b정확한 합의 위치반올림 결과
2^-24−2^-30가운데 바로 아래1
2^-24정확히 가운데1
2^-24+2^-30가운데 바로 위1+2^-23

가운데 사례에서 아래쪽 1의 유효숫자 끝 비트는 0이다. 그래서 1로 간다. 반대로 a=1+2^-23에 b=2^-24를 더하면 아래쪽 끝 비트가 1이다. 이때는 위쪽인 1+2×2^-23을 선택한다. ‘가운데면 항상 아래’ 또는 ‘가운데면 항상 올림’이라는 구현은 이 두 tie 사례 중 하나에서 틀린다.

이 검증이 흥미로운 이유는 아주 작은 잔여 비트 하나가 마지막 출력 비트를 바꾸기 때문이다. 입력 범위를 넓게 훑는 것과 이런 조건의 양쪽을 만드는 것은 서로 다른 작업이다. 모든 임의 비트열이 같은 확률이라고 해도 특정 연산 결과의 경계 위치가 충분히 다양하게 나타난다는 보장은 없다.

마지막 판단에 필요한 정보가 남았는가

정상 범위의 양수 결과를 정해진 유효숫자 폭으로 반올림하는 단순한 상황에서, 남길 마지막 비트를 L, 그다음 비트를 G, 이후 첫 비트를 R, 나머지 버릴 비트의 OR를 S라고 하자. nearest-even에서 남길 유효숫자를 증가시키는 조건은 G AND (R OR S OR L)로 쓸 수 있다.

G=1이고 R=S=0이면 정확한 가운데다. L에 따라 위쪽 또는 아래쪽을 고른다. 가운데보다 위라면 R이나 S가 1이므로 올린다. sticky인 S를 빼먹으면 위 표의 세 번째 입력도 정확한 가운데처럼 처리할 수 있다. 표에서 답이 갈리는 위치가 실제 논리식의 분기와 연결된다.

이 식 하나로 연산기 전체의 반올림 검증이 끝나지는 않는다. 정규화가 만든 자리 이동, 증가 후의 carry, subnormal로 내려가는 이동, 다른 반올림 모드는 각각 추가 조건을 갖는다. 경계를 만들었다면 그 비트 정보가 어느 단계까지 보존되는지도 봐야 한다. 중간에서 버린 정보를 마지막 단계의 올바른 식이 복구할 수는 없다.

기준 답과 입력 생성기를 함께 검토한다

Berkeley TestFloat는 단순한 패턴과 가중된 임의 입력을 섞어 생성하고, 연산 결과와 예외 플래그를 기준 구현과 비교한다. 이는 무작위 비트만 계속 뽑는 것보다 경계의 종류를 의식하는 접근이다. testfloat_gen을 이용하면 연산과 반올림 옵션을 정해 입력과 기대 답을 만들고, 대상 회로를 호출하는 어댑터에서 비교할 수 있다. TestFloat 일반 문서 §4·§5, testfloat_gen 문서

비교할 때는 값만 같으면 된다고 해서는 안 된다. 정확한 가운데의 합이 가까운 표현으로 바뀌었다면 수치 출력이 맞아도 inexact 플래그가 빠질 수 있다. 연산마다 발생한 플래그와 여러 연산 동안 누적한 상태도 구분해야 한다. 어댑터가 다른 거래의 결과나 이전 플래그를 붙여 보내면 산술 오류처럼 보이는 불일치가 생긴다.

또한 기준의 옵션을 대상 계약과 맞춰야 한다. 반올림 모드, tiny 판정 위치, NaN 결과 정책이 다르면 두 쪽의 차이가 곧 회로 버그를 뜻하지 않을 수 있다. TestFloat 문서는 결과 차이를 해석할 책임과 도구의 한계를 함께 설명한다. 특히 division과 square root의 까다로운 반올림 사례나 특정 알고리즘의 오류를 잘 찾는 도구라고 보장하지 않는다. 통과를 무결함의 증명으로 읽어서는 안 된다. TestFloat 일반 문서 §2·§4·§7·§8

재현할 수 있는 검사에는 입력 비트열과 옵션, 기대 결과와 플래그가 남아야 한다. 난수 검사는 생성기 버전과 seed도 남기는 것이 좋다. 실패 사례를 정확한 유리수나 별도의 검증된 계산으로 다시 따져 보면 기준 모델 또는 연결 문제와 실제 반올림 오류를 분리할 수 있다.

수백만 번의 통과보다 위의 세 입력이 더 유용할 때가 있다. 반올림 경계 검증의 목적은 큰 검사 횟수를 만드는 데 있지 않다. 답을 바꾸는 판단마다 양쪽 입력과 정확한 경계 입력을 두고, 그 판단에 필요한 정보와 결과 플래그까지 확인하는 데 있다.

반올림 경계 검증: 백만 번의 통과보다 세 입력이 더 유용한 순간 · ariser