Skip to content

Instantly share code, notes, and snippets.

@laughingclouds
Last active October 24, 2024 04:20
Show Gist options
  • Save laughingclouds/0b3a3a35a6ced6cbd14dc06a7fd9a5e2 to your computer and use it in GitHub Desktop.
Save laughingclouds/0b3a3a35a6ced6cbd14dc06a7fd9a5e2 to your computer and use it in GitHub Desktop.
Computer Architecture Notes | Generated using ChatGPT + Publicly available lecture notes (NPTEL Multicore computer architecture)

Let’s go into extreme detail on each of these topics, focusing on how they work, their key principles, and their impact on system performance.


1. Cache Memory

Cache memory is a small, high-speed memory located close to the CPU that stores frequently accessed data and instructions. Its purpose is to reduce the time it takes for the CPU to access data from slower main memory (RAM), enhancing overall system performance.

Key Components and Structure:

  • Cache Levels: Modern systems implement multiple levels of cache (L1, L2, L3):
    • L1 Cache: Closest to the CPU cores, typically split into instruction (L1i) and data (L1d) caches. It’s the smallest but fastest level of cache.
    • L2 Cache: Larger but slower than L1, it may be dedicated to individual cores or shared between them.
    • L3 Cache: Typically shared among all CPU cores, larger than L1 and L2, and designed to reduce cache misses before accessing main memory.

Cache Design:

  • Cache Line: Data is stored in fixed-size blocks known as cache lines (typically 32-64 bytes). When a CPU requests data, entire cache lines are loaded to exploit spatial locality.
  • Tag, Index, Offset: Each cache line has a tag (used to identify which block of main memory is stored), index (to select the set within the cache), and offset (to locate data within a block).

Types of Cache Mapping:

  • Direct-Mapped Cache: Each block of main memory maps to exactly one cache line. The simplicity makes it fast but prone to cache thrashing if multiple blocks map to the same line.
  • Set-Associative Cache: Divides the cache into several sets, and each memory block can be mapped to any line within a set. This improves flexibility and reduces conflicts but increases complexity.
  • Fully Associative Cache: Any memory block can be stored in any cache line, which eliminates conflict misses but makes the search process more complex and slower.

Cache Replacement Policies:

When the cache is full, a replacement policy decides which data to evict:

  • Least Recently Used (LRU): Evicts the least recently accessed block, based on the assumption of temporal locality.
  • First In, First Out (FIFO): The oldest block is evicted first. This policy is simpler but less efficient than LRU in many cases.
  • Random: Randomly selects a block to evict, typically used in hardware implementations for speed but offers less predictability.

Write Policies:

  • Write-Through: Every time data is written to the cache, it is also written to main memory simultaneously. This ensures data consistency but increases the amount of memory traffic.
  • Write-Back: Data is written to main memory only when the corresponding cache line is evicted. This reduces memory traffic but requires careful management to ensure data consistency.

Cache Coherence in Multi-Core Systems:

  • Cache Coherence: In multi-core processors, multiple cores may cache the same memory location. Cache coherence protocols ensure consistency across caches.
  • MESI Protocol: A widely used coherence protocol where each cache line can be in one of four states—Modified, Exclusive, Shared, or Invalid. This ensures that all cores have a coherent view of memory and manage modifications without conflicts.

Cache Misses:

  • Compulsory Misses: Occur when data is accessed for the first time and is not present in the cache.
  • Conflict Misses: Arise when multiple data blocks map to the same cache line, especially in direct-mapped or set-associative caches.
  • Capacity Misses: Happen when the working set of a program is larger than the cache size, causing frequent evictions and reloads.

Cache Optimization Techniques:

  • Prefetching: Anticipates future data accesses by loading likely needed data into the cache before it is requested, reducing cache miss rates.
  • Victim Cache: A small cache that holds recently evicted cache lines, providing a chance to recover recently displaced data.
  • Multi-level Caches: Modern processors use L1, L2, and L3 caches, each with increasing size and latency but decreasing speed, to reduce access to slower main memory.

2. Memory Management

Memory management refers to the techniques and systems used by the operating system (OS) to control and allocate memory to different processes efficiently. It is essential for ensuring system stability, performance, and multitasking.

