3 ms·
> Where are you getting those numbers? I think situation is much more complicated, than your give it credit. I explained this upthread. Glibc apparently suppo
by anonymoushn 4y ago
> Where are you getting those numbers? I think situation is much more complicated, than your give it credit.
I explained this upthread.
Glibc apparently supports 4 distinct subsets of extensions for x64 according to this article about them removing a 5th one: https://www.phoronix.com/scan.php?page=news_item&px=Glibc-Dropping-SSSE3-Paths https://www.phoronix.com/scan.php?page=news_item&px=Glibc-Dr...
Most code isn't glibc and would be fine supporting just 2 distinct subsets of SIMD extensions for x64.
> See https://raphlinus.github.io/rust/simd/2018/10/19/fearless-simd.html https://raphlinus.github.io/rust/simd/2018/10/19/fearless-si...
I haven't looked into these Rust SIMD libraries much, but it sounds like they are doing worthwhile things. In 2022 you can also use Google's Highway if you are able to integrate template spaghetti into your code, but it's understandable if one cannot do this.
> It's still dropping down to assembly and having to worry about arcane details like endianess and byte alignment.
You don't have to write assembly. In Zig, you can just use binary and unary operators on vectors and get new vectors without using any intrinsics, but you'll still need to use more than 0 intrinsics for string parsing because you probably want pshufb. In the case of pshufb specifically, and this is representative of most of this stuff, the entirety of the complexity that you pay for having one AVX2 target and one SSE4.1 target is that the SSE4.1 target needs to get by with a half-as-wide pshufb. One way to do that (which might not be the best for all uses of pshufb on the SSE4.1 target) would be to write the wider pshufb in terms of the narrower one. Here it is:
extern fn @"llvm.x86.ssse3.pshuf.b.128"(a: u8x16, b: u8x16) u8x16;
pub inline fn shuffle16(a: u8x16, b: u8x16) u8x16 {
return @"llvm.x86.ssse3.pshuf.b.128"(a, b);
}
pub inline fn shuffle16x2(a: u8x32, b: u8x32) u8x32 {
const ret: [2]u8x16 = .{
shuffle16(@bitCast([2]u8x16, a)[0], @bitCast([2]u8x16, b)[0]),
shuffle16(@bitCast([2]u8x16, a)[1], @bitCast([2]u8x16, b)[1]),
};
return @bitCast(u8x32, ret);
}
simdjson's structural character indexer just uses a 64-byte-wide version of this operation, so that's 4 independent 16-byte-wide pshufbs, and it will be 4 instructions for SSE4.1, 2, for AVX2, or 1 for AVX-512, but if we do what I've suggested and don't have any particular support for AVX-512, it may end up being 2 there too.
Endianness is not arcane, but everything is little endian anyway. The penalties for unaligned access on the CPUs supporting the sets of extensions I've arbitrarily chosen are modest. You probably won't end up with a slow text editor just because your inner loops are frequently paying 1 cycle of latency for unaligned SIMD loads, but you can certainly fix that if you like.
> Is it? The more you use arcane features of code, the more computation you put out, and hence more heat.
Can you explain to Daniel Lamire that he is incorrect about this topic, and in fact it is more energy efficient to implement memcpy with 1-byte loads and stores than with wider ones? Thanks.
> I didn't say they do. I said they leverage CPU+GPU. And for average program to achieve the same, you need GPGPU.
Average programs want to compute many orders of magnitude less stuff than games though.