It’s not a single instruction performance that counts but rather how long does it take for the entire program to run. The solution is to execute multiple instructions at the same time which is known as Instruction Level Parallelism.
All instructions don’t have to be executed one after another if they are not dependent on each other. To run multiple instructions at the same time we need to track the dependencies between instructions dynamically to decide in which order the instructions need to be executed.
There are various techniques to execute instructions in parallel.
Pipelining is a way to reduce cycle time. Cycle time is the time taken to complete one fetch-execute cycle. It may take multiple cycles to execute one instruction.
Pipelining allows the next instruction to start execution while the current instruction is still being executed. This requires more hardware but it can improve the performance without having to increase the clock speed.
Pipelines are not easy to implement in a processor. There are various scenarios where this kind of architecture can create problems as the instructions can be dependent on each other. These problems are called hazards. There are two kinds of hazards: 1. Data hazard and 2. Control Hazard.
2. Super Scalar Architecture:
The idea behind Super Scalar Architecture is to have multiple execution units available to execute multiple instructions at the same time. The CPU has to perform more aggressively to figure out the dependencies and execute only those instructions which are independent.
3. Out of Order Execution:
It is also known as Dynamic Execution. The idea behind dynamic execution is to skip those instructions whose registers are not ready. While executing instructions if it stumbles upon an anti-dependency, it renames the register.