4

好吧,这根本不是一个优化问题。

我正在编写一个(目前)简单的 Linux 内核模块,我需要在其中找到一些位置的平均值。这些位置存储为浮点(即float)变量。(我是整件事的作者,所以我可以改变这一点,但我宁愿保持浮动的精确性,如果可以避免的话,不要参与其中)。

现在,这些位置值存储(或至少习惯于)在内核中只是为了存储。一个用户应用程序写入这些数据(通过共享内存(我使用的是 RTAI,所以是的,我在内核空间和用户空间之间有共享内存)),而其他应用程序则从中读取数据。我假设从浮点变量读取和写入不会使用 FPU,所以这是安全的。

安全,我的意思是避免在内核中使用 FPU,更不用说某些系统甚至可能没有 FPU。我不会使用kernel_fpu_begin/end,因为这可能会破坏我的任务的实时性。

现在在我的内核模块中,我真的不需要太多的精度(因为无论如何位置都是平均的),但我需要它达到 0.001。我的问题是,如何在不使用 FPU 的情况下将浮点数转换为整数(原始数字的 1000 倍)?

我考虑过手动从浮点数的位模式中提取数字,但我不确定这是否是个好主意,因为我不确定字节序如何影响它,或者即使所有架构中的浮点都是标准的。

4

4 回答 4

5

SoftFloat软件包具有完全符合您要求的功能float32_to_int32它在软件中实现了 IEEE 754)。

最后,无论如何在内核中提供某种浮点支持(无论是硬件还是软件)都会很有用,因此在您的项目中包含它很可能是一个明智的决定。它也不是太大。

于 2012-04-18T16:07:32.563 回答
5

如果您想告诉 gcc 使用软件浮点库,显然有一个开关,尽管在标准环境中可能不是交钥匙:

在 x86 linux 上使用软件浮点

事实上,这篇文章表明 linux 内核及其模块已经编译为-msoft-float

http://www.linuxsmiths.com/blog/?p=253

也就是说,@PaulR 的建议似乎是最明智的。而且,如果您提供的 API 可以进行您喜欢的任何转换,那么我不明白为什么它比其他任何东西都丑。

于 2012-04-18T16:02:44.850 回答
2

真的,如果可能的话,我认为您应该更改模块的 API 以使用已经采用整数格式的数据。当您不允许在内核空间中使用浮点时,在内核用户界面中使用浮点类型只是一个坏主意。

话虽如此,如果您使用单精度浮点数,它基本上总是 IEEE 754 单精度,并且字节序应该与整数字节序匹配。据我所知,Linux 支持的所有拱门都是如此。考虑到这一点,只需将它们视为无符号 32 位整数并提取这些位以缩放它们。如果可能的话,我会缩放 1024 而不是 1000;这样做真的很容易。只需从尾数位(位 0-22)开始,位 23 上的“或”,然后如果指数(减去 127 的偏差后)小于 23 则右移,如果大于 23 则左移。你会需要处理右移量大于 32 的情况(C 不允许;

如果您碰巧知道您的值不会超过特定范围,当然,您可以消除其中一些检查。事实上,如果你的值永远不会超过 1 并且你可以选择缩放,你可以选择它为 2^23,然后你可以直接使用((float_bits & 0x7fffff)|0x800000)指数为零时的值,否则右移。

于 2012-04-18T18:17:23.310 回答
0

您可以使用有理数而不是浮点数。操作(乘法,加法)也可以在不损失准确性的情况下实现。

如果您真的只需要 1/1000 精度,则可以将 x*1000 存储为长整数。

于 2012-04-18T16:07:59.760 回答