Most efficient binary (energy wise)

What would produce the most energy efficient binary? Small or fast? I get that fast will try to produce as fewer instructions as possible but those might be consuming more energy (AVX512). I guess a combination of fast and targeting lower CPU specs?

All this might depend more on the CPU than the compiler anyway.

7 Likes

That is a very interesting question indeed. None of the optimization modes perfectly align with the goal of energy efficiency, even though fast is quite close to it.

I think, in general, it is a reasonable heuristic that fast mode is also efficient mode because usually to be fast is also to be efficient (Power divided by Work); if you are using more power (numerator), you’re also crunching the data faster (denominator). However, there are exceptions as you pointed out.

I suspect that, in the real world, the best way to achieve energy efficiency is to choose a chip designed for such things, and optimize for fast mode, in which case those use cases will perfectly align.

Let’s keep an eye on this use case, however. I could see a world in which this makes sense as an additional optimization mode.

9 Likes

In practice this is a very under-researched area. You probably just have to go and measure it.

Maybe ask the KDE devs, they have some experience with that.

3 Likes

Not entirely unexplored. I spent several weeks figuring out what I needed to do to make a Raspberry Pi run as fast as possible while using as little energy as possible.

I discovered that fast mode has the lowest power consumption. But that’s not enough. You also have to ensure that the memory is used optimally, or rather, that the cache is properly filled. Only this combination leads to success. In principle, nothing new, and it’s been covered in various presentations, among other things.

But implementing it correctly in practice is more difficult than expected. And without the massive use of perf, I wouldn’t have figured it out.

For example, if you apply an FFT to, say, a 30 ms iq16 recording, it will be slow and consume a lot of power. This is because with 30 ms = 1,843,200 samples, you get an unfavorable radix factoring that cannot be loaded optimally.

But with 30.52 ms = 1875000 samples, several blocks can be combined to a radix-5 size, and although 0.5 ms more is recorded, the FFT is over 12 ms faster and therefore consumes less power.

This is only meant to roughly illustrate that it is not enough to simply set ‘-O ReleaseFast’, which is basically the right approach, but parallelization - i.e. SIMD - must also be considered, which only works if the CPU does not have to wait for the data it is supposed to calculate.

6 Likes

My understanding is that what’s most important is completing your work quickly and not using unnecessary CPU time (for example, by busy-waiting instead of using a futex to get woken up by the OS), so the processor can return to lower power states.

Depending on what you’re targeting, you may also need to turn parts of a microcontroller off and on (“power management”), by turning only the parts you use on when you use them, you can save power. Microcontrollers will usually also have peripheral-specific power optimizations.

It’s an interesting topic, and one I’ve also been pondering with my PinePhone project, where power efficiency is a high priority.

For example I’ve got 4 cores avail, and although I was tempted to offload some work to other cores, I think it is probably more energy efficient to stick to a single core, or maybe even shuffling between cores to keep them cool. Currently I can get away with single threaded code, and it’s allocation free, which probably also helps. Maybe on a more modern SoC you’d also be trying to target specific low power cores, or running some stuff in 32bit mode vs aarch64. I’m not sure where you’d start in building a compile mode to target such decisions.

At least for my project (currently small), I imagine a new compile mode wouldnt make much difference, these CPUs are so fast anyway, and most of the power is probably used by peripherals. Although I did get a nice win switching to a ‘WFI’ (wait for interrupt) based event loop. That got me down from 63C down to a steady 42C. And as always with such topics, profiling is key.

1 Like