Live data from Hacker News

Rust and C++ on Floating-Point Intensive Code

reidatcheson.com

61–70 of 95 posts

Re: Rust and C++ on Floating-Point Intensive Code

#61
post #59

Earlier quoted context omitted.

You don't have to box, but you do need some sort of type to make things sized. This is usually a pointer of some kind, but any kind of pointer works. Take references, for example: enum List { Nil, Cons(T, &'a List ) } fn main() { let list = List::Cons("hello", &List::Nil); } Box is usually chosen because it's a good default choice.

you're right of course! i should've used a more generic term like "indirection" or "reference", didn't mean to put emphasis on Box

It’s all good, most people say just Box, because it is the majority case.

Re: Rust and C++ on Floating-Point Intensive Code

#62
post #43

I have some experience with this, ie ensuring LLVM optimizes and codegens the "best"! I have been working to generate target independent "kernels" for the Rav1e AV1 encoder and have had to do a lot of unidiomatic things to get LLVM to generate machine code similar in quality to hand written ASM. Granted, this is on integers and not floats, but the same principles should apply. What I've found is that you need to igno…

To sum up: LLVM is heavily optimized for C code, not so much for Rust. So Rust code has to imitate certain C mannerisms for the optimizer to kick in. You have to pay the price of compatibility with the existing toolchain even if it's not your explicit goal.

there are aspects of Rust that are easier for llvm to optimize with than c. there are things rust isn't yet doing that it will do to make llvm be able to optimize it better as well.

the primary reason THIS code didn't optimize as well is that you can't pass ffast-math to llvm from rust in any useful way (yet)

Re: Rust and C++ on Floating-Point Intensive Code

#63
post #50

Earlier quoted context omitted.

Hum, did the program get vectorized?

As I said, the compiler did generate FMA instructions. These are SIMD instructions, so yes, the program was vectorized.

it isn't always that simple. FMA instructions are tricky to use in a way that actually improves performance, llvm may be doing it right while doing it manually that way may not.

also, sometimes a SIMD instruction is used but only on 1 lane at a time. this is actually common with floating point code.

Re: Rust and C++ on Floating-Point Intensive Code

#64
post #60

Earlier quoted context omitted.

Hum, did the program get vectorized?

You can see the full compiler output here: https://rust.godbolt.org/z/FbDqye

Thanks. It seems that at least parts of the inner loop have been vectorized. Edit: If Im reading the asm correctly, the second zip has been vectorized, but the first fold was not.

Re: Rust and C++ on Floating-Point Intensive Code

#65
post #50

Earlier quoted context omitted.

As I said, the compiler did generate FMA instructions. These are SIMD instructions, so yes, the program was vectorized.

it isn't always that simple. FMA instructions are tricky to use in a way that actually improves performance, llvm may be doing it right while doing it manually that way may not. also, sometimes a SIMD instruction is used but only on 1 lane at a time. this is actually common with floating point code.

What do you mean "manually" ? `mul_add` is a rust function that operates on a single f64, it's still up to LLVM to choose which instructions to use and to do the vectorization.

Re: Rust and C++ on Floating-Point Intensive Code

#66

Earlier quoted context omitted.

I think the key issue with the optimizations that ICC is performing for C++ but Rust is not doing in this case is just FP-contraction, which is related to, but not the same as, assuming associativity. The RFC about that is https://github.com/rust-lang/rfcs/pull/2686 , where you see users kind of split into the "I want faster binaries" and "I want more deterministic execution" camps. Neither are wrong TBH. Some people…

> I think the key issue with the optimizations that ICC is performing for C++ but Rust is not doing in this case is just FP-contraction, which is related to, but not the same as, assuming associativity. I think associativity is necessary to vectorize reduction operations like: r+=(c[i]-a[i]*b[i])*a[i]*(c[i]-a[i]*b[i]); I haven't looked at the code generated by ICC, but I would expect it to vectorize this by computing…

Yes, you are right, for those reduce operations you need associativity.

Re: Rust and C++ on Floating-Point Intensive Code

#67
post #50

Earlier quoted context omitted.

Hum, did the program get vectorized?

As I said, the compiler did generate FMA instructions. These are SIMD instructions, so yes, the program was vectorized.

> yes, the program was vectorized

"The program" contains two hot loops. Judging from the assembly code you linked in a sibling comment, only the second of these loops was vectorized, the first one wasn't. This slower non-vectorized loop will still dominate execution time.

And for whatever it's worth, dropping the original article's

            for i in 0..n{
                b[i]=b[i]+(r/beta)*(c[i]-a[i]*b[i])
            }
in place of your loop using iterators and FMA, you still get nicely vectorized code (though without FMA) for this loop:

    .LBB6_120:
        vmovupd zmm2, zmmword ptr [r12 + 8*rcx]
        vmovupd zmm3, zmmword ptr [r12 + 8*rcx + 64]
        vmovupd zmm4, zmmword ptr [r12 + 8*rcx + 128]
        vmovupd zmm5, zmmword ptr [r12 + 8*rcx + 192]
        vmovupd zmm6, zmmword ptr [r14 + 8*rcx]
        vmovupd zmm7, zmmword ptr [r14 + 8*rcx + 64]
        vmovupd zmm8, zmmword ptr [r14 + 8*rcx + 128]
        vmovupd zmm9, zmmword ptr [r14 + 8*rcx + 192]
        vmulpd  zmm10, zmm2, zmmword ptr [rbx + 8*rcx]
        vsubpd  zmm6, zmm6, zmm10
        vmulpd  zmm10, zmm3, zmmword ptr [rbx + 8*rcx + 64]
        vsubpd  zmm7, zmm7, zmm10
        ...
Neither FMA nor iterators make a difference for whether this loop is vectorized, so any speedups are necessarily limited.

Re: Rust and C++ on Floating-Point Intensive Code

#68
post #29

Earlier quoted context omitted.

The one very important thing that often get destroyed by compiler using associativity is the TwoSum Error free transform which is a vital composant of several algorithms that deal with numerical error (most notably the Kahan Summation). The problem is mentionned in the Wikipedia page of the Kahan summation (and I have been able to reproduce it with gcc) : https://en.wikipedia.org/wiki/Kahan_summation_algorithm#Poss..…

I think the key issue with the optimizations that ICC is performing for C++ but Rust is not doing in this case is just FP-contraction, which is related to, but not the same as, assuming associativity. The RFC about that is https://github.com/rust-lang/rfcs/pull/2686 , where you see users kind of split into the "I want faster binaries" and "I want more deterministic execution" camps. Neither are wrong TBH. Some people…

For the error free transform, the important part is the associativity and not the fusion (which would not degrade the operation).

As illustrated in the Wikipedia page, if move terms according to associativ rules you can show that one of the term is always zero and conclude that it is useless, dropping it from the computation.

However, in practice, floating-points are not associativ and that term contains the numerical error of the previous operation.

Re: Rust and C++ on Floating-Point Intensive Code

#69
post #16

Earlier quoted context omitted.

> I'm also partial to exposing it per-function so the control is actually in the hands of the people writing the code that know the context As a C++ programmer who routinely uses fast-math "until something breaks" with DSP code, I would find that capability very attractive.

That's kind of at odds with Rust guarantee that your code never breaks.

Technically Rust only guarantees memory-safety (and only outside of unsafe!{}). It has many features that aid in other kinds of safety - strongly encouraging you to unwrap Option and Result, requiring all match cases to be covered, allowing for lots of strategic immutability, etc. But it doesn't guarantee that kind of correctness.
Post reply on HN