PERSONAL - Advanced Computer Architecture

Cross Cutting Aspects

Performance

Terminology

Dynamic and Static Energy

Technique Dynamic Energy Static Energy Key Mechanism
DVFS ↓↓ ↓ or ↑ Dynamic Voltage and Frequency Scaling; switching clock rate and voltage according to program characteristics; lower VVV but longer ttt
Clock gating ↓↓ ↔ Switch clock off for certain components
Power gating ↓ ↓↓ Switch power off entirely (loses data!)
Dark silicon ↓ ↔ or ↓ Limits active area with parts of the chip that cannot be powered simultaneously due to power/thermal limits

Parallelism

Parallel Metrics (p processors)

Memory Hierarchy

39801aeabf6776547131c3553f768bb6.webp

Fault Tolerance, Reliability, Availability

Term Stage Effect Example
Fault Cause Potential to create an error Broken memory cell
Error Manifestation Wrong system state Flipped bit in memory
Failure Observable problem System behaves incorrectly Program crashes or displays wrong value
Metric What it Measures Focus Example
Reliability Correct operation over time Avoiding failures MTBF of a processor is 10,000 hours
Safety Avoiding harm even when failures occur Preventing catastrophic events Airplane control computer fails safely
Availability System ready for use when needed Uptime & quick recovery Cloud server uptime 99.99%

Virtualization

Processor Classes

Parallel Architectures

70f7228a816c68454f1de58a204a77da.webp

Instruction Set Architecture

Aspect Interrupt Exception
Origin External (hardware) Internal (CPU)
Timing Asynchronous Synchronous
Cause Event outside current instruction Result of current instruction
Typical use I/O, timers, device signals Errors, faults, system calls

CISC vs. RISC

Instruction Pipelining

Pipeline Hazards

Data Dependencies

// read-after-write (RAW): true dependency
// instruction needs a value that a previous instruction will write
add r1, r2, r3 // writes r1
sub r4, r1, r5 // reads  r1

// write-after-read (WAR): anti-dependency
// instruction writes to a location that a previous instruction still needs to read
sub r2, r3, r4 // reads  r3
add r3, r5, r6 // writes r3

// write-after-write (WAW): output dependency
// two instructions write to the same location, and the order of the writes matters
add r1, r2, r3
sub r1, r4, r5
// read-after-write (RAW): true dependency
// instruction needs a value that a previous instruction will write
add r1, r2, r3 // writes r1
sub r4, r1, r5 // reads  r1

// write-after-read (WAR): anti-dependency
// instruction writes to a location that a previous instruction still needs to read
sub r2, r3, r4 // reads  r3
add r3, r5, r6 // writes r3

// write-after-write (WAW): output dependency
// two instructions write to the same location, and the order of the writes matters
add r1, r2, r3
sub r1, r4, r5
Dependency Meaning Also called
RAW Read after write True dependency
WAR Write after read Anti-dependency (name dependency)
WAW Write after write Output dependency (name dependency)

Data Dependency Solutions

Technique Purpose Behavior
Interlocking Handle hazards Stall pipeline
Forwarding Reduce stalls Bypass data between stages
Forwarding with interlocking Optimal hazard handling Forward when possible, stall when necessary

Control Hazards

add r1,r2,r3       ...
...            ->  ...
br addr            br addr
nop                add r1,r2,r3   // delay slot, always executed!
add r1,r2,r3       ...
...            ->  ...
br addr            br addr
nop                add r1,r2,r3   // delay slot, always executed!
// correlation predictor example
if (aa == 2)  { aa = 0; }
if (bb == 2)  { bb = 0; }
if (aa != bb) { ... } // we know the outcome of this based on the previous 2 ifs
// correlation predictor example
if (aa == 2)  { aa = 0; }
if (bb == 2)  { bb = 0; }
if (aa != bb) { ... } // we know the outcome of this based on the previous 2 ifs

Pipelining in Modern Processors

9da1865953dda0f75c517039db2fb2f5.webp

