3 ms·
Yes, I support your sentiment. On the topic, in C# (*), it is currently strongly recommended to rewrite any code that used to rely on specific ISA and ISA exte
by neonsunset 3y ago
Yes, I support your sentiment.
On the topic, in C# (*), it is currently strongly recommended to rewrite any code that used to rely on specific ISA and ISA extensions (SSE4.2, AVX, NEON) to cross-platform methods on `Vector128/256/512<T>` and `Vector<T>` themselves.
Also, .NET is getting support for SVE2 now on top of `Vector<T>`, which is nice.
* Which has proper portable SIMD API, unlike Java panama vectors in their current shape (codegen and API limitations makes them currently an unsuitable counterpart)
- astrange 3y agoIs it strongly recommended by people who've successfully written performant software on multiple platforms (like ffmpeg), or by compiler engineers? Because this is the kind of thing compiler engineers would like to believe is true, but in practice isn't unless you have the power to make them fix it for you. There are actual differences between ISAs here and if your case deoptimizes on one of them then there wasn't a point in using SIMD at all. (Examples: whether it has a full permute, whether unaligned loads are fast or unusably slow, whether it supports half-floats.) And of course nobody can do an abstraction for MMX, so they just pretend it doesn't exist.
- neonsunset 3y agoThe quote reads as "In C#, it is recommended..." Which means that, in the past, C# did not have cross-platform SIMD abstractions aside from a very limited set of arithmetic operations on Vector<T> so that manually vectorized code had to rely on SIMD intrinsics introduced earlier (AVX2, AdvSimd, etc.). However, .NET 7 introduced a set of common arithmetic, logical and bitwise operations on Vector128/256/512<T>[0] (VectorXXX are common vector width types that used to be consumed by intrinsic APIs exclusively), and subsequently both 7 and 8 also included QoL improvements for more high-level Vector<T>. This change rendered the code that duplicated SIMD paths per-platform mostly obsolete save for certain operations like `Shuffle` (which then got addressed by introducing ShuffleUnsafe which is just a raw platform-specific shuffle with the expectation that the users will account for those manually, or the set of outputs they care about has sufficiently common behavior everywhere). CoreLib itself relies on these APIs now and there is no reason to use platform-specific intrinsics in most situations over cross-platform API. Now, one of the reasons .NET can do this is because it does not have to target such a wide range of platforms regular C code has to deal with: most code out there only ever cares about x86, x86_64 (multiple flavors due to SSE2/4, AVX/2 and AVX512), armv7, armv8a and now also wasm (with packed SIMD), and maybe riscv in the future. Out of those, x86_x64 and armv8a receive most attention and performance investment, which are sufficiently similar save for movemask workhorse emulation of which is suboptimal (community has learned vshrn[1] and other tricks for common operations since then to avoid the issue). With that said, C++ has its own experimental cross-plat SIMD abstraction, and there are many high-quality frameworks that allow to abstract away writing SIMD code manually completely. There is also a Rust crate[2] that offers C#-style SIMD abstraction, so it's not exclusive to C# (or particularly difficult in systems programming languages) but C# is probably the one and only high-level language to offer it with an assurance to emit good codegen (unless you abuse it too hard). [0] https://github.com/dotnet/runtime/blob/main/docs/coding-guidelines/vectorization-guidelines.md https://github.com/dotnet/runtime/blob/main/docs/coding-guid... [1] https://github.com/U8String/U8String/blob/main/Sources/U8String/Helpers/VectorExtensions.cs#L143-L156 https://github.com/U8String/U8String/blob/main/Sources/U8Str... [2] https://github.com/Lokathor/wide https://github.com/Lokathor/wide