3 ms·
Major omission from this article: vector extensions. GCC (and Clang) allows having first class SIMD vector values and use standard operators (+, -, *, /) to ope
by exDM69 14y ago
Major omission from this article: vector extensions. GCC (and Clang) allows having first class SIMD vector values and use standard operators (+, -, *, /) to operate on them. This makes writing computer graphics and other 3d stuff a lot nicer.
Like this:
typedef float vec4 __attribute__((vector_size(16)));
vec4 a = { 1, 2, 3, 4 }, b = { 5, 6, 7, 8 };
vec4 c = a + b;
What GCC does not allow (IIRC) is GLSL/OpenCL -style shuffle syntax like position.xyzw or (vec4)(a.xx, b.yy). Clang has __builtin_shufflevector but GCC doesn't have anything like it and you have to revert to SIMD intrinsics for SSE, NEON, etc.
Interesting thing about shuffles: Clang's implementation of ARM NEON intrinsics actually defines NEON shuffle intrinsic functions using a __builtin_shufflevector. I've noticed that Clang emits a lot better NEON code than GCC does. GCC's NEON backend is a lot worse than the SSE backend. And shuffle instructions are a major difference between NEON and SSE.
- anonymous 14y agoCan you give an example where such shuffle instructions are useful? I'm genuinely curious.
- klodolph 14y agoIf you think of processors as plumbing, shuffle operations are like pipes: they put the data in the right place for other operations. General shuffle operations let you do things like convert RGB data to RGBA data without trouble. Shuffling is a more flexible version of the more common pack, unpack, and bytewise shift operations.
- jandrewrogers 14y agoThe shuffle instructions are commonly used when encoding or decoding integer serialization formats or processing integer arrays. It can also be a fast intermediate operation for some bit-twiddling algorithms, which would require multiple sequential operations to achieve an equivalent distribution of bits for processing. If you are not working on high-performance bit-twiddling algorithms then you will probably have limited use for shuffle intrinsics. For those applications, it can save a few clock cycles for each call relative to more naive methods.
- CountHackulus 14y agoCross product is a good example: (v1.yzx * v2.zxy) - (v1.zxy * v2.yzx)
- exDM69 14y agoShuffles are what makes SIMD go. It's trivial to make simple repeated math ops done in parallel instead of 4 (SIMD vector width) times sequentially, but shuffling vectors cleverly is where you can get big performance wins. Basic example, doing addition of 4 values in 2 ALU operations: vec4 sum(vec4 v) // return v.x+v.y+v.z+v.w repeated 4 times { vec4 temp = v + v.yxzw; return temp + temp.zwxy; // did I get this right? } Practical examples: https://github.com/rikusalminen/threedee-simd https://github.com/rikusalminen/threedee-simd (work in progress) Requires this: http://gruntthepeon.free.fr/ssemath/ http://gruntthepeon.free.fr/ssemath/