Key Functions:

  • Memory Allocation:

    • Static Allocation: Memory is allocated at compile time and remains fixed throughout the program's execution.
    • Dynamic Allocation: Memory is allocated at runtime using functions like malloc() or new. Dynamic allocation enables more flexible and efficient use of memory.
  • Memory Segmentation:

    • Segmentation divides memory into logical units or segments (code, data, stack) with varying sizes. Each segment has a base address and length, allowing the operating system to map processes' logical addresses to physical memory.
    • Segmentation Faults occur when a process tries to access memory outside its segment bounds, usually resulting in a crash.
  • Memory Paging:

    • Paging divides both logical and physical memory into fixed-size blocks called pages and page frames (typically 4KB). The OS uses a page table to map pages from logical addresses to page frames in physical memory, enabling processes to access memory non-contiguously.
    • Page Faults: When a process accesses a page that is not currently in memory, the OS retrieves it from disk, incurring a large performance cost.
  • Fragmentation:

    • Internal Fragmentation: Occurs when memory allocated to a process is larger than required, leaving unused space within an allocated block.
    • External Fragmentation: Happens when free memory is divided into small, non-contiguous chunks, making it hard to allocate large blocks of memory.
    • Compaction: The process of reorganizing memory to reduce fragmentation, though it’s time-consuming and costly in terms of performance.

Memory Management Techniques:

  • Virtual Memory: Expands physical memory by using disk space (swap space) as additional memory. Processes are given access to a larger address space than physically available by swapping unused pages to disk when physical memory is full.

    • Demand Paging: Pages are only loaded into memory when they are needed, reducing memory use.
    • Swapping: Entire processes are swapped in and out of memory based on CPU scheduling needs, allowing more processes to run simultaneously.
  • Memory Protection:

    • Protects processes from each other by isolating memory spaces. This is achieved using base and limit registers or page-level protection in paging systems.
    • Access Control: Memory can be marked as read-only, writable, or executable to prevent unintended modifications (e.g., preventing execution of code from the stack to avoid exploits like buffer overflows).

Page Replacement Algorithms:

  • Optimal Replacement: Replaces the page that will not be used for the longest period of time (theoretical ideal).
  • Least Recently Used (LRU): Replaces the page that has not been used for the longest time, based on the principle of temporal locality.
  • First In, First Out (FIFO): Replaces the oldest loaded page, regardless of usage.
  • Clock Algorithm: A variation of FIFO that uses a circular buffer and a reference bit to track usage, replacing pages that haven’t been used recently.

3. Parallel Processing

Parallel processing is the simultaneous execution of multiple instructions or tasks to improve system performance by utilizing multiple cores or processors.

Key Concepts:

  • Types of Parallelism:
    • Data Parallelism: The same operation is applied simultaneously to different pieces of data. This is common in SIMD (Single Instruction, Multiple Data) architectures like GPUs.
    • Task Parallelism: Different tasks or threads are executed concurrently. This is common in MIMD (Multiple Instruction, Multiple Data) architectures, such as multi-core processors.

Flynn’s Taxonomy:

  • SISD (Single Instruction, Single Data): Traditional, sequential execution where one instruction operates on a single data point.
  • SIMD: One instruction operates on multiple data points simultaneously. This is efficient for vector and matrix operations and is used extensively in GPUs for tasks like graphics rendering and deep learning.
  • MISD (Multiple Instruction, Single Data): Rarely used, involves multiple instructions operating on the same data stream.
  • MIMD: Each processor executes different instructions on different data. This is typical of multi-core CPUs and distributed systems.

Models of Parallelism:

  • Shared Memory Model: Multiple processors share a single memory space. Threads communicate by reading and writing to shared variables.
  • Distributed Memory Model: Each processor has its own memory, and communication occurs through message passing (e.g., MPI). This model is common in large-scale supercomputers and clusters.

Challenges of Parallel Processing:

  • Synchronization:
    • Locks: Ensure mutual exclusion so that only one thread can access a critical section of code at a time.
    • Semaphores: Generalized locks that control access to shared resources by counting available instances.
    • Deadlock: Occurs when two or more threads are waiting on each other to release resources, resulting

