We software engineers love to find the perfect solution to any problem we encounter. But oddly enough, we find that in this particular area, there is no perfect solution. Clever tricks may save some power, but this area is dominated by other simpler factors. There are several large elephants in the room, and we must carefully hunt the elephants we can see before spending energy hunting the smaller animals.
When considering the power consumption of a system, it is important to understand what we are actually measuring. When we say "saving power", we can mean several things. Does it mean "power" or "energy". In fact, we need both power and energy. Most handheld portable devices have two different budgets: a power budget - which manages the instantaneous power consumption to avoid overheating or thermal stress, and an energy budget, which manages the total amount of energy used in the long term. Software needs to meet both the short-term power budget and the long-term energy budget.
Obviously, we can reduce the power consumption of any device to nearly zero by not asking it to do anything or any meaningful operation! However, to perform useful functions requires energy consumption. Therefore, we can only make a constant compromise between meaningful operations and energy conservation. In order to perform the desired functions, we must consume energy; but we must try to ensure that these functions are performed in an energy-efficient manner.
Power-Time ProductA better metric commonly used in academic materials on the subject is the "power-time product." Although there are no standard units or specific methods, this metric combines energy and performance metrics. Increasing energy or decreasing performance increases the value of the power-time product, so the goal is to find the lowest acceptable power-time product value, in other words, the lowest energy consumption consistent with executing the required tasks in the allowed time.
Where does the energy go? All computing machines perform two basic functions. Both are necessary, and without them no meaningful task can be accomplished.
The first thing that comes to mind is computation or data processing. Computation is usually performed on values stored in machine registers. To perform computation as efficiently as possible, we need to execute the fewest instructions in the shortest amount of time. Most importantly, efficient computation allows us to choose between two options: either we can finish the computation early and go to sleep, or we can slow down the clock and still complete the computation in the required time.
What is often overlooked here is data communication (data movement). In most architectures (ARM uses a load/store architecture, and is no exception), data movement is a must. If the information is not moved from one location to another and often back to the original location, the user cannot process any information. For example, the value in memory needs to be moved to a register for processing, and then the result is written back to memory.
But which one uses more energy? Where is the biggest payoff?
Figure 1 shows the common fact that about 60% of program-related memory access operations are instruction fetches, and the remaining 40% are data accesses.
Figure 1: Memory access distribution
Figure 2: Memory access energy consumption
Figure 2 shows some research conducted by ARM. If the energy consumption of executing an instruction is 1, then the energy consumption of Tightly Coupled Memory (TCM) access is about 1/25, and the energy consumption of cache access is about 1/6. The energy consumption of external RAM access is 7 times the energy consumption of instruction execution.
In other words, for every external RAM access, we can execute 7 instructions, 40 cache accesses, or about 170 TCM accesses.
Computation is cheap but communication is expensive
So it seems that data movement is more expensive than data processing. So the first elephant is data efficiency.
We can propose two rules for managing the energy consumption of memory accesses.
Proximity - From an energy perspective, the closer the memory is to the core, the lower the relative energy cost of accessing the memory.
Fewer accesses - Reducing the number of memory accesses is more important than reducing the number of instructions.
Take advantage of on-chip memory
It is clear from our energy graphs that TCM is by far the most efficient type of memory a system has. Not all systems have what ARM calls TCM memory (connected to the core via a dedicated and optimized interface), but most have at least some type of fast memory on-chip. For the sake of discussion, we refer to this as a common on-chip memory (SPM). Given that a single access to an SPM consumes about 1/170 the energy of an external RAM access, making full use of this SPM memory should be the first choice.
Figure 3: Energy advantage of SPM
The graph in Figure 3 shows that for a simple “multi-class” benchmark, even a 128-byte SPM region can reduce power consumption by about half. A 1k-byte memory can reduce power consumption by up to 70%. The approach taken in this study (Mar wedel, 2004) is to dynamically relocate code and data segments from external RAM to SPM. Even in terms of moving the overhead on demand, not only does it reduce power consumption, but performance also improves by about 60%.
Clearly, we are losing returns at a certain point. This is where the performance gains slow down beyond 1k SPM and the total system power consumption increases slightly. Here, we are actually incurring SPM power that cannot be used by this particular application because the application itself is not large enough.
You can also notice that, combined with the allocation algorithm used, this particular application cannot use SPM regions smaller than 64 bytes, as there are no available fragments small enough to fit. A more sophisticated algorithm was also demonstrated in this study, which can achieve energy savings of over 80% in the best case.
Always do cache-friendly things
Analyzing the benefits of caches can sometimes be more complicated than analyzing the benefits of SPM. On the one hand, caches are essentially self-managing. On the other hand, caches do not operate on individual memory locations, but rather on fixed-size "lines." Therefore, accessing a single cacheable memory location may load an entire line, resulting in a burst of memory accesses. If this additional data is never accessed, the energy consumed is wasted.
Another disadvantage is the cost (in terms of silicon area and power) of the additional logic required for the cache. [page]
Figure 4: Energy advantage of cache
Figure 4 is from a paper by Princeton (Brooks, 2000) and shows three sets of data for a simple application benchmark. For different cache sizes, the bars represent performance IPC (instructions per cycle), power consumption, and power consumption time product (EDP). In general, performance will increase as the cache size increases. However, the power consumption of the system will also increase because the increase in cache units will increase the power consumption accordingly. The power consumption time product allows us to strike a balance between performance and cache size. In this example, there is an optimal point, that is, when the cache size is 64k, the power consumption time product is the smallest.
Minimize data memory access
One of the characteristics of the ARM architecture is that constants are nondeterministic. In particular, it is not possible to put an arbitrary 32-bit constant into a register with a single instruction. In fact, all memory accesses must operate on addresses in registers, which means that programs need to frequently put these and other constants into registers, which is difficult to do. The standard way to solve this problem is to embed constants as literal data in the code segment and load them at run time using PC-relative loads.
Therefore, it is useful to minimize the impact of constants. Make sure these constants are known at compile time and, if possible, embed them into a single ARM instruction. Minimize the need to load a base pointer to access global variables. This requires ensuring that global variables are in memory at runtime so that a single pointer can be used to access multiple variables. The simplest way to achieve this goal is to put global variables in a structure.
Although ARM's stack access is relatively efficient (stack access can load and store multiple instructions well), programmers can also reduce stack access in many ways: reduce active variables, avoid occupying local variable addresses, make full use of tail call optimization when possible, reduce the number of parameters passed to the function to less than four, allow the compiler to actively inline functions, etc.
Recursive situations and how to avoid them are more complicated. Often compilers can tail-optimize recursive functions very well. In fact, storing all data on the stack can give you better locality than you would otherwise. Perhaps the advice might be better expressed as "don't use recursive algorithms unless other approaches make data locality worse or you are sure the compiler can tail-optimize recursive calls". Exception handlers should be written to increase the chances of tail chaining, thereby avoiding unnecessary saves and restores of stack context.
Now let's turn our attention to the second elephant in the room, instruction execution.
Minimize the number of instructions
In fact, reducing the number of instructions executed is essentially the same as performance optimization. The fewer instructions executed, the lower the energy consumption. In addition, some obvious pointers should be added.
First, configure the tools correctly. Before the compiler and linker fully understand the target platform, even some basic optimizations cannot be implemented.
You need to be smart when writing code to avoid unnecessary operations. For the ARM architecture, 32-bit data types are efficient: 8-bit and 16-bit data types, although they take up less storage space, are also less efficient to process. In the v6 and v7 architectures, the pack and unpack instructions and SIM D operations can help somewhat, but be aware that these instructions are not accessible from C in the main program.
Be careful when writing loops
Loops can be written by following some simple rules: use unsigned integer counters, count down, and terminate when zero is reached. This can make loops shorter, faster, and use fewer registers. Also remember to write loops with vectorization in mind. Some simple rules about control structures and data declarations can make the compiler's job easier when trying to unroll and vectorize even the simplest loops.
Figure 5: Loop unrolling
Figure 5 shows some data related to one particular loop optimization, loop unrolling (Brooks, 2000). As expected, execution time and the number of instructions decrease as the unrolling factor increases. We see the effects of reduced loop overhead and fewer address calculations. The power results are more interesting, but less dramatic. The accuracy of the branch predictor decreases as the loop is further unrolled because there are fewer branches for the predictor to train its behavior and the final misprediction fraction for loop completion failures increases. However, because the continuous data flow of sequential instruction fetches is not interrupted as often, the efficiency of the instruction fetch stage can be improved. The combined result is a net reduction in energy consumption per instruction.
So even though the execution time is essentially less than a factor of 4, the all-important power-time product is reduced because power continues to decrease, so an energy-conscious compiler or developer will be more likely to unroll loops than one that only considers execution time.
The accuracy meets the requirements
You must also consider the precision required for the output. Even if floating-point hardware is available, calculations in fixed-point implementations are usually more efficient than those in floating-point implementations. If you are rendering an image to be viewed on a screen, you probably don't need to be completely compliant with the standard; you just need to render an acceptable image.
A study of progressive optimization of the standard MPEG-4 decoding function (Shin, 2002) has shown that switching from soft floating point to fixed point binary can reduce power consumption by 72%. The loss of precision means that the results are no longer compliant with the standard, but are still good enough for rendering purposes on the systems studied.
About Thumb
The Thumb instruction set was specifically designed to improve code density and also improve performance on narrow memory systems. However, while code density did improve, the number of instructions also increased. This is because the functionality of individual Thumb instructions was reduced compared to ARM instructions. So it seems reasonable that Thumb recompilation would result in increased energy consumption, and this is indeed what we have seen.
The above study shows that if the code size is reduced by 4%, the number of instructions executed increases by 38%, and the energy consumption increases by 28%. To find the third elephant, we need to go beyond the realm of the processor and its memory and look at the larger system. The system we use these days has been put together by our hardware design colleagues, and this system provides a lot of energy saving options.
Energy savings in the wider system
It is obvious that unused components should be placed in low power states whenever possible. This is an integral part of any smartly designed system, and these components should include memory and cache systems and even the processors themselves. In multi-core systems, we must consider the possibility of suspending one or more cores when processing requirements are relatively low.
First, a small but worthwhile consideration: when dealing with peripherals, always try to use interrupts rather than polling. Polling loops just consume power without any purpose. Almost all architectures include some kind of instruction to wait for an interrupt, which can put the system into a standby state in this case. For ARM systems, the core is usually clock gated, leaving only static leakage.
Unnecessary sleep-wake cycles can generally be avoided by designing the interrupt architecture to add tail chaining. The ARM Cortex-M3 architecture does this automatically.
[page]
For individual computing units, choosing a shutdown scheme is easy. For units that are predictably needed, the application or operating system can stop them when they are not needed. For units that are not predictably needed, the system can be powered up on demand or automatically powered down after being idle for a certain period of time. The time scale for powering down a subsystem can be derived from the power consumption when powered on but idle and the energy consumption of the sleep-wake cycle. Ultimately, it depends on the application. However, simple cycle counts of the power cycling code would be the most obvious starting point.
Measurements show that Neon engines run at about 10% higher power than cores such as Cortex-A9. However, for traditional signal processing algorithms, performance is improved by 40% - 150%. The benefits of enabling NeON during a task and shutting it down when not needed are clear. It is common that not only can the Neon engine be shut down when the task is completed, but the entire processor system can save more power.
Often a difficult choice is whether to enable a computation component to complete computations early (and therefore be off longer) or to reduce the processor speed when computations are completed to save power. Figure 6 shows the energy consumption data for each iteration of a simple benchmark (Domeika, 2009). This benchmark was run four times for each of two clock speeds, using different combinations of instruction cache and floating point coprocessor. Two key points are clear. First, although both the instruction cache and the floating point unit reduce power consumption, the floating point unit performs better than the instruction cache.
Figure 6: System component power utilization
Second, the energy consumption per iteration is essentially the same for all configurations, regardless of clock speed, so it is more efficient to enable everything and run at full speed rather than slowing down the clock speed in order to complete the task faster.
Multiprocessing
It is well known that using multiple cores can achieve higher performance and better energy efficiency than turning up the power of a single core. When using a multi-core system, we must consider the option of suspending one or more cores when they are not needed. ARM's research shows that the cost of a single core cycle in an SMPLinux system is 50,000 cycles (most of which are used to clear the first-level cache), which means that this operation will be completed in a few hundred milliseconds, not less, otherwise its energy consumption cost will outweigh its advantages.
ARM is an active research architecture that consists of two cores, a high-performance core for full-function operations and a smaller companion core for low-power operations with lower performance. When higher processing power is needed, the system runs the larger core. When the task is completed, the system can pass all information to the small core and shut down the large core. When the reverse information movement is needed, it switches back to the large core. If the two cores are connected as a related system, the energy cost of switching can be minimized.
About the operating system
Unfortunately, when running on an operating system, application programmers do not have this flexibility. Cache configuration, whether SPM is used or not, power cycles of components, etc. are largely determined by the operating system architecture and device drivers. However, application programmers still have a lot to consider.
Research has shown that poorly designed inter-process communication (IPC) can significantly increase the energy consumption of a system. A simple technique called "vectorizing" IPC, which batches small messages and sends a large number of small messages as a single large message, can often reduce context switching overhead. Additionally, reducing the number of processes can significantly reduce the need for IPC. Processes that need to communicate frequently can be combined into a single process.
Recent research (Tan, 2003) running on embedded Linux has shown that analysis and proper design of inter-process communication2 can potentially improve energy consumption by up to 60%.
in conclusion
Although I have emphasized that many areas are still within the realm of academic research, there is still much that can be done today. The results are relatively simple: reduce external memory accesses, reduce instruction execution, and turn off certain units when they are not in use.
In coming to this conclusion, I recalled a conversation I had with customers in a training class in mid-2009. These customers were concerned with implementing signal processing algorithms on the Cortex-A8 platform with Neon and wanted to know the exact energy consumption of individual instructions. I explained that in reality much of this information is unknown and in any case difficult to derive using current tools. Looking back, we have come to realize that this information is irrelevant in the long-term mission of hunting the elephant. In fact, the elephant that the customer is hunting is very small compared to the other elephants in the room. A better suggestion, either through analysis or continuous tracking of the data, is to estimate the number and type of data accesses involved in each implementation. This, combined with instruction counts, can lead to more informed choices. The power consumption of individual instructions is almost irrelevant compared to poor placement of memory accesses.
We, the software developers, need to continue to put pressure on academia and tool vendors to build these capabilities into the next generation of tools. It won’t be easy but it will happen.
Finally, I must remind you that all of this depends on your system, platform, application, OS, battery, and user. As the saying goes, "Earnings vary."
Previous article:Introduction to the principle and program implementation of LPC2100 series encryption ARM chips
Next article:Embedded-ARM register basic concepts
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- How to write down what you want to express in your heart
- Heat gun disassembly-Yaogong 857
- What capacitors should I use with LaunchPad?
- 【AT-START-F403A Review】+2.2' color TFT display driver
- Showing goods + inventory
- Does anyone have a simulation circuit diagram of the LMD18200 chip?
- Digital Circuit Design with Verilog HDL.pdf
- 46% of open source maintainers are unpaid, and 26% earn more than $1,000 per year
- How to start learning analog electronics
- I would like to ask about the AMS1117 and LM2596S chips