I noticed you couldn't optimize my code to use SIMD so I went ahead and used inline assembly. It will probably take another 30 years before you can actually think like a human and perform optimizations like this.
I noticed you couldn't optimize my code to use SIMD so I went ahead and used inline assembly. It will probably take another 30 years before you can actually think like a human and perform optimizations like this.
Yes, you can take a subroutine and apply local optimizations on it. Building complex software in assembly that on the whole is better optimized than what a compiler can do is next to impossible.
Speaking of SIMD and stuff like it, there are already optimizations that LLVM is doing, but such optimizations are hard to apply ahead of time because (1) if you want to distribute those binaries easily, then you need to compile for the common denominator (which is less of an issue with LLVM) and (2) your programming language sucks. It's not the compiler's fault, but rather your own fault that you're using a programming language so confusing that inferring intent from your code is next to impossible. How can the compiler know that you're sorting freaking numbers if you're specifying exactly how bits move around in memory while doing so?
If you're speaking about virtual machines though, there are projects out there for .NET or Scala for instance that can recompile/retarget code at runtime to run with SIMD instructions or on your GPUs if you have any. All you need is a virtual machine that runs bytecode and a programming language (slash compiler) that lets you access at runtime the syntax trees of the routines that you want to optimize and that lets you generate new bytecode. So you can easily shove this kind of optimizations in libraries for special-purpose and descriptive DSLs (e.g. LINQ).
Of course, it gets tricky and doing stuff like this at runtime has overhead, but it's better than what 99.99% of developers can do, not to mention that good developers first and foremost ship.
And that's the long-running argument for why high-level languages have the possibility to be compiled to faster code eventually. We are mostly still waiting for the languages and compilers. (Even though ghc gives us hope.)
So you go ahead and write clever SIMD code but please use the SIMD intrinsics I can understand, not inline assembler which I cannot do anything with. You are very good in expressing algorithms in a SIMD friendly way and do a decent job in instruction selection.
You, however, are not very good in doing instruction scheduling and register allocation, so let me handle that and we can achieve a result that can keep the CPU pipelines busy. When you make the tiniest change to the program, I can re-do instruction scheduling and register allocation in an instant, when that would take you hours to rewrite the whole algorithm to use different registers.
my point: SIMD intrinsics + a smart C compiler produces a lot better code than a programmer writing assembly. Clang + vector extensions in particular is very good at it.
I don't recall any specific paper, but I think tournament were played.
The compiler's output is far from useless, because compilers generally know a few tricks and/or cute sequences that you can copy. And using intrinsics is certainly better than relying on it to automatically vectorize things itself - I've never heard of that do anything remotely interesting. But, even though it's 2013, it still seems like the compiler is easier to beat by hand than you'd think.
I make no claim that this is worth doing in every case.
(As for the suggestion that the compiler can't rearrange inline assembly language, or provide symbolic register names - whyever not? Perhaps people have been conditioned by gcc and VC++ never to expect anything except the absolute bare minimum from inline assembly language support, but that's no reason to assume that these tasks are impossible. Code Warrior for Wii would rearrange assembly language for you to avoid holdups due to instruction latencies, and while automatically assigning registers for you. I believe most modern assemblers will do similar reordering and at least let you assign names to the registers you're using.)
I have picked up your clever optimized SIMD and decided it was better to change the execution order, because another unit was bored without nothing to do.
Unfortunately the L2 cache seems to have some issues getting all required data for your instructions due to the way all your threads are manipulating the required addresses from multiple cores.
You still beat them with inline assembly, but you probably won't accelerate the code vectorwidth times anymore.
ICC is the best one, but GCC from 4.0 could do it "automatically" (being very loose about the term)
And no one does inline assembly for that, they use intrinsics
Depends on your architecture. With ARM, compilers will often not set the alignment bits in vector loads and stores, and this can be a big performance hit depending on the microarchitecture. In general, compilers sometimes deal poorly with instructions that have particularly strange register constraints, or loads/stores with address writeback.
After all they need to provide reasons why you would buy them.
GCC got a 23% speedup vs 15% for XLC and 28% for ICC. GCC did well considering the proprietary compilers' narrow focus and corporate resources.
BTW, Fortran compilers for the 1980's supers did autovectorization pretty well. Funny that we've made it so hard today.
Unfortunately, the automatic vectorization compilers do is not very smart and is targeted at simple scalar loops in existing code bases. In many cases, a decent programmer can easily outperform the compiler with simple SIMD tricks, especially in cases where you can use clever vector shuffling tricks (e.g. sum of 4 numbers with 2 additions + 2 vector shuffles).
To get the best of both worlds, use compiler/machine specific intrinsic functions or vector extensions with a smart optimizing compiler. Clang's vector extensions work really well.
(sorry, I'm rusty in SIMD)
But remember, similar (old, but simpler) tricks were adopted by compilers, like xor to load 0, lea to do math (not sure about this one), shifts instead of multiply/divide etc
vec4 s1 = v + v.yxwz; // s1 = (v.x+v.y, v.y+v.x, v.z+v.w, v.w+v.z)
vec4 sum = s1 + s1.zwxy; // sum = sum of v
More practical examples, related to 3d graphics: https://github.com/rikusalminen/threedee-simdITYM "It will probably take another 30 years before I use a language that tells you what the required semantics of the code are, meanwhile I'll use my requirements interpretation privileges to relax the semantics in a few places"
I noticed that it takes forever to understand inline assembly. I don't foresee myself ever thinking like a computer and reading assembly as well as a high-level language.