Page 43

EETE MAR 2015

Optimizing data memory utilization By Colin Walls Optimization is important to embedded software developers because they are always facing limited resources. So, being able to control the size and speed trade-off with code is critical. It is less common for thought to be given to the optimization of data, where there can be a similar speedversus size tension. This article looks at how this conflict comes about and what the developer can do about it. A key difference between embedded and desktop system programming is variability: every Windows PC is essentially the same, whereas every embedded system is different. There are a number of implications of this variability: tools need to be more sophisticated and flexible; programmers need to be ready to accommodate the specific requirements of their system; standard programming languages are mostly non-ideal for the job. This last point points towards a key issue: control of optimization. Optimization is a set of processes and algorithms that enable a compiler to advance from translating code from (say) C into assembly language to translating an algorithm expressed in C into a functionally identical one expressed in assembly. This is a subtle but important difference. Data/memory optimization A key aspect of optimization is memory utilization. Typically, a decision has to be made in the trade-off between having fast code or small code - it is rare to have the best of both worlds. This decision also applies to data. The way data is stored into memory affects its access time. With a 32-bit CPU, if everything is aligned with word boundaries, access time is fast; this is termed ‘unpacked data’. Alternatively, if bytes of data are stored as efficiently as possible, it may take more effort to retrieve data and hence the access time is slower; this is ‘packed’ data. So you have a choice much the same as with code: compact data that is slow to access, or some wasted memory but fast access to data. For example, this structure: struct { short two_byte; char one_byte; } my_array4; could be mapped into memory in a number of ways. The C language standard gives the compiler complete freedom in this regard. Two possibilities are: packed, like in figure 1, or unpacked like in figure 2: Unpacked could be even more wasteful. This graphic shows word (16-bit) alignment. Long word (32-bit) alignment would result in 5 bytes being wasted for every 3 bytes of data! Most embedded compilers have a switch to select what kind of code generation and optimization is required. However, there may be a situation where you decide to have all your data unpacked for speed, but have certain data structures where you would rather save memory by packing. In this case, the language extension keyword packed may be applied, thus: packed struct { short two_byte; char one_byte; } my_array4; This overrides the optimization setting for this one object. Alternatively, you may need to pack all the data to save memory, and have certain items that you want unpacked either for speed or for sharing with other software. This is where the unpacked extension keyword applies. It is unlikely that you would use both packed and unpacked keywords in one program, as only one of the two code generation options can be active at any one time. Space optimization As previously discussed, modern embedded compilers provide the opportunity to minimize the space used by data objects; this may be controlled quite well by the developer. However, this optimization is only to the level of bytes, which might not be good enough. For example, imagine an application that uses a large table of values, each of which is in the range 0 to 15. Clearly this requires 4 bits of storage (a nibble), so keeping them in bytes would only be 50% efficient. It is the developer’s job to do better (if memory footprint is deemed to be of greater importance than access time). There are broadly two ways to address this problem. One way is to use bit fields in structures. This has the advantage that a compiler can readily optimize memory usage, if the target CPU offers a convenient capability. The downside is that bit fields Colin Walls is an embedded software technologist with the Mentor Graphics Embedded Software Division - www.mentor.com/embedded-software and is based in the UK. He may be reached by email at colin_walls@mentor.com Fig. 1: packed C code mapping. Fig. 2: unpacked C code mapping. www.electronics-eetimes.com Electronic Engineering Times Europe March 2015 27


EETE MAR 2015
To see the actual publication please follow the link above