FP16(반정밀도): FP16에서는 부동 소수점 숫자가 16비트를 사용하여 표현됩니다. 부호 비트 1개, 지수 5비트, 분수(가수) 10비트로 구성됩니다. 이 형식은 해당 범위 내의 분수 값을 표현하는 데 더 높은 정밀도를 제공합니다.
BF16 (BFloat16): BF16도 16비트를 사용하지만 배포 방식이 다릅니다. 부호 비트 1개, 지수 8비트, 가수 7비트를 갖습니다. 이 형식은 더 넓은 범위의 지수를 수용하기 위해 분수 부분의 정밀도를 어느 정도 희생합니다.
FP16은 범위가 더 작지만 10비트 가수로 인해 해당 범위 내에서 정밀도가 높습니다.
BF16은 8비트 지수와 7비트 가수로 인해 범위는 더 넓지만 분수 값에 대한 정밀도는 낮습니다.
예제를 사용하여 FP16과 BF16의 차이점을 3가지 사례로 설명하겠습니다. TensorFlow는 하단에서 테스트와 코드를 공유하는 데 사용됩니다.
원래 값: 0.0001 — 두 메서드 모두 다음을 나타낼 수 있습니다.
FP16: 0.00010001659393(이진수: 0|00001|1010001110, 16진수: 068E) — 가수 10개와 지수 5개
BF16: 0.00010013580322 (2진수: 0|01110001|1010010, 16진수: 38D2) — 가수 7개와 지수 8개
보시다시피 지수와 가수가 다르기 때문에 다르게 표현할 수 있습니다. 하지만 FP16이 더 가까운 값으로 더 정확하게 표현한 것을 확인할 수 있습니다.
원래 값: 1e-08(0.00000001)
FP16: 0.00000000000000(2진수: 0|00000|0000000000, 16진수: 0000)
BF16: 0.000000010011 72(바이너리: 0|01100100| 0101100, 16진수: 322C)
이것은 매우 흥미로운 사례입니다. FP16이 실패하고 결과가 0이 되었지만 BF16은 이를 특수한 형식으로 표현할 수 있습니다.
원래 값: 100000.00001
FP16: inf(2진수: 0|11111|0000000000, 16진수: 7C00)
BF16: 99840.00000000000000(2진수: 0|100011 11|1000011, 16진수: 47C3 )
위의 경우 FP16은 실패합니다. 모든 지수 비트가 가득 차서 값을 표현할 만큼 충분하지 않기 때문입니다. 그러나 BF16은 작동합니다
FP16은 딥 러닝 훈련 및 추론에 일반적으로 사용되며, 특히 제한된 범위 내에서 작은 분수 값을 표현하는 데 높은 정밀도가 필요한 작업에 사용됩니다.
BF16은 분수 부분의 정밀도를 희생하더라도 더 넓은 범위의 표현 가능한 값의 이점을 누릴 수 있는 기계 학습 작업용으로 설계된 하드웨어 아키텍처에서 인기를 얻고 있습니다. 이는 큰 기울기를 처리할 때나 넓은 범위의 수치적 안정성이 작은 값의 정밀도보다 더 중요한 경우에 특히 유용합니다.
FP16은 더 작은 범위 내의 분수 값에 대해 더 높은 정밀도를 제공하므로 작은 숫자를 정확하게 표현해야 하는 작업에 적합합니다. 반면에 BF16은 약간의 정밀도를 희생하면서 더 넓은 범위를 제공하므로 더 넓은 범위의 값을 포함하거나 넓은 범위에 걸친 수치 안정성이 중요한 작업에 유리합니다. FP16과 BF16 사이의 선택은 현재 머신러닝 작업의 특정 요구 사항에 따라 달라집니다.
위의 모든 이유로 인해 SDXL(Stable Diffusion XL) 교육을 수행할 때 FP16과 BF16에는 약간 다른 학습 속도가 필요하며 BF16이 더 잘 작동하는 것으로 나타났습니다.
위 예제를 생성하는 데 사용된 코드
import tensorflow as tf import struct def float_to_binary(f): return ''.join(f'{b:08b}' for b in struct.pack('>f', f)) def display_fp16(value): fp16 = tf.cast(tf.constant(value, dtype=tf.float32), tf.float16) fp32 = tf.cast(fp16, tf.float32) binary = format(int.from_bytes(fp16.numpy().tobytes(), 'big'), '016b') sign = binary[0] exponent = binary[1:6] fraction = binary[6:] return f"FP16: {fp32.numpy():14.14f} (Binary: {sign}|{exponent}|{fraction}, Hex: {fp16.numpy().view('uint16'):04X})" def display_bf16(value): bf16 = tf.cast(tf.constant(value, dtype=tf.float32), tf.bfloat16) bf32 = tf.cast(bf16, tf.float32) binary = format(int.from_bytes(bf16.numpy().tobytes(), 'big'), '016b') sign = binary[0] exponent = binary[1:9] fraction = binary[9:] return f"BF16: {bf32.numpy():14.14f} (Binary: {sign}|{exponent}|{fraction}, Hex: {bf16.numpy().view('uint16'):04X})" values = [0.0001, 0.00000001, 100000.00001] for value in values: print(f"\nOriginal value: {value}") print(display_fp16(value)) print(display_bf16(value))
부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.
Copyright© 2022 湘ICP备2022001581号-3