Earlier quoted context omitted.
Maybe you can use chunks_exact() and chunks_exact_mut(). The _exact versions allow lifting the bounds checks out of the loop and gave me some great performance boosts in image processing code.
These blocks are non-continuous. It operates over a part of a row, where the start of the next row is the start of the current row + some stride. I mean maybe? But I probably wouldn't anyway for this case as a slice reference is actually a "fat" pointer (ie twice the size of a normal pointer) and the length of the slice won't be used (the block size is known per kernel); LLVM might delete the length part anyway. Thes…
Rust and C++ on Floating-Point Intensive Code
51–60 of 95 posts
Re: Rust and C++ on Floating-Point Intensive Code
#52Re: Rust and C++ on Floating-Point Intensive Code
#53What's "almost" algebraic about enum? It can definitely be used to construct sum types, and you can make product types with struct or inline in an enum
enum List {
Nil,
Cons(T, List)
}
instead, you have to box/reference-ify the recursive occurrence: enum List {
Nil,
Cons(T, Box>)
}
so in certain circumstances it doesn't let you "coproduct" two types together, you might need to modify one a bit, which makes it a technically-not-exactly-a-coproduct (i think). a bit of a stretch but it sort of makes sense next to a by-reference-only ML langs where you can (co)product anything as you please(btw, it's the same for recursive products)
---
1 - https://users.rust-lang.org/t/recursive-enum-types/2938/2
Re: Rust and C++ on Floating-Point Intensive Code
#54What's "almost" algebraic about enum? It can definitely be used to construct sum types, and you can make product types with struct or inline in an enum
my best guess is that you can't do recursive enums without explicit boxing [edit: or other forms of indirection, like &T]¹. so you can't do this: enum List { Nil, Cons(T, List ) } instead, you have to box/reference-ify the recursive occurrence: enum List { Nil, Cons(T, Box >) } so in certain circumstances it doesn't let you "coproduct" two types together, you might need to modify one a bit, which makes it a technical…
Re: Rust and C++ on Floating-Point Intensive Code
#55What's "almost" algebraic about enum? It can definitely be used to construct sum types, and you can make product types with struct or inline in an enum
my best guess is that you can't do recursive enums without explicit boxing [edit: or other forms of indirection, like &T]¹. so you can't do this: enum List { Nil, Cons(T, List ) } instead, you have to box/reference-ify the recursive occurrence: enum List { Nil, Cons(T, Box >) } so in certain circumstances it doesn't let you "coproduct" two types together, you might need to modify one a bit, which makes it a technical…
Re: Rust and C++ on Floating-Point Intensive Code
#56Earlier 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.
Re: Rust and C++ on Floating-Point Intensive Code
#57What's "almost" algebraic about enum? It can definitely be used to construct sum types, and you can make product types with struct or inline in an enum
my best guess is that you can't do recursive enums without explicit boxing [edit: or other forms of indirection, like &T]¹. so you can't do this: enum List { Nil, Cons(T, List ) } instead, you have to box/reference-ify the recursive occurrence: enum List { Nil, Cons(T, Box >) } so in certain circumstances it doesn't let you "coproduct" two types together, you might need to modify one a bit, which makes it a technical…
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.Re: Rust and C++ on Floating-Point Intensive Code
#58Earlier 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.
This should probably be exposed as separate floating point types. With relatively cheap conversions. (Mostly done error checks.)
Floating point code is really difficult to do correctly. LLVM doesn't actually model IEEE 754 correctly yet, although hopefully the remaining issues with the constrained intrinsics will be fixed by the end of the year (even then, sNaN support is likely to still be broken for some time).
What makes floating point more difficult than integers is two things. First, there is an implicit dependency on the status register that greatly inhibits optimization, yet very few users actually care about that dependency. The second issue is that there is many more properties that matter for floating point. For an integer, you essentially only care about three modes: wrapping (w/ optional carry flag), saturating, and no-overflow. Exposing these as separate types exhaustively is easy. For floating point, you have orthogonal concerns of rounding mode (including dynamic), no-NaN, no-infinity, denormals (including flush-to-zero support), contraction to form FMA, reciprocal approximation, associative, acceptable precision loss (can I use an approximate inverse sqrt?), may trap, and exception sticky bits. Since they're orthogonal, that means that instead of a dozen types, you need a few thousand types to combine them, although many combinations are probably not going to be too interesting.
Re: Rust and C++ on Floating-Point Intensive Code
#59Earlier quoted context omitted.
my best guess is that you can't do recursive enums without explicit boxing [edit: or other forms of indirection, like &T]¹. so you can't do this: enum List { Nil, Cons(T, List ) } instead, you have to box/reference-ify the recursive occurrence: enum List { Nil, Cons(T, Box >) } so in certain circumstances it doesn't let you "coproduct" two types together, you might need to modify one a bit, which makes it a technical…
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.
Re: Rust and C++ on Floating-Point Intensive Code
#60It looks like what the author was looking for is [1] f64::mul_add(self, a: f64, b: f64) -> f64 Adding it to the code indeed allows the LLVM to generate the "vfma" instruction. But it didn't significantly improve performance, on my machine at least. $ ./iterators 1000 Normalized Average time = 0.0000000011943495282455513 sumb=89259.51980374461 $ ./mul_add 1000 Normalized Average time = 0.0000000011861410852805122 sumb…
Hum, did the program get vectorized?