Stage In Order? Purpose
Fetch Yes Get instruction bytes (I-Cache, branch prediction logic)
Decode Yes Translate to µops
Rename / Allocation Yes Remove name dependencies and allocate resources in reorder buffer, issue queue and L/S queue (no resources for buffers / queues? \to→\to stall instruction until required resource is released)
Issue No Select ready instructions (otherwise wait in queue until all operands and functional units are available)
Execute No Perform computation
Writeback No Publish results to intermediate storage (merged register file, ROB)
Commit Yes Update architectural state, ensuring sequential order

Fetch

eeb1b04a79997bb591783a51880e57a1.webp

// hybrid branch predictor example
if (x > 0)  ... // A: predictable per-branch   -> local wins
if (y == x) ... // B: correlated with branch A -> global wins 
// hybrid branch predictor example
if (x > 0)  ... // A: predictable per-branch   -> local wins
if (y == x) ... // B: correlated with branch A -> global wins 

Decode

beac1843e9a21b5c884b6675d49b4dee.webp

Rename / Allocation

Feature ROB Renaming Merged Register File
Where results are stored In ROB entries In physical registers (PRF)
Purpose of ROB Holds both result + commit info Holds only status/commit info
Size limitation ROB size limits both instruction window and storage PRF can be larger than ROB → more in-flight instructions
Operand reading From ROB entries (potential bypass network) From PRF using rename table tags
Speculation handling ROB entries checkpoint program state Rename table + PRF can be checkpointed
Complexity Simpler, fewer physical resources More hardware: free list, larger wakeup network

Issue / Dispatch

d8f7fc7ac4431925455fe93a00d6fe81.webp

div  f0,  f2, f4 // A
add  f10, f0, f8 // B: blocked by A
load f12, f8, 10 // C: independent, but still cannot be executed because we need to respect program order
div  f0,  f2, f4 // A
add  f10, f0, f8 // B: blocked by A
load f12, f8, 10 // C: independent, but still cannot be executed because we need to respect program order
Aspect Reservation Stations (Tomasulo) Unified Issue Queue
Organization Distributed per functional unit Centralized
Instruction placement Assigned to a specific unit early Assigned to unit at issue time
Scheduling Implicit (local readiness) Explicit (global select logic)
Flexibility Limited (fixed unit binding) High (dynamic unit matching)
Hardware complexity Lower (small local structures) Higher (global wakeup/select)
Scalability Better in small systems Harder as width grows
Typical era Classic RISC / early OoO Modern superscalar CPUs

f71dd054ac9acb7fe4553e65b8543e36.webp

// memory ambiguity
store [r3], r4       //           problem:
load  r1  , [r2]     // RAW?      we don't know yet where [r3], [r2] and [r6] point to...
store [r6], r1       // WAR? WAW? ... it could be that [r3] == [r2] == [r6]
add   r3  , r1  , r7
// memory ambiguity
store [r3], r4       //           problem:
load  r1  , [r2]     // RAW?      we don't know yet where [r3], [r2] and [r6] point to...
store [r6], r1       // WAR? WAW? ... it could be that [r3] == [r2] == [r6]
add   r3  , r1  , r7

Execute

Commit

Recovery from Branch Misprediction

afb9ecb7a55fb5ae0eb318b0a50a88a1.webp

Compiler Support

Software Pipelining

LOAD  0
ADD   0  LOAD  1
STORE 0  ADD   1 LOAD  2
         STORE 1 ADD   2
                 STORE 2
LOAD 0
---
ADD   0
LOAD  1
---
STORE 0
ADD   1
LOAD  2
---
STORE 1
ADD   2
---
STORE 2
Software Pipelining

LOAD  0
ADD   0  LOAD  1
STORE 0  ADD   1 LOAD  2
         STORE 1 ADD   2
                 STORE 2
LOAD 0
---
ADD   0
LOAD  1
---
STORE 0
ADD   1
LOAD  2
---
STORE 1
ADD   2
---
STORE 2
do i = 1, n
  a(i) = b(i) + 2                do i = 1, n
enddo                      ->      a(i) = b(i) + 2
                           ->      c(i) = d(i+1) * a(i)