in a system freeze.

  • Load Balancing:

    • The distribution of work among processors. In an unbalanced system, some processors may be idle while others are overloaded, reducing overall efficiency.
    • Static Load Balancing: Tasks are pre-assigned to processors based on known computational needs.
    • Dynamic Load Balancing: Tasks are distributed during runtime based on current processor loads, ensuring better resource utilization.
  • Amdahl’s Law: Defines the theoretical speedup achievable in parallel systems: [ \text{Speedup} = \frac{1}{(1 - P) + \frac{P}{N}} ] Where P is the portion of the program that can be parallelized, and N is the number of processors. Amdahl’s Law highlights the diminishing returns of adding more processors when the portion of serial code is significant.


4. Virtual Memory

Virtual memory is a technique that allows a computer to use more memory than is physically available by using disk space to simulate additional RAM. It provides a larger logical address space to programs while isolating their memory spaces for protection.

Key Concepts:

  • Address Translation:

    • Virtual addresses used by processes are translated into physical addresses using a page table. Each page table entry (PTE) maps a virtual page to a physical frame or a location on disk.
    • Translation Lookaside Buffer (TLB): A small, fast cache that stores recent page table mappings to accelerate address translation.
  • Demand Paging:

    • Pages are loaded into memory only when needed, reducing the amount of physical memory required. If a page is not present in memory, a page fault occurs, and the OS retrieves the page from the disk (swap space).
    • Lazy Loading: Pages are not pre-loaded into memory at the start of a process, but rather loaded on demand.
  • Page Replacement:

    • When memory is full and a new page needs to be loaded, the OS must replace an existing page. Page replacement policies (LRU, FIFO, etc.) determine which page to evict.
  • Swapping:

    • In extreme cases, entire processes are swapped out to disk to free up physical memory. When the process is swapped back in, it must restore its entire memory image, which incurs significant overhead.
  • Virtual Address Space:

    • Virtual memory provides each process with its own virtual address space, preventing processes from interfering with each other’s memory. This is crucial for process isolation, security, and stability.

Advantages of Virtual Memory:

  • Process Isolation: Virtual memory ensures that processes cannot directly access or interfere with each other’s memory space.
  • Efficient Memory Utilization: Processes are not limited by the physical memory available on the system. They can operate as if they have more memory (through paging and swapping), allowing multiple processes to run simultaneously.
  • Simplified Memory Management: Virtual memory decouples logical memory allocation from physical memory, enabling dynamic memory allocation and efficient resource sharing.

Performance Implications:

  • Virtual memory incurs overhead due to the need for page table lookups, TLB misses, and disk I/O during page faults.
  • Page Swapping: When excessive, swapping can lead to thrashing, where the system spends more time loading and unloading pages than executing code, drastically reducing performance.
  • Optimizing Virtual Memory: Operating systems employ sophisticated algorithms to optimize TLB management, reduce page faults, and balance the use of physical and virtual memory.

These topics cover the extreme technical details of cache memory, memory management, parallel processing, and virtual memory, highlighting the principles, mechanisms, and challenges involved in each. Let me know if you need any further explanation or examples!

Certainly! Let’s delve into even more intricate details for each topic, covering advanced concepts and technical nuances. Here’s an in-depth expansion of the previously identified topics:


1. Computer Organization vs. Architecture

  • Computer Architecture: The architecture defines the system’s high-level design visible to the programmer. The key components here are the Instruction Set Architecture (ISA), which acts as the interface between hardware and software. The ISA includes:

    • Instruction Set: The complete set of instructions a processor can execute, such as arithmetic, logical, control flow, and data transfer operations.
    • Data Types: Architecture specifies the types of data the processor can manipulate, such as integers, floating-point numbers, and vectors.
    • Addressing Modes: The methods used to access data operands (e.g., register, immediate, direct, indirect).
    • Memory Hierarchy: Understanding the interaction between caches, main memory, and secondary storage in an architecture is essential, including cache organization (e.g., write-through vs. write-back, direct-mapped vs. associative caches).
    • Pipeline Depth and Instruction-level Parallelism (ILP): Advanced processors exploit ILP by executing multiple instructions concurrently using deep pipelines.
  • Computer Organization: Deals with the operational units and their interconnections that realize the architecture. Key components include:

    • CPU (Central Processing Unit): Includes functional units like the Arithmetic Logic Unit (ALU), Floating Point Unit (FPU), registers, and control units.
    • Data Paths: The buses and connections that transfer data between the CPU, memory, and I/O devices.
    • Control Signals: The organization defines the signals needed to control the flow of data, timing, and synchronization between functional units.
    • Microprogramming: Many architectures rely on microprogramming, where microinstructions dictate low-level hardware operations like fetching, decoding, and executing instructions.

