Entry tags:
BFloat16 в эпловском процессоре M2
Оказывается, процессор Apple M2 поддерживает в хардвере тип данных BFloat16. Подробности есть в статье: "BFloat16 processing for Neural Networks on Armv8-A".
Проверить факт наличия BFloat16 на конкретном маке можно командой:
Алгоритм преобразования:
Проверить факт наличия BFloat16 на конкретном маке можно командой:
К примеру, команда BFCVT превращает число float32 в bfloat16: BFCVT--Floating-point-convert-from-single-precision-to-BFloat16-format.$ sysctl hw.optional.arm.FEAT_BF16
hw.optional.arm.FEAT_BF16: 1
Алгоритм преобразования:
В компиляторе Си имеются соответствующие встроенные тип и функции. Вот пример.// FPConvertBF() // ============= // Converts a single-precision OP to BFloat16 value with using rounding mode of // Round to Nearest Even when executed from AArch64 state and // FPCR.AH == '1', otherwise rounding is controlled by FPCR/FPSCR. bits(16) FPConvertBF(bits(32) op, FPCRType fpcr, FPRounding rounding) bits(32) result; // BF16 value in top 16 bits boolean altfp = HaveAltFP() && !UsingAArch32() && fpcr.AH == '1'; boolean fpexc = !altfp; // Generate no floating-point exceptions if altfp then fpcr.<FIZ,FZ> = '11'; // Flush denormal input and output to zero if altfp then rounding = FPRounding_TIEEVEN; // Use RNE rounding mode // Unpack floating-point operand, with always flush-to-zero if fpcr.AH == '1'. (fptype,sign,value) = FPUnpack(op, fpcr, fpexc); if fptype == FPType_SNaN || fptype == FPType_QNaN then if fpcr.DN == '1' then result = FPDefaultNaN(fpcr); else result = FPConvertNaN(op); if fptype == FPType_SNaN then if fpexc then FPProcessException(FPExc_InvalidOp, fpcr); elsif fptype == FPType_Infinity then result = FPInfinity(sign); elsif fptype == FPType_Zero then result = FPZero(sign); else result = FPRoundCVBF(value, fpcr, rounding, fpexc); // Returns correctly rounded BF16 value from top 16 bits return result<31:16>; // FPConvertBF() // ============= // Converts a single-precision operand to BFloat16 value. bits(16) FPConvertBF(bits(32) op, FPCRType fpcr) return FPConvertBF(op, fpcr, FPRoundingMode(fpcr));
Компилируем, запускаем:#include <stdio.h> int main() { float f = 123.456; __bf16 b; b = __builtin_aarch64_bfcvtbf(f); printf("From float32 to bfloat16: %.3f -> %#04hx\n", f, b); f = __builtin_aarch64_bfcvtsf(b); printf("From bfloat16 to float32: %#04hx -> %.3f\n", b, f); }
$ gcc-13 -O -march=armv8.6-a+bf16 bfdemo.c -o bfdemo
$ ./bfdemo
From float32 to bfloat16: 123.456 -> 0x42f7
From bfloat16 to float32: 0x42f7 -> 123.500