5个版本
0.1.3 | 2022年4月19日 |
---|---|
0.1.2 | 2022年1月5日 |
0.1.1 | 2022年1月5日 |
0.1.0 | 2022年1月5日 |
0.0.0 | 2021年10月30日 |
#843 in 数学
66KB
1.5K SLoC
快速浮点数数学
fast_fp
提供了一组原始类型,支持许多操作的对快速数学编译器优化。这些优化允许编译器通过放宽一些IEEE 754浮点算术的要求来生成潜在的更快的代码。
示例
use fast_fp::{FF32, ff32};
// Construct instances of the fast type from std's type using the convenience
// wrapper `ff32` (or `ff64`)
let four = ff32(4.0);
// or using the `From`/`Into` trait
let five: FF32 = 5.0.into();
assert_eq!(four + five, ff32(9.0));
// Most ops are also implemented to work with std's floats too (including PartialEq).
// This makes working with literals easier.
assert_eq!(five + 6.0, 11.0);
assert_eq!(five * 2.0, 10.0);
// Functions can be made generic to accept std or fast types using `num-traits`
use num_traits::real::Real;
fn square<T: Real>(num: T) -> T {
num * num
}
assert_eq!(square(3.0_f32), 9.0);
assert_eq!(square(five), 25.0);
// If the nalgebra feature (with version suffix) is enabled, interop with
// nalgebra is supported
# #[cfg(feature = "nalgebra_v029")]
use nalgebra_v029 as na;
# #[cfg(feature = "nalgebra_v029")]
assert_eq!(na::Matrix3::repeat(four).sum(), 36.0);
注意事项
精度
快速数学优化可能会导致与标准浮点原始类型(如 f32
)操作不同的输出,尤其是在精细精度很重要的情况下。快速数学可能允许以某种方式重新排序操作,从而在整个计算中丢失一些精度。请注意,也有快速数学优化可以提高精度的案例,例如将单独的乘法和加法合并为融合乘加操作。
性能
使用此Crate的原始类型在某些情况下可能不会比标准原始类型更快。这可能是因为生成的代码在实际中较慢,或者是因为此Crate为防止未定义行为(特别是对于比较密集的代码)所采取的某些措施。用户应仔细测量和基准测试其代码,以了解他们是否真正从使用这些类型中受益。
有限数学
许多操作启用了finite-math-only
优化标志。使用此标志时,用户必须确保对快速类型的操作不涉及无穷大或NaN值。如果操作的参数是,或者操作的结果将是无穷大(+inf、-inf)或NaN,则操作的结果值是不确定的。此Crate尽力确保此类操作在严格意义上不是未定义行为,但输出可以是输出类型的任何可表示值,并且可能根本不是固定值。
构建
fast_fp
通过调用启用这些优化的C代码来实现快速数学优化;此外,还使用了一些LLVM IR来防止这些优化可能触发的未定义行为(UB)。因此,构建此crate需要安装 clang
,并且最终二进制文件需要使用跨语言LTO链接以获得性能提升。
这种LTO需要与rustc使用的LLVM版本兼容的clang版本。要找到所需的LLVM版本,请在 verbose 模式下检查rustc的版本信息。
$ rustc -vV
rustc 1.56.0 (09c42c458 2021-10-18)
binary: rustc
commit-hash: 09c42c45858d5f3aedfa670698275303a3d19afa
commit-date: 2021-10-18
host: x86_64-unknown-linux-gnu
release: 1.56.0
LLVM version: 13.0.0 # <--- see the version here
然后使用相应版本的 clang
和 lld
进行构建和链接。
$ CC="clang-13" \
RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang-13 -Clink-arg=-fuse-ld=lld-13" \
cargo build
为了简化,这些参数可以存储在一个 cargo config 文件中。
[env]
CC = "clang-13"
[build]
rustflags = ["-Clinker-plugin-lto", "-Clinker=clang-13", "-Clink-arg=-fuse-ld=lld-13"]
尽管rustc并不总是使用官方的LLVM发布版本,但通常与同一版本号的官方clang和LLVM发布版本兼容性足够好。
依赖项
~0.1–1.4MB
~26K SLoC