Live data from Hacker News

Beating the compiler

roguelazer.com

21–30 of 46 posts

Re: Beating the compiler

#21

On the general topic of how much we can rely on compilers, even using old and well-understood languages (C++), consult Mike Acton: http://www.slideshare.net/cellperformance/gdc15-code-clinic https://www.youtube.com/watch?v=rX0ItVEVjHc

C++ is well-understood? I don't get that impression from people who know it.

Re: Beating the compiler

#22
post #12

> What's the point of micro-optimizing a 3ms function call when each request spends 8 or 9 seconds inside the SQLAlchemy ORM? Well, sometimes it's nice to practice those optimizion skills anyway I have a different opinion on those 3ms optimizations: "It all adds up" Stopping at one 3ms optimization is not going to move mountains. But doing that 10 times is already 30ms. Imagine that you found 100 micro optimizations.…

I'm a massive fan of this sort of 'large-scale micro' optimization. There's a big difference between premature optimization, and having heaps of little sticking points in your project.

One of my favorite examples is Ubuntu - they run their 'One Hundred Papercuts' program [1], which is about fixing and optimizing little things that on their own would never get fixed, but together they are more than the sum of their parts in terms of user experience.

[1] https://wiki.ubuntu.com/One%20Hundred%20Papercuts

Re: Beating the compiler

#23
post #12

> What's the point of micro-optimizing a 3ms function call when each request spends 8 or 9 seconds inside the SQLAlchemy ORM? Well, sometimes it's nice to practice those optimizion skills anyway I have a different opinion on those 3ms optimizations: "It all adds up" Stopping at one 3ms optimization is not going to move mountains. But doing that 10 times is already 30ms. Imagine that you found 100 micro optimizations.…

I'm a massive fan of this sort of 'large-scale micro' optimization. There's a big difference between premature optimization, and having heaps of little sticking points in your project. One of my favorite examples is Ubuntu - they run their 'One Hundred Papercuts' program [1], which is about fixing and optimizing little things that on their own would never get fixed, but together they are more than the sum of their pa…

My favourite recent example was SQLite, where hundreds of micro-optimizations led to version 3.8.7 to be 50% faster than 3.7.17.

http://permalink.gmane.org/gmane.comp.db.sqlite.general/9054...

Re: Beating the compiler

#24
post #5

Er. Author missed a crucial point of "just" using PyPy: for me it's over 24x speedup over standard python (if you run it enough times for JIT to warmup). Know your tools

For that matter, his numpy code, which wasn't described until the comments, was terrible. Unlike all the other versions, it included a complete reallocation, conversion and copying step, which accounted for almost the entire processing time.

People in the comments who tried a reasonable numpy version found it to be around the same speed as the unoptimized C version.

Re: Beating the compiler

#25
post #4

Earlier quoted context omitted.

All the author had to to was to add '-march=native' or '-march=core-avx2' to the compiler command line: http://goo.gl/H4f62I

Clang 3.7.0 (experimental) + -march=skylake gives you AVX512. zmm all the way, baby! 256 bytes processed in the inner loop!

But what gives me a Skylake CPU?

Re: Beating the compiler

#26
post #16
post #6

Earlier quoted context omitted.

Rather than inline ASM, wouldn't it be better to have a maker that says "error if this can't be vectorised"? Something analogous to Scala's @tailrec

I've been thinking about that for the last few days, and I think that's the best solution, if it's possible. Optimizations might clutter up the code and make the intent not clear. Writing idiomatic code and hoping that the compiler figures it out is also suboptimal, as noted by the grandparent. I think the best solution is to be able to make some kind of annotation, or other way of declaration, on a function that say…

In my experience, I always write a clear, idiomic C code along with my intrinsics-based vectorized function, alo png with comment on tricky part (such as using packus for clamping thing to 0-255). You got clear code, and also optimized code (you might want C code anyway for pre-sse2/mmx and non-x86). Downside is that you are to maintained multiple copy of code, but if you have the version optimized for each sse2/sse3/sse4.1/avx2 anyway it is not really that more hassle.

Re: Beating the compiler

#27
post #12

> What's the point of micro-optimizing a 3ms function call when each request spends 8 or 9 seconds inside the SQLAlchemy ORM? Well, sometimes it's nice to practice those optimizion skills anyway I have a different opinion on those 3ms optimizations: "It all adds up" Stopping at one 3ms optimization is not going to move mountains. But doing that 10 times is already 30ms. Imagine that you found 100 micro optimizations.…

The cost of maintaining your optimized code adds up too. As does the risk that you introduced a bug. And this takes time away from newer features that customers might be willing to pay money for.

Occasionally performance is a feature, but a lot of times it's just an excuse for developers to have fun writing assembly.

Re: Beating the compiler

#28
post #23

Earlier quoted context omitted.

I'm a massive fan of this sort of 'large-scale micro' optimization. There's a big difference between premature optimization, and having heaps of little sticking points in your project. One of my favorite examples is Ubuntu - they run their 'One Hundred Papercuts' program [1], which is about fixing and optimizing little things that on their own would never get fixed, but together they are more than the sum of their pa…

My favourite recent example was SQLite, where hundreds of micro-optimizations led to version 3.8.7 to be 50% faster than 3.7.17. http://permalink.gmane.org/gmane.comp.db.sqlite.general/9054...

Here's the associated HN discussion thread: https://news.ycombinator.com/item?id=8420274

Re: Beating the compiler

#29
post #17
post #6

Earlier quoted context omitted.

Rather than inline ASM, wouldn't it be better to have a maker that says "error if this can't be vectorised"? Something analogous to Scala's @tailrec

Again, inline ASM is pretty rare these days (when we do use it, it isn't for SIMD). Intrinsics are much more common. The big issue (aside from convincing MSVC to implement it ;) with your suggestion is that, unlike TCO, vectorization isn't really a boolean. There's a range of what vectorization might mean (you can vectorize code and do a bad job with it, only marginally beating out the scalar code), so you'd still ne…

Writing SSE code using compiler intrinsics is indeed a fun puzzle, but it has huge drawbacks: 1) it's Intel-specific, and 2) it's a maintenance risk unless everyone in the shop knows how to write and maintain SSE code. Unfortunately nobody else at my job knows how to do it, so I am not allowed to check any in :(

Re: Beating the compiler

#30
The first instance of 8 way unrolling

    loop:
        acc += A
        acc += B ...
was inefficient because each add instruction is dependent on the one before it. The CPU has to pause constantly to wait for the result in acc in order to continue.

The correct way to do this is to have 8 accumulators (or whatever the loop unrolling depth is) and then to sum those together at the end. This helps to keep the processor's pipelines full.

    loop:
        acc1 += A
        acc2 += B
    
    acc = acc1 + acc2
The author's use of SIMD instructions is even better still, where multiple variables were used. However intrinsics would have been far more readable.

For further speed improvements, streaming intrinsics (since all reads are only done once, and never written to) could be useful. Also OpenMP for multithreading would be a good fit here.

Post reply on HN