do i = 1, n                      enddo
  c(i) = d(i+1) * a(i)
enddo
do i = 1, n
  a(i) = b(i) + 2                do i = 1, n
enddo                      ->      a(i) = b(i) + 2
                           ->      c(i) = d(i+1) * a(i)
do i = 1, n                      enddo
  c(i) = d(i+1) * a(i)
enddo

06a46629ddfec5828b686bc9ad29126c.webp
162e63fcfbbb3a33161d0e419cc40da1.webp

Caches

Cache Mapping

Address:
+------------+----+
| bbbbbbbbbb | ww |
+------------+----+

Example:
0x43F -> 0100 0011 11|11 -> idx. 0 (just inserted?), column 11 (4th) -> 0x12
0x5D2 -> 0101 1101 00|10 -> idx. 1 (just inserted?), column 10 (3rd) -> 0xFA

Cache:
+--------------+----+----+----+----+
|      Tag     | 00 | 01 | 10 | 11 |
+--------------+----+----+----+----+
| 0100 0011 11 | AB | CD | EF | 12 |
| 0101 1100 00 | 53 | 91 | FA | B2 |
|      ...     | .. | .. | .. | .. |
+--------------+----+----+----+----+
Address:
+------------+----+
| bbbbbbbbbb | ww |
+------------+----+

Example:
0x43F -> 0100 0011 11|11 -> idx. 0 (just inserted?), column 11 (4th) -> 0x12
0x5D2 -> 0101 1101 00|10 -> idx. 1 (just inserted?), column 10 (3rd) -> 0xFA

Cache:
+--------------+----+----+----+----+
|      Tag     | 00 | 01 | 10 | 11 |
+--------------+----+----+----+----+
| 0100 0011 11 | AB | CD | EF | 12 |
| 0101 1100 00 | 53 | 91 | FA | B2 |
|      ...     | .. | .. | .. | .. |
+--------------+----+----+----+----+
Address:
+---------+-----+----+
| bbbbbbb | lll | ww |
+---------+-----+----+

Example:
0x35C -> 0011 010|1 11|00 -> line 111, column 00 -> 0x3C

Cache:
    +----------+----+----+----+----+
    |    Tag   | 00 | 01 | 10 | 11 |
    +----------+----+----+----+----+
000 |    ...   | .. | .. | .. | .. |
001 |    ...   | .. | .. | .. | .. |
... |    ...   | .. | .. | .. | .. |
111 | 0011 010 | 3C | 5D | 29 | 15 |
    +----------+----+----+----+----+
Address:
+---------+-----+----+
| bbbbbbb | lll | ww |
+---------+-----+----+

Example:
0x35C -> 0011 010|1 11|00 -> line 111, column 00 -> 0x3C

Cache:
    +----------+----+----+----+----+
    |    Tag   | 00 | 01 | 10 | 11 |
    +----------+----+----+----+----+
000 |    ...   | .. | .. | .. | .. |
001 |    ...   | .. | .. | .. | .. |
... |    ...   | .. | .. | .. | .. |
111 | 0011 010 | 3C | 5D | 29 | 15 |
    +----------+----+----+----+----+
Address:
+----------+----+----+
| bbbbbbbb | ss | ww |
+----------+----+----+

Example:
0x3CB -> 0011 1100 |10|11 -> set 10, column 11 -> 0x2C
0xFB8 -> 1111 1011 |10|00 -> set 10, column 00 -> 0xC2

Cache:
   +-----------+----+----+----+----+
   |    Tag    | 00 | 01 | 10 | 11 |
   +-----------+----+----+----+----+
00 |    ...    | .. | .. | .. | .. |
00 |    ...    | .. | .. | .. | .. |
01 |    ...    | .. | .. | .. | .. |
01 |    ...    | .. | .. | .. | .. |
10 | 0011 1100 | B5 | 8A | F9 | 2C |
10 | 1111 1011 | C2 | 5B | 9F | 32 |
11 |    ...    | .. | .. | .. | .. |
11 |    ...    | .. | .. | .. | .. |
    +----------+----+----+----+----+