2. Execution Cycle

The execution cycle consists of a sequence of steps that the CPU follows to process each instruction. Each step relies on intricate timing and hardware synchronization:

  • Instruction Fetch (IF):

    • Program Counter (PC): Holds the address of the next instruction to be executed. The PC is automatically incremented after fetching an instruction.
    • Memory Address Register (MAR): The PC value is copied to the MAR, which is used to access the instruction from memory.
    • Memory Data Register (MDR): The fetched instruction is placed into the MDR, which holds the data retrieved from memory before being passed on.
    • Caches: Modern processors have multiple levels of caches (L1, L2, L3) to reduce the latency of instruction fetches.
  • Instruction Decode (ID):

    • Instruction Register (IR): Holds the fetched instruction. The control unit uses the opcode (operation code) in the instruction to determine which operation needs to be performed.
    • Control Signals: Based on the opcode, control signals are generated to activate different parts of the processor (ALU, memory access, etc.).
    • Micro-operations: Complex instructions (like floating-point divide) are broken down into simpler micro-operations that the processor can execute step-by-step.
  • Operand Fetch:

    • Addressing Modes: The processor determines how to locate operands. For example, the Effective Address (EA) of an operand can be computed using indexed or base register addressing modes.
    • Data Transfer: The operand is fetched from memory or registers and placed into ALU input registers.
  • Execute (EX):

    • Arithmetic Logic Unit (ALU): The core execution unit where operations like addition, subtraction, AND, OR, and comparisons are performed.
    • Condition Flags: Operations like comparisons and shifts update condition flags (e.g., zero flag, carry flag), which influence subsequent control flow instructions.
    • Pipelined ALU: In modern processors, the ALU may be pipelined to allow multiple operations to be in-flight simultaneously, improving throughput.
  • Memory Access (MEM):

    • This stage is crucial for load/store instructions. For a load instruction, the processor retrieves data from memory (possibly going through cache hierarchy) into a register. For a store, the data from a register is written back to memory.
    • Write-Back Cache Policy: If the cache uses write-back policy, modified data is only written to main memory at specific points (e.g., during cache eviction).
  • Write-Back (WB):

    • The result of the operation (from ALU or memory) is written back into a register or memory location, depending on the instruction.
    • Commit Stage: In out-of-order execution engines, results are not immediately written back. They are temporarily stored and committed once all previous instructions have completed successfully.

3. Processor-Memory Interaction

Modern CPUs interact with memory through a complex memory hierarchy designed to optimize latency and bandwidth:

  • Memory Hierarchy: CPUs have a tiered memory structure:

    • Registers (fastest, smallest): These are directly within the CPU and store data temporarily during computations.
    • Cache Memory (L1, L2, L3): Faster but smaller compared to main memory. L1 cache is split into instruction and data caches. L2 cache is shared between cores in modern multi-core processors.
    • Main Memory (RAM): Significantly slower than caches but larger in capacity. Accessing main memory is a major performance bottleneck, so caches help minimize main memory accesses.
    • Virtual Memory: Extends physical memory by using disk storage. It maps logical addresses used by programs to physical addresses using page tables and TLBs (Translation Lookaside Buffers) for fast address translation.
  • Bus Architecture: The connection between the CPU, memory, and other peripherals:

    • Front-Side Bus (FSB): Traditional architecture where the CPU connects to memory and I/O through the FSB.
    • HyperTransport, PCIe, QPI (QuickPath Interconnect): Modern high-speed point-to-point interconnects that replace the FSB for better memory and I/O bandwidth.

