9
\$\begingroup\$

I am a software engineer concerned about current draw.

I am aware that there are ways to reduce the current draw of a program, for example:

  • using a hlt instruction which disables the CPU until the next interrupt

  • maybe avoiding floating point so that the FPU doesn't get jiggled

I'm wondering if it's possible to estimate the current draw of a single instruction, so that a theoretical compiler can select the instruction which will draw less power. Existing compilers can normally optimise for speed or for size, but I have never see a compiler which can optimise for current draw. Maybe no-one's considered it, maybe no-one's done the research into every single instruction, maybe it's actually impossible.

But consider for example some NMOS processor like the early 6502s. By my intuition, subtracting 0xff from 0xff would draw more power than subtracting 0x01 from 0x01 because I think the inputs to the ALU need to be precharged more or something. But knowing next to nothing about electronics I'd appreciate if someone could tell me if

a) my intuition is correct

b) it's practical to estimate the current draw of a CPU instruction if you know what state the CPU's in, so that you know exactly what the instruction is doing.

\$\endgroup\$
10
  • 1
    \$\begingroup\$ By my intuition, the best instruction is the one that does the least computation. Perhaps subtracting 0xff from 0xff uses a tiny bit more power, but arranging things so that you try to subtract 0x01 from 0x01 uses even more power still! \$\endgroup\$
    – user20574
    Commented Aug 13, 2021 at 14:40
  • 8
    \$\begingroup\$ No one is doing it, even the major CPU manufacturers for their embedded firmwares and microcode, and believe me, power consumption is a serious concern there. Instead they focus on overall power consumption and identifying "bottlenecks" (in terms of power) and trying optimize these. Pretty much the same as no one is doing micro-optimizations for speed or size on instruction levels, but instead optimizing bottlenecks. \$\endgroup\$
    – Eugene Sh.
    Commented Aug 13, 2021 at 14:50
  • 4
    \$\begingroup\$ Moreover, imagine that you have came up with such a compiler for, say certain processor architecture, and determined that mov r0, 0 is more power hungry than xor r0, r0. Then tomorrow, the CPU manufacturer decided to change its hardware so that mov is now less power-consuming than xor and simply released this processor as a revision of the first one. This will effectively invalidate your compiler effort. \$\endgroup\$
    – Eugene Sh.
    Commented Aug 13, 2021 at 14:53
  • 12
    \$\begingroup\$ The goal should be to get your code to run as fast as possible so the CPU can get into lower power sleep modes as fast as possible. Sleep modes will consume much less than what you could ever get by choosing "lighter" instructions. \$\endgroup\$
    – Mat
    Commented Aug 13, 2021 at 15:02
  • 2
    \$\begingroup\$ @OmarL The approach being taken is to shut down sections that aren't being used. This includes clock chains. Most MCUs have peripherals, voltage references, analog to digital converters, digital to analog converters, and sub-timing chains, all of which can be turned off. In the ultimate, the entire processor can be shut off (including its only remaining clock) and left to detect only a pin-change. The CPU core itself doesn't vary so much by instruction, but much more by clocking instead. There may be small instruction differences, but I've never seen an analysis showing them. \$\endgroup\$
    – jonk
    Commented Aug 13, 2021 at 17:44

6 Answers 6

14
\$\begingroup\$

While this would be theoretically possible, I doubt if it could be done in practice in a way that a compiler could use the information in a modern processor. If you only want to do an academic exercise for a trivial processor you might have a chance.

You would need to characterize the power consumption for each instruction for all possible addressing modes (immediate operand, register operand, stack operand, etc.) and for all possible data values.

You would need to measure the energy used if the instruction is fetched from L1 cache, from L2 cache, and so forth. You would need to somehow separate the energy used to execute the instruction from the energy used to decode the next instruction in the pipeline, read the instruction before that from memory, and write the result of the previous instruction. All of these are happening simultaneously.

And keep in mind that compilers don't select instructions individually, they select groups of instructions that perform some desired high-level language operation.