Address:
+----------+----+----+
| bbbbbbbb | ss | ww |
+----------+----+----+

Example:
0x3CB -> 0011 1100 |10|11 -> set 10, column 11 -> 0x2C
0xFB8 -> 1111 1011 |10|00 -> set 10, column 00 -> 0xC2

Cache:
   +-----------+----+----+----+----+
   |    Tag    | 00 | 01 | 10 | 11 |
   +-----------+----+----+----+----+
00 |    ...    | .. | .. | .. | .. |
00 |    ...    | .. | .. | .. | .. |
01 |    ...    | .. | .. | .. | .. |
01 |    ...    | .. | .. | .. | .. |
10 | 0011 1100 | B5 | 8A | F9 | 2C |
10 | 1111 1011 | C2 | 5B | 9F | 32 |
11 |    ...    | .. | .. | .. | .. |
11 |    ...    | .. | .. | .. | .. |
    +----------+----+----+----+----+
Cache Type Placement Flexibility Hardware Cost Conflict Misses
Direct Mapped One place only Low High
Set Associative Few places Medium Medium
Fully Associative Anywhere High Low

Replacement Algorithms

Write Policies (Update Strategies)

Cache Misses

Instruction Cache, Trace Cache

Cache Optimization

Reducing Hit Time

Increasing Cache Bandwidth

Feature Blocking Cache Nonblocking Cache
CPU behavior on miss Stalls until data arrives Continues executing independent instructions
Complexity Simple More complex (needs buffers to track misses)
Performance Lower (miss penalty directly stalls CPU) Higher (miss penalty can be overlapped with useful work)
Typical use Small, simple caches High-performance CPUs, multi-level caches

Reducing Miss Penalty

Reducing Miss Rate

Reuse Distance Examples

A,B,C,D,E,F,G,A
Reuse Pair      : (A,A)
Unique Locations: 6 (B,C,D,E,F,G)
Reuse Distance  : 6

A,B,B,B,C,A
Reuse Pair      : (A,A)
Unique Locations: 2 (B,C)
Reuse Distance  : 2
Reuse Distance Examples

A,B,C,D,E,F,G,A
Reuse Pair      : (A,A)
Unique Locations: 6 (B,C,D,E,F,G)
Reuse Distance  : 6

A,B,B,B,C,A
Reuse Pair      : (A,A)
Unique Locations: 2 (B,C)
Reuse Distance  : 2

Compiler Optimizations

// no strip mining
for (int i = 0; i < N; i++) {
    for (int j = 0; j < M; j++) {
        A[i][j] += B[j]; // if B is large, it may not stay in cache across iterations of i
    }
}


// strip mined loop
// S: strip size chosen such that B[jj ... jj + S - 1] fits in cache
for (int jj = 0; jj < M; jj += S) {
    for (int i = 0; i < N; i++) {
        for (int j = jj; j < min(jj + S, M); j++) {
            A[i][j] += B[j];
        }
    }
}
// no strip mining
for (int i = 0; i < N; i++) {
    for (int j = 0; j < M; j++) {
        A[i][j] += B[j]; // if B is large, it may not stay in cache across iterations of i
    }
}


// strip mined loop
// S: strip size chosen such that B[jj ... jj + S - 1] fits in cache
for (int jj = 0; jj < M; jj += S) {
    for (int i = 0; i < N; i++) {
        for (int j = jj; j < min(jj + S, M); j++) {
            A[i][j] += B[j];
        }
    }
}
// loop interchange in C (row-major)

// bad (continuous thrashing)
for (int j = 0; j < N; ++j) {
    for (int i = 0; i < M; ++i) {
        A[i][j] += B[i][j];
    }
}

// good (optimized for cache locality)
for (int i = 0; i < M; ++i) {
    for (int j = 0; j < N; ++j) {
        A[i][j] += B[i][j];
    }
}
// loop interchange in C (row-major)

// bad (continuous thrashing)
for (int j = 0; j < N; ++j) {
    for (int i = 0; i < M; ++i) {
        A[i][j] += B[i][j];
    }
}