4. Von Neumann Model

  • Unified Memory: The fundamental concept of the Von Neumann model is that both instructions and data are stored in the same memory space. This simplifies the architecture but also creates bottlenecks, especially in the instruction fetch phase, where memory access can stall the pipeline.
  • Sequential Processing: Instructions are fetched and executed one after the other unless there’s a jump or branch. Modern processors overcome this limitation using superscalar designs and speculative execution to increase instruction-level parallelism (ILP).
  • Harvard Architecture: In contrast, the Harvard architecture separates instruction and data memory, allowing simultaneous access to both.

5. Instruction Set Architecture (ISA) and Types

The ISA is the interface that software interacts with. Here’s a breakdown of common instruction types:

  • Arithmetic Instructions: Perform integer or floating-point operations. Examples include ADD, SUB, MUL, DIV. Floating-point arithmetic requires dedicated hardware like an FPU (Floating Point Unit), and operations like floating-point division can take multiple clock cycles.
  • Logical Instructions: Perform bitwise operations (AND, OR, XOR, NOT), which are essential for manipulating binary data and setting condition flags.
  • Shift and Rotate Instructions: Shift bits left or right (e.g., SHL, SHR). These operations are crucial for efficient multiplication and division by powers of two, as well as for cryptography and encoding algorithms.
  • Data Movement Instructions: These include MOV (move data between registers and memory), PUSH (push data onto a stack), and POP (retrieve data from a stack). In modern CPUs, register renaming ensures that data movement doesn’t cause stalls due to false dependencies.
  • Control Flow Instructions: These include branching instructions like JMP, CALL, RET, as well as conditional branches (BEQ, BNE). Processors employ branch prediction and speculative execution to minimize pipeline stalls caused by control flow changes.

6. ISA vs. Microarchitecture

  • ISA (Instruction Set Architecture): This is the agreed-upon contract between software and hardware. For example, the x86 architecture has evolved over decades while maintaining backward compatibility. A key concept is orthogonality, where each instruction operates consistently across all data types and addressing modes.
  • Microarchitecture: Different implementations of the same ISA can vary significantly in performance and design. For instance, the Intel Core and AMD Zen microarchitectures both implement the x86-64 ISA but differ in aspects like core layout, cache design, branch prediction algorithms, and out-of-order execution capabilities.
    • Pipeline Depth: Deeper pipelines (e.g., 10-20 stages) can improve clock speed but at the cost of increased branch penalties and hazard management.
    • Superscalar Execution: A superscalar processor can issue multiple instructions per clock cycle, allowing parallelism at the instruction level.
    • Out-of-order Execution (OoO): Modern CPUs, like Intel’s Skylake, use out-of-order execution to maximize resource utilization. Instructions are executed as soon as their operands are ready, rather than strictly in program order.

7. Addressing Modes

Addressing modes define how the processor identifies operands. Complex addressing schemes allow flexibility in how data is accessed and manipulated.

  • Immediate Addressing: The operand is a constant embedded in the instruction. It’s fast since no memory access is required.
  • Direct Addressing: The instruction contains the memory address of the operand. This is straightforward but limited by address field size.
  • Indirect Addressing: The address of the operand is stored in a memory location pointed to by the instruction. This adds flexibility but requires multiple memory accesses, increasing latency.
  • Indexed Addressing: Involves adding an index (stored in a register) to the base address. Common in array processing.
  • Relative Addressing: Common in branching instructions, where the operand is a relative offset from the current instruction pointer (useful for implementing loops and conditional branches).
  • Auto-increment/Auto-decrement: The operand address is automatically incremented or decremented after being accessed. Useful for stack operations.

8. Instruction Pipeline

  • Pipelining improves throughput by dividing the instruction processing into stages, where each stage is handled by a different hardware unit.
  • Pipeline Stages:
    1. IF (Instruction Fetch): Retrieves the instruction from memory.
    2. ID (Instruction Decode): Decodes the instruction and reads necessary registers.
    3. EX (Execute): The ALU performs arithmetic, logic, or memory address calculations.
    4. MEM (Memory Access): Loads from or stores data to memory.
    5. WB (Write Back): Writes the result back to a register.
  • Superpipelining: Increases pipeline depth by further subdividing stages (e.g., splitting instruction fetch into multiple stages), but adds complexity in managing hazards.
  • Superscalar Execution: Involves dispatching multiple instructions per cycle into different pipelines, allowing for parallelism at the instruction level.

