在 C 语言中,最简单的实现公式是什么int divround(int a, int b) {...},其中输出为 a/b,并采用银行家四舍五入(四舍五入为偶数)?
例如,divround(3,2)两者divround(5,2)的计算结果均为 2。
我正在编写嵌入式代码,所以我不能依赖库。我希望代码对于 ARM 和 RISC-V 是通用的,所以也不需要汇编。我试图模仿np.around(a/b)NumPy 中的行为(它执行大约一半到偶数),因此我可以准确比较来自 Python 和我的嵌入式应用程序的输出测试向量。
float64、32 和 16 的 IEEE 754 标准使用有符号有效数和有偏指数。作为一名设计硬件架构的学生,对有效数和指数部分使用二进制补码对我来说更有意义。
例如,32 位(半精度)浮点数被定义为第一位代表符号,接下来的 8 位 - 指数(127 偏置),最后 23 位代表尾数。要实现(负数的)加法/乘法,我们需要将尾数转换为二进制补码并返回。由此产生的硬件相当复杂。
相反,请考虑前 8 位是否表示指数,后 24 位表示尾数,两者均采用二进制补码。位移、加法和乘法相对简单,硬件也不那么复杂。此外,我们有一个唯一的有效位零(两个零表示有符号位)
我搜索了几个月来寻找这些设计决策的原因,并找到了这些:
这是真的,我们需要一个加法器(减法器)来比较 2 的补码。但是,对于 GPU 和我自己的基于 FPGA 的 CNN 加速器等流水线架构,我们需要避免可变延迟。逐位迭代比较有符号表示使得无法预先确定延迟。在我看来,在这种情况下减法更好。
也许我们可以为此分配一两个位。并将有效数设为 23 位。
现在这是一个正当理由。它并不真正适用于我的用例,但我想知道如果他们用额外的位来实现它是否会更好。
我的用例
我正在 FPGA 上构建 CNN 加速器。预定义乘法和加法延迟以及最小化硬件复杂性对我来说至关重要。我不执行除法,也不必担心 inf 和 NAN。
因此,我决定使用如上所述的二进制补码表示来使用浮点的自定义内部表示。有什么明显的缺点我应该小心吗?