Finish powf post.

This commit is contained in:
James Pace 2024-02-01 01:04:35 +00:00
parent 5a6717ad3a
commit 4ce9eb3fd1
3 changed files with 48 additions and 81 deletions

View File

@ -1,20 +0,0 @@
---
title: "Rust: libm vs micromath speed comparison"
author: "James Pace"
date: "2024/01/16"
---
<!--
Relevant for comparison:
1. Distance between two points.
2. Dicretizing a point into a grid.
On laptop libm was way faster...
~0.23ms compared to 0.70ms in release
0.73ms compared to 8.66ms in debug
Switching to powi micromath
0.3ms in release
3.0ms in debug
-->

View File

@ -1,61 +0,0 @@
---
title: "Rust: powf is slow"
author: "James Pace"
date: "2024/01/18"
---
I'm currently working on my motion planner on a microcontroller project and
was looking at switching from [libm][libm] to [micromath][micromath] as the
library I use for standard math operations.
For context, in Rust, normal math operations (like absolute value and square
root for floats) are provided as part of the standard library (called `std`).
The standard library is not available in environments that don't have a backing
operating system.
Crates than run in those environments thus can't use `std`, which is called being
`no_std`.
A lot of functions that are in `std` are actually in two other crates, `core` or `alloc`
which can be used in `no_std` environments.
The normal math functions aren't one of them, and therefore a different library has to be
used.
My intitial implementation of the planner used `libm` (largely because I found it first),
and when I later found `micromath` I wanted to do some profiling comparisons to see which
one was faster.
I'm going to make a separate blog post with statistics from the profiling, but I wanted to
write a quick article today talking about `powf`.
One of the operations my planner does a lot is find the distance between two things.
My initial implementation did something like
```rust
fn distance(point1: &Point, point2: &Point) -> f32 {
let squared_dist = powf((point2.x - point1.x), 2.0) + powf((point2.y - point1.y), 2.0);
sqrt(squared_dist)
}
```
which works fine.
When I was profiling I switched to:
```rust
fn distance(point1: &Point, point2: &Point) -> f32 {
let squared_dist = powf((point2.x - point1.x), 2.0) + powf((point2.y - point1.y), 2.0);
sqrt(squared_dist)
}
```
which was noticeably faster for both `libm` and `micromath` particularly on the `microbit`
that I was using for profiling.
## Does this replicate for `std::powf`?
Not when building with `--release`. [^release-rant]
## How much faster?
[^release-rant]: As an aside, I think I'm going to switch to using `--release` when building rust code
all the time. The optimizations help a ton, to the extent I would never "use" software
not built with `--release` and extrapolating performance, even experientially, from
binaries built with the `dev` profile is just not transferrable at all.
[libm]: https://github.com/rust-lang/libm
[micromath]: https://github.com/tarcieri/micromath

48
posts/powf_is_slow.md Normal file
View File

@ -0,0 +1,48 @@
---
title: "Rust: powf is slow"
author: "James Pace"
date: "2024/01/31"
---
I'm currently working on a project in Rust which does a lot of math on
a microcontroller.
In Rust, normal math operations (like absolute value and square
root for floats) are provided as part of the standard library (called `std`),
which is not available for the microcontroller I'm using.
Thus, alternate libraries have to be used.
The two major ones I've found (and which I need to do a detailed comparison
of) are [micromath][micromath] and [libm][libm].
For now, I've been using `libm`, mainly because its the first one I found.
One of the operations my project does a lot is find the distance between two points.
My initial implementation did something like
```rust
fn distance(point1: &Point, point2: &Point) -> f32 {
let squared_dist = libm::powf((point2.x - point1.x), 2.0) + libm::powf((point2.y - point1.y), 2.0);
sqrt(squared_dist)
}
```
While doing some profiling, I switched to
```rust
fn distance(point1: &Point, point2: &Point) -> f32 {
let x_dist = point2.x - point1.x;
let y_dist = point2.y - point1.y;
let squared_dist = x_dist*x_dist + y_dist*y_dist;
libm::sqrt(squared_dist)
}
```
which was significantly faster, especially on the `microbit` I was running the code on for
profiling.
Out of curiousity, I tried doing the same thing, but on my laptop using `std::powf` instead
of `libm::powf`.
When compiling with the default optimization level (`-O3`), I saw a similar performance
increase, but not when I switched to compiling with `--release`, which I found interesting,
and which underscores the importance of building in `--release` which shipping Rust binaries.
[libm]: https://github.com/rust-lang/libm
[micromath]: https://github.com/tarcieri/micromath