// good (optimized for cache locality)
for (int i = 0; i < M; ++i) {
    for (int j = 0; j < N; ++j) {
        A[i][j] += B[i][j];
    }
}

Data Transformations

// assume A and B are accessed together in a loop
// and A and B (by default) happen to map to the same cache line / set

// example: no array padding
int A[1024], B[1024];
A[i] -> miss
B[i] -> miss (evicts A[i])
A[i] -> miss (evicts B[i])
...

// example: with array padding
int A[1024], pad[16], B[1024]; // A and B now live in separate lines / sets
A[i] -> miss (cold)
B[i] -> miss (cold)
A[i] -> hit
B[i] -> hit
...
// assume A and B are accessed together in a loop
// and A and B (by default) happen to map to the same cache line / set

// example: no array padding
int A[1024], B[1024];
A[i] -> miss
B[i] -> miss (evicts A[i])
A[i] -> miss (evicts B[i])
...

// example: with array padding
int A[1024], pad[16], B[1024]; // A and B now live in separate lines / sets
A[i] -> miss (cold)
B[i] -> miss (cold)
A[i] -> hit
B[i] -> hit
...
// array merging

// no merging
int B[200], A[200]
for (int i = 0; i < N; ++i)
    B[i] = ... A[i] ... // could be that B and A constantly evict eachother

// merging
int C[400]
for(int i = 0; i < N; ++i)
    C[2 * i - 1] = ... C[2 * i] ... // now the elements are close to eachother, in the same line
// array merging

// no merging
int B[200], A[200]
for (int i = 0; i < N; ++i)
    B[i] = ... A[i] ... // could be that B and A constantly evict eachother

// merging
int C[400]
for(int i = 0; i < N; ++i)
    C[2 * i - 1] = ... C[2 * i] ... // now the elements are close to eachother, in the same line

Hardware / Software Prefetching

Volatile Memory

e62fc5d341d11a94f95705972a0f8aa6.webp

Feature SRAM DRAM
Storage Mechanism Flip-flops (transistors) Capacitors
Speed Faster Slower
Density Lower Higher
Cost Higher Lower
Refresh Needed No Yes
Typical Use CPU cache Main system memory
Feature RDIMM LR-DIMM
Buffer Type Command/Address register Command/Address + Data buffer
Electrical Load Reduced Significantly reduced
Max Memory per DIMM Medium Very high
Latency Low to medium Higher
Cost Moderate Higher
Use Case Standard servers, workstations High-memory servers, databases

Virtual Memory

Non-Volatile Memory

Type Programmable? Erasable? Method of Erasure Reprogrammable?
ROM No No N/A No
PROM Yes (once) No N/A No
EPROM Yes Yes UV light Yes
EEPROM Yes Yes Electrical Yes

Very Long Instruction Word Processing

VLIW Example (no dependencies)

High-level code:
a = b + c;
d = e * f;
g = A[i];

Normal (non-VLIW, assuming one per cycle):
ADD  a, b, c
MUL  d, e, f
LOAD g, A[i]

VLIW (single-cycle, one instruction):
|    ALU    |    MUL    |     MEM     | BR  |
| ADD a,b,c | MUL d,e,f | LOAD g,A[i] | NOP |
VLIW Example (no dependencies)

High-level code:
a = b + c;
d = e * f;
g = A[i];

Normal (non-VLIW, assuming one per cycle):
ADD  a, b, c
MUL  d, e, f
LOAD g, A[i]

VLIW (single-cycle, one instruction):
|    ALU    |    MUL    |     MEM     | BR  |
| ADD a,b,c | MUL d,e,f | LOAD g,A[i] | NOP |
VLIW Example (dependencies)

High-level code:
a = b + c;
d = a * e; // depends on a

VLIW (cycles 1,2):
| ADD a,b,c | NOP | NOP | NOP |
| NOP | MUL d,a,e | NOP | NOP |
VLIW Example (dependencies)

High-level code:
a = b + c;
d = a * e; // depends on a