9. Pipeline Hazards

  • Structural Hazards: Occur when two instructions attempt to use the same resource. For example, a shared memory unit might cause a stall if both a load and store instruction need memory access simultaneously.

    • Solution: Duplicate resources (e.g., separate data and instruction caches), or introduce pipeline stalls.
  • Data Hazards:

    • RAW (Read After Write): Occurs when an instruction needs data that hasn’t yet been written by a previous instruction.
    • WAR (Write After Read): Happens when a subsequent instruction writes to a location that an earlier instruction still needs to read.
    • WAW (Write After Write): Two instructions write to the same register out of order, potentially leading to inconsistent data.
    • Solutions: Use techniques like operand forwarding (bypassing the normal data path) to resolve RAW hazards, or stalling to delay the pipeline until data dependencies are resolved.
  • Control Hazards: Caused by branching instructions. If the processor doesn’t know the outcome of a branch, it might fetch the wrong instruction, leading to pipeline flushes.

    • Branch Prediction: Modern processors use dynamic branch predictors (e.g., TAGE, gshare predictors) to guess the outcome of a branch. Predictors can be highly accurate, minimizing stalls due to control hazards.

10. Branch Prediction

  • Static Branch Prediction: Uses fixed rules (e.g., assume branches are not taken). This is simple but not adaptive to real-time conditions.
  • Dynamic Branch Prediction: Tracks branch behavior over time using history tables. Predictors use Finite State Machines (FSMs) to adjust predictions based on past outcomes.
  • Branch Target Buffer (BTB): Stores the predicted target address of branches, reducing penalty when a branch is correctly predicted as taken.
  • 2-Bit Predictors: Use two bits to track whether a branch is likely to be taken. This allows for hysteresis, reducing the chance of misprediction when a branch behavior changes infrequently.
  • Tournament Predictors: Combine multiple predictors (e.g., global and local predictors) to choose the most accurate one in different contexts.

11. Performance Evaluation

  • Execution Time (CPU Time): Measured by: [ \text{CPU Time} = \text{CPI} \times \text{Instruction Count} \times \text{Clock Cycle Time} ] Where CPI (Cycles Per Instruction) is a key metric. Optimizing CPI and clock cycle time is critical for improving performance.
  • Throughput: Measures the number of instructions a processor can complete per unit time. High throughput architectures rely on superscalar execution, out-of-order execution, and parallelism.
  • Amdahl’s Law: Describes the maximum speedup a system can achieve by improving part of it: [ \text{Speedup} = \frac{1}{(1 - f) + \frac{f}{S}} ] Where f is the fraction of execution time that benefits from improvement, and S is the speedup factor of the improved part. Amdahl’s Law shows that the benefit of parallelizing a system diminishes if only part of the workload can be parallelized.

12. Multi-Cycle Operations

  • Some instructions (like floating-point multiply, divide, or square root) require more than one clock cycle to complete. These instructions can create bubbles (delays) in the pipeline.
  • Floating Point Pipeline: Floating-point operations like addition or multiplication often have separate pipelines due to their complexity. For instance, floating-point multiplication can take 3-5 cycles depending on precision (single vs. double) and operand normalization.
  • Latency: Refers to the number of cycles required for an instruction to produce its result.
  • Initiation Interval: The minimum number of cycles required between issuing two independent operations. For example, in a fully pipelined floating-point unit (FPU), new operations can be issued every cycle, even if they take multiple cycles to complete.
  • Hazards in Multi-cycle Pipelines: Multi-cycle operations introduce hazards such as structural hazards (limited FP units) and WAW hazards (write-after-write in out-of-order execution). Modern CPUs handle these hazards using reservation stations and scoreboarding.

Conclusion:

This extreme detail breaks down the inner workings of modern computer architectures, explaining their complexity and how they handle efficiency challenges. It covers concepts like pipelining, branch prediction, memory hierarchy, instruction execution, and more. These mechanisms work together to maximize processor performance, especially in modern, multi-core environments where the goal is to extract the most parallelism from sequential code while managing the many bottlenecks and hazards that arise. Let me know if you need any further elaboration or examples!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment