Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
en:multiasm:papc:chapter_6_16 [2025/11/20 09:26] – [Optimisation (DRAFT)] ktokarzen:multiasm:papc:chapter_6_16 [2025/11/25 12:49] (current) – removed ktokarz
Line 1: Line 1:
-====== Optimisation (DRAFT) ====== 
-Optimisation strongly depends on the microarchitecture of the processor. Some optimisation recommendations change together with new versions of processors. Producers usually publish the most up-to-date recommendations. The last release of the Intel documentation is "Intel® 64 and IA-32 Architectures Optimization" ((https://www.intel.com/content/www/us/en/developer/articles/technical/intel64-and-ia32-architectures-optimization.html)). AMD published the document "Software Optimization Guide for the AMD Zen5 Microarchitecture" ((https://docs.amd.com/v/u/en-US/58455_1.00)). 
-A selection of specific optimisation recommendations is described in this section. 
  
-===== The use of inc and dec instructions ===== 
-It is natural for programmers to use **inc** or **dec** instructions to increment or decrement the variable. They are simple and appear to be executed faster than addition and subtraction with a constant "1". The **inc** and **dec** are single-byte instructions, while **add** and **sub** with the argument as a constant consume at least one byte more. The problem with **inc** and **dec** instructions stems from the fact that they do not modify all flags, whereas **add** and **sub** modify all. Modifying all flags frees the processor from the need to wait for previously executed instructions to finish their operation in terms of flag modification. Intel recommends replacing **inc** and **dec** with **add** and **sub** instructions, but compilers do not always consider this recommendation.  
- 
-===== Versions of logic instructions ===== 
-While new extensions are introduced, several new instructions appear. In addition to advanced data processing instructions, simple logic instructions are also implemented. Previous versions of instructions are extended to operate with the latest, bigger registers. This may lead to confusion about which instruction to use, especially when they perform the same operation and give the same result. Let's consider three logic XOR instructions **pxor**, **xorps** and **xorpd**. All of them can operate on 128-bit XMM registers performing the bit-wise logic XOR function. At first sight, the instruction choice is meaningless - the result will be the same. In reality, the selection of the instruction matters. The performance analysis yields a result that, in different situations, the execution time can be longer or shorter. A deeper analysis reveals that when previous calculations are performed with integers, it is better to use integer operation **pxor**; if the data is floating-point, it is better to use the floating-point version **xorps** or **xorpd**. There is a section in the Intel optimisation manual about mixing SIMD data types. It is recommended to use packed-single instead of packed-double when possible. 
- 
- 
-===== Data placement ===== 
-It is recommended to place variables in the memory at their natural boundaries. It means that if the data is 16 bytes, the address should be evenly divisible by 16. For 8-byte data, the address should be divisible by 8. 
- 
-===== Registers use ===== 
-It is recommended to use registers instead of memory for scalar data if possible. Keeping data in registers eliminates the need to load and store it in memory.  
- 
-===== Cache temporal locality ===== 
-The term temporal locality refers to the fact that if data is used, it remains in a cache for a certain amount of time until other data is loaded into the cache. It is efficient to keep data in a cache instead of reloading it. This feature helps improve performance in situations where the program uses the same variables repeatedly, e.g. in a loop. 
-In a situation where the data processed exceeds half the size of a level 1 cache, it is recommended to use the non-temporal data move instructions **movntq** and **movntdq** to store data from registers to memory. These instructions are hints to the processor to omit the cache if possible. It doesn't mean that the data is immediately stored directly in memory. It can remain in the internal processor's buffers, and it is likely that the last version is not visible to other units of the computer. It is the programmer's responsibility to synchronise the data using the **sfence** (Store Fence) instruction. 
-===== Cache support instructions ===== 
-In modern microarchitectures, the cache memory is essential for improving performance. In general, the processor handles cache memory in the most efficient way possible; however, it is easy to write a program that prevents the processor from utilising this mechanism effectively. The rules for helping processors to use cache to achieve the best performance are: 
- 
- 
-There are also instructions which allow the programmer to support the processor with cache utilisation. 
- 
-MOVNTQ - saving the contents of the MMX register bypassing cache 
-MOVNTPS - write the contents of the SSE register bypassing cache 
-MASKMOVQ - write selected bytes from the MMX register bypassing cache 
-SFENCE - force the memory – cache synchronization  
-PREFETCH - a hint to the processor, that indicate that the memory area should be found higher in the hierarchy cache 
-clflush - Flushes a Cache Line from all levels of cache. 
-lfence - Guarantees that all memory loads issued before the lfence instruction are completed before any loads after the lfence instruction. 
-mfence - Guarantees that all memory reads and writes issued before the mfence instruction are completed before any reads or writes after the mfence instruction. 
-pause - Pauses execution for a set amount of time. 
- 
-movntdqa - Non-temporal aligned move. Load hint instruction. 
- 
- 
-===== Cache temporal locality ===== 
-The term temporal locality refers to the fact that if data is used, it remains in a cache for a certain amount of time until other data is loaded into the cache. It is efficient to keep data in a cache instead of reloading it. This feature helps improve performance in situations where the program uses the same variables repeatedly, e.g. in a loop. 
-In a situation where the data processed exceeds half the size of a level 1 cache, it is recommended to use the non-temporal data move instructions **movntq** and **movntdq** to store data from registers to memory. These instructions are hints to the processor to omit the cache if possible. It doesn't mean that the data is immediately stored directly in memory. It can remain in the internal processor's buffers, and it is likely that the last version is not visible to other units of the computer. It is the programmer's responsibility to synchronise the data using the **sfence** (Store Fence) instruction. 
- 
-===== Further research ===== 
-The essential readings in an optimisation topic are vendors' optimisation guides. 
- 
-Interesting position about optimisation in x64 processors is by Agner Fog((https://agner.org/optimize/optimizing_assembly.pdf)). 
- 
-Assembly tutorial ((https://sonictk.github.io/asm_tutorial/#debuggingassembly/thetools/radare2/cutterandida)) 
en/multiasm/papc/chapter_6_16.1763630803.txt.gz · Last modified: 2025/11/20 09:26 by ktokarz
CC Attribution-Share Alike 4.0 International
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0