AcademySoftwareFoundation / AcademySoftwareFoundation/Imath

fp32 to f16 benchmarking

Open
#343 0 comments 1 reaction 0 assignees View on GitHub
Dominant language
C++
Stars
488
Forks
161
Avg merge
1d 3h
Merged PRs (30d)
3

Description

This article was published a few moths ago showing various methods for converting f32 to f16
https://www.corsix.org/content/converting-fp32-to-fp16

I had some existing code for checking accuracy against hardware that I've adapted it to benchmark them along with Imath's implementation and a few of my own.
https://github.com/markreidvfx/float2half_test

![image](https://github.com/AcademySoftwareFoundation/Imath/assets/814966/10ea3a0c-41cf-4613-9184-cb951bc21b96)

![image](https://github.com/AcademySoftwareFoundation/Imath/assets/814966/45f81316-9494-402e-9445-add338ffc9c1)

x86 since ivy bridge (2012) and AMD jaguar (2013) can have the f16c extensions, I'm not sure if its optional feature, but you can use the `cpuid` instruction to find out if its present. Ideally this benchmark should be tested on machines that don't have the fp16c extension. Unfortunately I only have a 2 macOS machines that are that old.

![image](https://github.com/AcademySoftwareFoundation/Imath/assets/814966/a9a5954f-dfa1-4bd0-b9f3-f88d2cac0592)

Interestingly `ryg` performs somewhat better, I think its because the macOS 10.13 platform might guarantee sse4.2 is present and clang is able to better vectorize. I haven't really analyzed the asm yet.

There are more machines I ran the benchmark on my github project page.

`ryg` and `maratyszcza` seem to perform the best but it can vary a lot between compilers. They do a clever trick by using the floating point unit to do the rounding the the is needed for the conversion. I implemented a SSE2 version of `maratyszcza` that I think would a good fallback for x86_64.

Another test the benchmark runs is exact accuracy against hardware.

![image](https://github.com/AcademySoftwareFoundation/Imath/assets/814966/54ea5377-6b44-4991-86cd-496e18713b62)

Imath doesn't do an exact hardware match of all NaN values. They are still NaN but different then hardware.
![image](https://github.com/AcademySoftwareFoundation/Imath/assets/814966/7b9eebe5-9e41-47d1-9678-d9de2e741a7b)

This can be fixed by changing
https://github.com/AcademySoftwareFoundation/Imath/blob/main/src/Imath/half.h#L401
```
return ret | (uint16_t) m | (uint16_t) (m == 0);
```
to
```
return ret | (uint16_t) m | 0x0200
```

Contributor guide

Open the contributing guide

Research direction

Start with src/Imath/half.h at line 401 and compare the NaN conversion behavior against the hardware results and benchmark project linked in the issue. Review the benchmark's fp32-to-fp16 methods, including the proposed SSE2 fallback, and determine the intended scope. Done means the selected conversion behavior and benchmark results are verified against the stated hardware expectations.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
computer-graphics, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.