Oh, and the manufacturer is free to change the manufacturing process at any time as long as the processor continues to meet its datasheet specifications. A small change in fabrication parameters could change the relative importance of leakage current, ac switching current, and transistor shoot-through current. So the data for one manufacturer's ARM A9 would not necessarily be of any value for another specific part number from the same manufacturer or an ARM A9 from another manufacturer.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ I think there's a middle ground you're overlooking. Something like a 6502 isn't exactly a "trivial processor", but it's still simple enough (and sufficiently well-understood) that characterizing the per-instruction energy usage should be possible. \$\endgroup\$
    – Mark
    Commented Aug 14, 2021 at 19:30
9
\$\begingroup\$

In a modern superscalar CPU with deep instruction pipelines, I'm not sure how easy it would be to even define the power consumption of a single instruction. Even if you could estimate the number of gates that switch for one instruction vs. another, manufacturing variations across the CPU die might make a larger difference. Furthermore, in earlier deep sub-micron processes (pre-FinFET) CPU power consumption is mostly static leakage current, not switching current.

In a simpler, lower-power system like a microcontroller, the CPU is not the only or even the most significant consumer of power. For example, an MCU that sleeps most of the time and wakes up periodically to transmit a wireless signal would spend most of its power on the radio transmission, not the CPU. Memories can also consume a lot of power, so running the CPU out of flash vs. RAM would make more of a difference than which instructions are executed. In low-power MCUs, whole peripherals and subsystems can have their clocks gated off when they're not in use. I don't think the tiny difference between instructions would matter compared to the time it takes to execute them, the memory usage, and the peripheral activity.

\$\endgroup\$
3
  • 5
    \$\begingroup\$ For what it is worth, static leakage is a pretty small fraction of modern CPU power post FinFETs. That is why Intel can sell the same architecture in 5w passive laptops as 200W desktops and why power consumption is changes only slightly with CPU temperature. It is almost all dynamic power. If it was leakage you wouldn't be able to do that, and you'd see your CPU power draw increase dramatically as the CPU heated up. \$\endgroup\$ Commented Aug 13, 2021 at 18:15
  • \$\begingroup\$ @user1850479: Don’t they run at different voltages which affects leakage a lot? If they use the same architecture but synthesize for a lower clock frequency they could also use low-leakage standard libraries for the laptop variant. It would also be interesting to compare power at different temperatures. \$\endgroup\$
    – Michael
    Commented Aug 14, 2021 at 12:57
  • 1
    \$\begingroup\$ Typo: "superscaler" should be "superscalar" \$\endgroup\$
    – psmears
    Commented Aug 16, 2021 at 9:54
5
\$\begingroup\$

It is done pretty much, see e.g. here (a random article about power efficiency). The interesting part is that, for the purpose of the analysis, the instruction "calorific value" is averaged over both the instruction set and the possible data streams.

For a simple CPU designs (without parallelisms, branch predictions, long pipelines, cache memory, etc...) one can even estimate the energy consumption of a particular instruction classes, e.g. data movement, addition/subtraction, multiplication, logical operations. Even then, one cannot be sure that a different implementation of the same instruction set will have the same (or even proportional) "power map".

And for a complex modern CPU it gets really hard, because the CPU really works on few instructions at once. In some cases, some of the work is even discarded because the execution path is not properly predicted. The cache memory, the RAM and other peripherals live their own life with DRAM refresh, i/o devices and the CPU competing to access the RAM chips and accessing adjacent memory cells may need more or less energy depending on how much distant are these cells in the physical silicon.

It boils down to that a single instruction may consume an orders of magnitude different amount of energy depending on what else the system does and what it did beforehand.

p.s. don't even start thinking that you may save energy by sparing a bit-flip in some register. In modern CPUs, a register is not a single place. It just pretends to be a single place where the programmer stores a value, because the CPU uses quite a complex logic to feed the proper value to the next instruction that tries to use it.

\$\endgroup\$
4
\$\begingroup\$

Existing compilers can normally optimise for speed or for size, but I have never see a compiler which can optimise for current draw.

Nowadays, the most effective power saving strategy is usually race to sleep. This means: run as fast as possible, so that you can turn off the whole CPU sooner. If you had a code sequence that could be done with 2 low-power instructions, or 1 high-power instruction, the second option would be better.

This is because static leakage currents form a large part of the energy usage, and they are the same irrespective of what instructions the CPU is executing. Only when the CPU is idle for a long enough time that its power supply can be turned off, can the static leakage be avoided.

The practical reason why race to sleep is not always possible is if CPU has to be kept operational to wait for some external event, or if turning it off and on takes too long time.

