Odd that c# has a better stable SIMD story than Rust! It has both generic vector types across a range of sizes and a good set of intrinsics across most of the common instruction sets
Why would that be odd? C# is an older and mature language backed by a corporation, while Rust is younger and has been run by a small group of volunteers for years now.
> hile Rust is younger and has been run by a small group of volunteers for years now
I thought Rust was getting financial support from Google, Microsoft and Mozilla? Or was the Rust Foundation just a convenient way for Mozilla to fire a large amount of developers and we are actually rapidly approaching the OpenSSL Heartbleed state. Where everyone is happily building on a secure foundation that is maintained by a half dead intern when he isn't busy begging for scraps on the street?
C# portable SIMD is very nice indeed, but it's also not usable without unsafety. On the other hand, Rust compiler (LLVM) has a fairly competent autovectorizer, so you may be able to simply write loops the right way instead of the fancy API.
Unsafety means different things. In C#, SIMD is possible via `ref`s, which maintains GC safety (no GC holes), but removes bounds safety (array length check). The API is called appropriately Vector.LoadUnsafe
Having worked in HPC a fair bit I'm not a fan of autovectorization. I prefer the compiled code's performance to be "unsuprising" based on the source and to use vectors etc where I know it's needed. I think in general it's better to have linting that points out performance issues (e.g. lift this outside the loop) rather than have compilers do it automatically and make things less predictable
You can write good autovectorized code in Rust today, but only for integers. Since Rust lacks --ffast-math, the results on most fp code are disappointing.
You are not "forced" into unsafe APIs with Vector<T>/Vector128/256/512<T>. While it is a nice improvement and helps with achieving completely optimal compiler output, you can use it without unsafe. For example, ZLinq even offers .AsVectorizable LINQ-style API, where you pass lambdas which handle vectors and scalars separately. It the user code cannot go out of bounds and the resulting logic even goes through (inlined later by JIT) delegates, yet still offers a massive speed-up (https://github.com/Cysharp/ZLinq?tab=readme-ov-file#vectoriz...).
Yeah, golang is a particular nightmare for SIMD. You have to write plan 9 assembly, look up what they renamed every instruction to, and then sometimes find that the compiler doesn't actually support that instruction, even though it's part of an ISA they broadly support. Go assembly functions are also not allowed to use the register-based calling convention, so all arguments are passed on the stack, and the compiler will never inline it. So without compiler support I don't believe there's any way to do something like intrinsics even. Fortunately compiler support for intrinsics seems to be on its way! https://github.com/golang/go/issues/73787
To be fair, Java's lack of support seems to have more to do with them needing to fix the whole primitive vs object mess rather than a lack of effort. It sounds like the Vector API will be stabilized shortly after they figure that out, but who knows how long it will take.
If anything, the Mono runtime is what prevents heavier (ab)use of SIMD types in the standard library, or at least it causes additional required effort to make it not regress in performance since it's nowhere near as capable as CoreCLR.
kelnos|3 months ago
josefx|3 months ago
I thought Rust was getting financial support from Google, Microsoft and Mozilla? Or was the Rust Foundation just a convenient way for Mozilla to fire a large amount of developers and we are actually rapidly approaching the OpenSSL Heartbleed state. Where everyone is happily building on a secure foundation that is maintained by a half dead intern when he isn't busy begging for scraps on the street?
booi|3 months ago
bencyoung|3 months ago
exyi|3 months ago
buybackoff|3 months ago
bencyoung|3 months ago
Tuna-Fish|3 months ago
neonsunset|3 months ago
Another example, note how these implementations, one in unsafe C# and another in safe F# have almost identical performance: https://benchmarksgame-team.pages.debian.net/benchmarksgame/..., https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
jiehong|3 months ago
ashf023|3 months ago
soupy-soup|3 months ago
pjmlp|3 months ago
fulafel|3 months ago
Eg https://tirania.org/blog/archive/2008/Nov-03.html
neonsunset|3 months ago
You can find the overview of relevant high-level types here: https://learn.microsoft.com/en-us/dotnet/standard/simd
For low-level types and historical context: https://devblogs.microsoft.com/dotnet/dotnet-8-hardware-intr...