VLIW (cycles 1,2):
| ADD a,b,c | NOP | NOP | NOP |
| NOP | MUL d,a,e | NOP | NOP |
{ .mii // memory integer integer; memory unit can also execute integer operations
     add r1 = r2, r3
     sub r4 = r4, r5;;   // end of group
     shr r7 = r4, r12;;  // end of group
} // end of bundle
{ .mmi
     ld8 r2 = [r1];;     // end of group
     st8 [r1] = r23
     tbit p1, p2 = r4, 5 // test 5th bit in r4; result of comparison and complement stored in p1 and p2
} // end of bundle
{ .mbb
     ld8 r45 = [r55]
(p3) br.call b1 = func1  // conditional call of func1 depending on predicate register p3; b1 stores target address (instruction commits only if predicate register is 1)
(p4) br.cond Label1
} // end of bundle
{ .mfi
     st4 [r45] = r6
     fmac f1 = f2, f3
     add r3 = r3, 8;;    // end of group spanning multiple bundles
} // end of bundle
{ .mii // memory integer integer; memory unit can also execute integer operations
     add r1 = r2, r3
     sub r4 = r4, r5;;   // end of group
     shr r7 = r4, r12;;  // end of group
} // end of bundle
{ .mmi
     ld8 r2 = [r1];;     // end of group
     st8 [r1] = r23
     tbit p1, p2 = r4, 5 // test 5th bit in r4; result of comparison and complement stored in p1 and p2
} // end of bundle
{ .mbb
     ld8 r45 = [r55]
(p3) br.call b1 = func1  // conditional call of func1 depending on predicate register p3; b1 stores target address (instruction commits only if predicate register is 1)
(p4) br.cond Label1
} // end of bundle
{ .mfi
     st4 [r45] = r6
     fmac f1 = f2, f3
     add r3 = r3, 8;;    // end of group spanning multiple bundles
} // end of bundle

Data Parallel Architectures

26c5c03b9ac72de6309faf32763c8fc4.webp

Single Instruction Multiple Data (SIMD)

Feature Vector architectures SIMD CPU extensions GPUs
Era Classic supercomputers Modern CPUs Modern accelerators
Vector length Long (tens–hundreds) Short (4–16+ elements) Thousands of threads
Programmer model Explicit vectors Explicit SIMD intrinsics / compiler Threads (CUDA/OpenCL)
Flexibility Low Medium High
Best for Scientific computing Multimedia, DSP Massive data-parallel tasks

Compute Unified Device Model (CUDA)

Concept What it is
CUDA Programming model & platform for GPU computing
Thread A single execution unit
Warp 32 threads executed together (hardware level)
Thread Block A cooperative group of threads
Streaming Multiprocessor (SM) Hardware unit that runs thread blocks
Grid All blocks launched by one kernel

Multithreading

Feature Process Thread
Memory Separate Shared
Isolation Strong Weak
Creation cost High Low
Communication Slow (IPC) Fast (shared memory)
Failure impact Isolated Can crash process

Shared Memory Systems

Feature ccNUMA nccNUMA COMA
Cache coherence Hardware Software Hardware/software (implicit)
Access time Local fast, remote slow Local fast, remote slow Memory “follows” processor
Memory type Local + shared Local + shared Distributed cache only
Programming difficulty Easy Hard Medium
Example systems Modern multi-socket servers Large HPC systems Some research multiprocessors (e.g., Sequoia)

Cache Coherence

Invalidation Protocol

Directory Protocols

7ca5fbc0d300c841ddd9ef736cac17f6.webp

Memory Consistency

Consistency Model Key Property
Strict Consistency Every read sees the most recent write globally (hard to implement).
Sequential Consistency All memory operations appear in a single total order consistent with program order.
Processor Consistency Writes by a single processor are seen in order by all processors, but writes from different processors may be seen in different orders.
Weak/Relaxed Consistency Certain ordering rules are relaxed; requires explicit synchronization to enforce ordering.

Coherence Misses

Aspect True Sharing False Sharing
Cause Multiple cores access the same variable Multiple cores access different variables in the same cache line
Type of access Legitimately shared Not actually shared
Miss type Coherence miss (valid) Coherence miss (avoidable)
Fix Hard to avoid Pad data / align to cache lines