Some CPUs, like many ARM-based microcontrollers, can turn off individual functional units, such as FPU. Compilers for these platforms usually have an option to compile without FPU usage.

\$\endgroup\$
2
  • \$\begingroup\$ It's actually not that much about static leakage (for which you have to turn off the power supply). A significant fraction of the "idle" power draw of modern CPUs comes from functional units that are being clocked but don't have anything useful to do. The main power saving techniques are thus frequency scaling (when you have to keep something running, at least don't clock it needlessly fast) and aggressive clock gating (shut off clock chains that aren't being used at the moment). \$\endgroup\$
    – TooTea
    Commented Aug 14, 2021 at 11:49
  • \$\begingroup\$ @TooTea Yes, that is a factor also. But turning off the power supply to parts or whole CPU is also done and is very useful. \$\endgroup\$
    – jpa
    Commented Aug 14, 2021 at 12:22
3
\$\begingroup\$

I'm wondering if it's possible to estimate the current draw of a single instruction, so that a theoretical compiler can select the instruction which will draw less power.

Yes you can do this, but one has to simulate the processor on a transistor level. This type of simulation is usually only available to the manufacturer of the processor because they don't want to give out a copy of their design (because of potential intellectual property issues).

So what can you do about finding power?

The best tool avalible to most engineers is using a dev/eval board or prototype board and actually running the code on the processor and observing the differences in power. This may be challenging if you want to measure uA (instead of mA) you could buy (or build) an ammeter. The ammeter should be high bandwidth (above 1MHz) to resolve small current spikes, and an oscilloscope could be used to view the output.

\$\endgroup\$
1
\$\begingroup\$

Since you tagged the question as related to microcontrollers, I'll take a try.

a) my intuition is correct

Your intuition is correct in the sense that it might be possible to determine current draw, specially when dealing only with the instructions themselves. If I were to do it, I'd make a long program with many equal instructions, flash the microcontroller and then measure average current draw (easier to do with microcontrollers than with traditional computers). Then repeat for each instruction.

With a table of current draw per instruction, it should, theoretically, be possible to select, from the compiler options, the arrangements which have lesser draw (taking into consideration also the time taken to complete the operation sequence). Of course, this is very hardware-dependent, and you would have to do the measurements for each chip you use, or at least do transistor-level simulations for each.

To make matters worse, each physical chip has slight differences that may affect current draw, even changing your supposed table. There's no way your compiler can account for that, except if you're tailoring the compiler for a specific chip, or if you're only estimating measurements statistically.

From the compiler standpoint, it probably wouldn't make sense to do this for operands, since for most situations the compiler won't know the operands ahead-of-time, unless you're targeting very specific cases like zeroing a register (comment about that below).

The exception, of course, is if you're designing encryption software. For this case, current draw analysis is a known side-channel attack vector (see some studies. However, like all other cases, this is also very hardware-dependent, and encryption-focused hardware is designed to use the same current draw regardless of the operands, which defeats your whole idea.

b) it's practical to estimate the current draw of a CPU instruction if you know what state the CPU's in, so that you know exactly what the instruction is doing.

As explained, very maybe possible, but not practical, especially for a 32-bit microcontroller, and probably unfeasible if taking operand effects into account. Would your "state" also include every possible operand for every possible instruction? How much time does each experiment or simulation take? It might be feasible for a single chip only, or maybe if you are the chip manufacturer, or if the chip is also only theoretical.

subtracting 0xff from 0xff would draw more power than subtracting 0x01 from 0x01 because I think the inputs to the ALU need to be precharged more or something.

This is also very hardware-dependent. Remember that the classical x86 example to zero a register is to XOR it with itself. This is done regardless of the register value, and you probably can't select the value that's already in there.

As a final thought, consider that manufacturers already struggle to make each instruction use as little energy as possible. If compilers use faster sequences of instructions, they already spend less energy. If they reduce the time taken doing calculations, they can get to sleep earlier and reduce total energy. For example, using the hardware FPU might actually use less energy, since doing FP calculations in software takes much longer to complete. The only way to avoid it is by using fixed-point, but you don't want your compiler to make this kind of decision.

My conclusion is: while a nice thought experiment, I wouldn't pursue this idea.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.