Synchronization

Atomic Operations

// test and set lock
//
// if the old value was 0, it means the lock was free -> set it
// if the old value was 1, it means the lock is taken -> wait
function test_and_set(lock):
    old_value = lock
    lock = 1
    return old_value

// compare and swap
//
// compare contents of a memory location and swap it with a new value if it matches
function compare_and_swap(address, expected, new_value):
    old_value = *address
    if old_value == expected:
        *address = new_value
    return old_value

// fetch and OP (here: add)
//
// performs an operation on a memory location atomically and returns the original value
function fetch_and_add(address, value):
    old_value = *address
    *address = old_value + value
    return old_value
// test and set lock
//
// if the old value was 0, it means the lock was free -> set it
// if the old value was 1, it means the lock is taken -> wait
function test_and_set(lock):
    old_value = lock
    lock = 1
    return old_value

// compare and swap
//
// compare contents of a memory location and swap it with a new value if it matches
function compare_and_swap(address, expected, new_value):
    old_value = *address
    if old_value == expected:
        *address = new_value
    return old_value

// fetch and OP (here: add)
//
// performs an operation on a memory location atomically and returns the original value
function fetch_and_add(address, value):
    old_value = *address
    *address = old_value + value
    return old_value

Locks

// test-and-set lock (TAS)
lock(location):
    tas register, location // copy location to register and assign 1 to location
    bnz register, lock     // compare old value to 0; if lock was taken, then keep waiting (jump back)
    ret

unlock(location):
    st location, 0
    ret
// test-and-set lock (TAS)
lock(location):
    tas register, location // copy location to register and assign 1 to location
    bnz register, lock     // compare old value to 0; if lock was taken, then keep waiting (jump back)
    ret

unlock(location):
    st location, 0
    ret
// test-and-test-and-set lock (TTAS)
lock(location):
    mov register, location      // load lock value into register
    bz  register, lock_attempt  // if the lock is not set, try to acquire
wait:
    mov register, location      // if the lock is set...
    bnz register, wait          // ...keep reading lock
lock_attempt:
    tas register, location      // classic TAS
    bnz register, lock          // fail, start over
lock_acquired:
    ret

unlock(location):
    st location, 0
    ret
// test-and-test-and-set lock (TTAS)
lock(location):
    mov register, location      // load lock value into register
    bz  register, lock_attempt  // if the lock is not set, try to acquire
wait:
    mov register, location      // if the lock is set...
    bnz register, wait          // ...keep reading lock
lock_attempt:
    tas register, location      // classic TAS
    bnz register, lock          // fail, start over
lock_acquired:
    ret

unlock(location):
    st location, 0
    ret
// load-link, store-conditional (LL/SC)
lock(location):
    ll  reg1, location  // read lock value into reg1 and monitor lock location
    bnz reg1, lock      // if lock taken; try again; otherwise, attempt to acquire
    sc  location, reg2  // conditionally store lock value into lock location ONLY IF no-one wrote to location inbetween this operation and the previous ll operation
    beqz lock           // if someone else modified location in the mean time, fail and try again
    ret

unlock(location):
    st location, 0
    ret
// load-link, store-conditional (LL/SC)
lock(location):
    ll  reg1, location  // read lock value into reg1 and monitor lock location
    bnz reg1, lock      // if lock taken; try again; otherwise, attempt to acquire
    sc  location, reg2  // conditionally store lock value into lock location ONLY IF no-one wrote to location inbetween this operation and the previous ll operation
    beqz lock           // if someone else modified location in the mean time, fail and try again
    ret

unlock(location):
    st location, 0
    ret
// ticket lock
typedef struct {
    atomic_int ticket;
    atomic_int service;
} ticket_lock_t;

void lock_init(ticket_lock_t *l) {
    atomic_init(&l->ticket, 0);
    atomic_init(&l->service, 0);
}

void lock(ticket_lock_t *l) {
    // 1. Take a ticket (increment the global ticket counter)
    int my_ticket = atomic_fetch_add(&l->ticket, 1);

    // 2. Spin until the service counter matches my ticket
    while (atomic_load(&l->service) != my_ticket);
}

void unlock(ticket_lock_t *l) {
    // 3. Increment the service counter to let the next person in
    atomic_fetch_add(&l->service, 1);
}
// ticket lock
typedef struct {
    atomic_int ticket;
    atomic_int service;
} ticket_lock_t;

void lock_init(ticket_lock_t *l) {
    atomic_init(&l->ticket, 0);
    atomic_init(&l->service, 0);
}

void lock(ticket_lock_t *l) {
    // 1. Take a ticket (increment the global ticket counter)
    int my_ticket = atomic_fetch_add(&l->ticket, 1);

    // 2. Spin until the service counter matches my ticket
    while (atomic_load(&l->service) != my_ticket);
}

void unlock(ticket_lock_t *l) {
    // 3. Increment the service counter to let the next person in
    atomic_fetch_add(&l->service, 1);
}
// array based lock
typedef struct {
  int next_ticket;
  int can_serve[NTHREADS * 16];
  int my_ticket[NTHREADS * 16];
} lock_t;

void lock(lock_t* lck, int tid) {
    // 1. Assign ticket number to arriving thread
    lck->my_ticket[tid * 16] = atomic_fetch_add(lck->next_ticket, 1) % NTHREADS;

    // 2. Wait until ticket number is ready to go
    while (lck->can_serve[lck->my_ticket[tid * 16] * 16] != 1);
}

void unlock(lock_t* lck, int tid) {
    // 3. Release current thread's ticket and go to next ticket number
    lck->can_serve[lck->my_ticket[tid * 16] * 16] = 0;
    lck->can_serve[(lck->my_ticket[tid * 16] + 1) % NTHREADS * 16] = 1;
}
// array based lock
typedef struct {
  int next_ticket;
  int can_serve[NTHREADS * 16];
  int my_ticket[NTHREADS * 16];
} lock_t;

void lock(lock_t* lck, int tid) {
    // 1. Assign ticket number to arriving thread
    lck->my_ticket[tid * 16] = atomic_fetch_add(lck->next_ticket, 1) % NTHREADS;

    // 2. Wait until ticket number is ready to go
    while (lck->can_serve[lck->my_ticket[tid * 16] * 16] != 1);
}

void unlock(lock_t* lck, int tid) {
    // 3. Release current thread's ticket and go to next ticket number
    lck->can_serve[lck->my_ticket[tid * 16] * 16] = 0;
    lck->can_serve[(lck->my_ticket[tid * 16] + 1) % NTHREADS * 16] = 1;
}

27eaf78cc268e91ed3973869cd053ea1.webp

Transactions

Chip Multiprocessors

Shared LLC

799b0af439dc2a04e75f8e7da1d8f1ef.webp

Private LLC

033a420c93e215453d5681feaafaa58f.webp

OpenMP

// sections
#pragma omp parallel sections
{
    #pragma omp section
    {
        compute_A();
    }

    #pragma omp section
    {
        compute_B();
    }

    #pragma omp section
    {
        compute_C();
    }
} // implicit barrier
// sections
#pragma omp parallel sections
{
    #pragma omp section
    {
        compute_A();
    }

    #pragma omp section
    {
        compute_B();
    }

    #pragma omp section
    {
        compute_C();
    }
} // implicit barrier

Distributed Memory Systems

3736091d2d97586e4147a00de80fc567.webp

Packet (128 bytes)
 ├─ Flit 0 (header)
 ├─ Flit 1 (payload)
 ├─ Flit 2 (payload)
 └─ Flit 3 (tail)
Packet (128 bytes)
 ├─ Flit 0 (header)
 ├─ Flit 1 (payload)
 ├─ Flit 2 (payload)
 └─ Flit 3 (tail)
Flit = 128 bits
Link width = 32 bits

→ 1 flit = 4 phits
Flit = 128 bits
Link width = 32 bits

→ 1 flit = 4 phits

Network Flow Control

Network Topologies

Topologies

Network Interface