Heterogeneous computing concepts
What Makes Computing "Heterogeneous"?
Key characteristics:
- Different processor types (CPU + GPU, CPU + FPGA, CPU + DSP, etc.)
- Asymetric capabilities (not just different speeds, but different strengths)
- Task partitioning (dividing work based on processor strengths)
- Explicit data movement between processor memories (often the bottleneck)
WHAT distinguishes it from homogeneous multicore?
- Homogeneous:8 identical CPU cores, all run same instruction set
- Heterogeneous: 4 CPU cores + 1 GPU with2048 CUDA cores + 1 Neural Processing Unit
The Hardware Architecture
CPU: The Control Master
Design philosophy: Optimize for latency of individual tasks
HOW it achieves this:
- Large caches (MB range) → reduce memory access time
- Complex out-of-order execution → hide instruction dependencies
- Branch prediction → speculate on control flow
- Few powerful cores (4-64 typically)
Best for:
- Sequential algorithms
- Irregular memory access patterns
- Complex control flow (many if/else, function calls)
- Operating system tasks, coordination
GPU: The Throughput Engine
Design philosophy: Optimize for throughput of many parallel tasks
HOW it achieves this:
- Thousands of simple cores (ALUs)
- Small caches per core
- SIMT execution model (Single Instruction, Multiple Threads)
- Massive memory bandwidth (hundreds of GB/s)
Best for:
- Data-parallel operations (same operation on millions of data points)
- Regular memory access patterns (coalesced reads/writes)
- Graphics rendering, matrix operations, simulations
Specialized Accelerators
Accelerators are fixed-function or configurable hardware designed for one class of problems.
Types:
- TPU (Tensor Processing Unit): Matrix multiply-accumulate operations for neural networks
- FPGA (Field-Programmable Gate Array): Reconfigurable logic blocks for custom datapaths
- DSP (Digital Signal Processor): Optimized for filtering, FFT, convolution
- Crypto accelerators: AES encryption, SHA hashing
WHY they exist: For narrow domains, hardwired logic is 10-100x more energy-efficient than general-purpose cores.
The Programming Model Challenge
Memory Hierarchy Mismatch
Total execution time:
WHY this matters: If is small, data transfer dominates!
Derivation of the break-even point:
Let:
- = PCIe bandwidth (GB/s)
- = data size (GB)
- = CPU FLOPS
- = GPU FLOPS
- = work (total FLOPS needed)
Time on CPU alone:
Time on heterogeneous system:
(Factor of 2 because data goes CPU→GPU→CPU)
Break-even when :
WHY THIS STEP? We isolate the data movement cost on the left. The right side is the computational advantage of GPU.
Interpretation: You need enough work (W) relative to data size (D) to overcome transfer overhead. This is called arithmetic intensity.
Transfer1 GB of data:
To break even, GPU compute time must save at least 0.0625s:
Work needed:
WHY? If the task requires 69 billion floating-point operations, GPU saves enough time to justify the transfer cost.
Arithmetic intensity:
Practical insight: Matrix-matrix multiply (O(n³) work, O(n²) data) is great for GPUs. Vector addition (O(n) work, O(n) data) is terrible.
Task Partitioning Strategies
Three models:
- Offload model: CPU does setup/control, GPU does compute kernels, CPU does post-processing
- Pipelined model: CPU stage 1 → GPU stage 2 → CPU stage 3, overlapping different data
- Collaborative model: CPU and GPU work on different parts of the same problem simultaneously
Step-by-step with WHY:
- CPU reads image1 from disk → CPU has file system access
- CPU transfers image 1 to GPU → GPU needs data in VRAM
- GPU applies filters to image 1 → Massively parallel pixel operations
- CPU reads image 2 (overlapped with step 3) → Hide transfer latency
- GPU returns processed image 1to CPU → CPU will write to disk
- CPU writes image 1 to disk (overlapped with GPU processing image 2)
WHY pipelined? Each stage overlaps with others. Total time ≈ max(read, transfer, compute, write) ×1000, not their sum.
Formula for pipeline efficiency:
If stages take time and we process items:
Sequential time:
Pipelined time:
WHY? First item pays full latency, then we sustain at the rate of the slowest stage.
Speedup:
Amdahl's Law in Heterogeneous Systems
Original Amdahl's Law assumes homogeneous speedup. We need to extend it.
Let:
- = fraction of code that's serial (CPU-only)
- = fraction that's paralelizable (can use GPU)
- = speedup of GPU over CPU for parallel work
Derivation from scratch:
Original execution time (CPU only): (normalized)
New execution time:
- Serial part: (no speedup)
- Parallel part: (runs times faster)
- Data transfer overhead: per kernel launch
WHY THIS STEP? Serial work is unaffected. Parallel work benefits from GPU. But we pay transfer tax.
Overall speedup:
Critical insight: Even if , speedup is bounded by
WHY only 11x when GPU is 50x faster?
- 5% serial bottleneck
- 2% transfer overhead
- These fixed costs dominate!
What if we eliminate transfer overhead (unified memory)?
Only 3.3x improvement from eliminating transfers! The5% serial code is the real killer.
Common Heterogeneous Patterns
Map Pattern (Embarrassingly Parallel)
Definition: Apply same function to every element independently.
CPU code:
for (int i = 0; i < N; i++) {
output[i] = f(input[i]);
}Why GPU wins: Each iteration is independent, perfect for thousands of threads.
Arithmetic intensity: Low (O(1) work per byte unless f is complex.
Reduce Pattern (Parallel with Coordination)
Definition: Combine array elements with associative operator (sum, max, etc.)
Sequential:
Parallel tree reduction:
Derivation of work/span:
Work (total operations): Still operations (can't reduce this)
Span (critical path):
- Level 1: pairs combine in parallel → depth 1
- Level 2: pairs combine → depth 2
- ...
- Level : final combine
WHY? Each level halves the data, takes one step.
Speedup with processors:
On GPU: Overhead is high due to synchronization between levels. Better to use warp-level primitives.
GPU (tree reduction):
- Launch kernel with 1024 threads per block, 976 blocks
- Each thread sums 1024 elements → 976 partial sums
- Reduce976 sums on CPU (small enough)
- Time: ~0.5ms GPU compute + 0.5ms transfer = 1ms total
Speedup: 3x (not great because low arithmetic intensity)
WHY not faster? Each element read once, added once. Ratio of 1 FLOP per 4 bytes (assuming float). PCIe transfer time dominates.
Scan Pattern (Prefix Sum)
Definition: Output[i] = input[0] ⊕ input[1] ⊕ ... ⊕ input[i]
Applications: Stream compaction, radix sort, resource allocation
Parallel algorithm (work-efficient):
Step 1 - Upsweep (build tree):
for d = 0 to log₂(n) - 1:
for each k = 0 to n/(2^(d+1)) - 1 in parallel:
idx = (k+1) * 2^(d+1) - 1
a[idx] = a[idx - 2^d] + a[idx]
WHY THIS STEP? Build a binary tree of partial sums, moving up levels.
Step 2 - Downswep (propagate sums):
a[n-1] = 0 // identity
for d = log₂(n) - 1 down to 0:
for each k in parallel:
idx = (k+1) * 2^(d+1) - 1
temp = a[idx - 2^d]
a[idx - 2^d] = a[idx]
a[idx] = a[idx] + temp
WHY THIS STEP? Propagate the accumulated sum down, maintaining the inclusive scan property.
Work: - same as sequential! Span: - logarithmic depth GPU advantage: Exploits paralelism without extra work.
Programming Models & APIs
Popular models:
- CUDA/HIP: Low-level, explicit control (NVIDIA/AMD GPUs)
- OpenCL: Cross-platform, vendor-neutral
- OpenMP offload: Pragma-based, implicit transfers
- SYCL: C++ template-based, single-source
- Vulkan Compute: Graphics API with compute shaders
Step 2 - Copy data to device:
cudaMemcpy(d_input, h_input, N*sizeof(float),
cudaMemcpyHostToDevice);WHY? Transfer over PCIe bus.
Step 3 - Launch kernel:
int threads_per_block = 256;
int blocks = (N + 255) / 256;
kernel<<<blocks, threads_per_block>>>(d_input, d_output, N);WHY THIS SYNTAX? <<<blocks, threads>>> specifies grid dimensions. GPU schedules these threads.
Step 4 - Copy result back:
cudaMemcpy(h_output, d_output, N*sizeof(float),
cudaMemcpyDeviceToHost);Step 5 - Free memory:
cudaFree(d_input);
cudaFree(d_output);Total overhead: Allocations + 2 transfers + kernel launch latency. This is why arithmetic intensity matters!
Power Efficiency: The Real Win
Derivation of energy advantage:
Let
- = CPU power (watts)
- = GPU power when active (watts)
- = GPU idle power (watts)
- = time on CPU
- = time on GPU (compute only)
- = transfer time
Energy on CPU:
Energy on heterogeneous system:
WHY THIS FORM? CPU is active during transfers and serial code. GPU is active during compute. GPU idles during transfers.
For pure parallel workload ():
If (speedup ):
Energy efficiency gain:
WHY IMPORTANT? For data centers, energy cost dominates over hardware cost!
GPU Setup:
- NVIDIA A100, 400W TDP, 10 TFLOPS (20× faster)
- Time: 0.5 hours + 5 min overhead
- Energy: 400W × 2100s = 0.84 MJ = 0.23 kWh
Energy saving: 85%!
WHY? Even though GPU uses more power, it finishes 20× faster, spending most time idle. Total energy is 6.5× lower.
Cost: At 0.18, GPU costs 150.
Advanced Concepts
Cache Coherence in Heterogeneous Systems
Problem: CPU and GPU have separate memory spaces (disagregated memory). If both access the same data, copies can diverge.
Solutions:
- Manual coherence: Programmer ensures transfers after writes
- Unified memory: Hardware/driver maintains coherence (CUDA unified memory)
- Cache-coherent interconnect: AMD Infinity Fabric, Intel CXL
Trade-off: Automatic coherence adds latency (coherence protocol traffic).
Dynamic Task Scheduling
Challenge: How to decide CPU vs GPU at runtime when workload is unknown?
Approach - Work stealing:
- Both CPU and GPU pull tasks from a shared queue
- GPU takes tasks if queue is large (amortize overhead)
- CPU takes tasks if queue is small (low latency)
Formula for threshold:
Execute on GPU if:
WHY? Need enough work to overcome transfer cost.
FPGA vs GPU Trade-offs
| Aspect | FPGA | GPU |
|---|---|---|
| Latency | Microseconds (hardwired datapath) | Milliseconds (kernel launch) |
| Throughput | Lower peak | Higher peak |
| Power | 10-50W | 200-400W |
| Flexibility | Reconfigurable (minutes) | Fully programmable (instant) |
| Best for | Fixed pipelines, low-latency | Data-parallel, training |
Example: High-frequency trading uses FPGAs (10μs latency matters). AI training uses GPUs (throughput matters).
Mistakes & Misconceptions
Why it feels right: GPUs have more cores and higher FLOPS.
The fix: GPUs excel at specific patterns (data parallelism, high arithmetic intensity). For serial code, complex control flow, or small datasets, CPU is faster. The transfer overhead can make GPU slower even for parallel work if the dataset is small.
Litmus test: Is your workload:
- Massively parallel? (Yes needed)
- Regular memory access? (Yes needed)
- High arithmetic intensity (>10 FLOP/byte)? (Yes needed)
- Large dataset (>10MB)? (Yes needed)
All four must be true for guaranteed GPU win.
Why it feels right: More paralelism should mean more speed.
The fix:
- Amdahl's Law: Serial portions limit speedup
- Memory bandwidth: If memory-bound, cores sit idle waiting for data
- Occupancy: GPU needs many threads per core to hide latency (need 10,000+ threads for full utilization, not 2048)
- Coordination overhead: Synchronization between threads adds cost
Reality: 10-100× speedup is typical for well-suited problems, not 1000×.
Why it feels right: Unified memory abstracts away explicit transfers.
The fix: Unified memory still moves data over PCIe, just automatically. You still pay the latency! Worse, page faults (when GPU touches CPU page) can be slower than explicit batched transfers. Unified memory is convenient, not free.
Best practice: Prefetch large blocks with cudaMemPrefetchAsync to retain control.
Why it feels right: FPGAs have lower power and can be optimized per-algorithm.
The fix:
- Development time: FPGA design takes months (RTL coding). GPU kernel takes days.
- Flexibility: Changing FPGA logic requires resynthesis (minutes-hours). GPU recompiles instantly.
- Peak performance: Modern GPUs have higher throughput for data-parallel tasks.
Use FPGAs when: Latency is critical, power is scarce, and the algorithm is stable (won't change often).
Connections
- CPU Architecture and Pipeline: Understanding CPU design motivates why GPUs are architected differently
- Memory Hierarchy and Caching: Explains why data movement dominates in heterogeneous systems
- Parallel Programming Models: Thread-level parallelism concepts extend to GPU thread blocks
- Amdahl's Law and Scalability: Directly applies to heterogeneous speedup analysis
- Power and Energy Optimization: Heterogeneous computing's primary advantage
- SIMD and Vector Processing: GPU SIMT is an evolution of SIMD principles
- DMA and I/O Controllers: Similar asynchronous data transfer concepts
- Rofline Performance Model: Tool for analyzing if workload is compute- or memory-bound on accelerators
Recall Explain to a 12-Year-Old
Imagine you're doing homework. Some problems need you to think really hard (like a tricky word problem) — that's what your brain (the CPU) is great at. But some problems are just doing the same simple thing over and over, like coloring in a thousand squares with the same color. For that, you could give10 friends (GPU cores) crayons and finish 10× faster!
Heterogeneous computing is like being smart about when you do the thinking yourself (CPU) versus when you hand out simple tasks to all your friends (GPU). The trick is: if it takes longer to explain the task and hand out the crayons than just doing it yourself, it's not worth it! That's why we only use our GPU friends for BIG tasks with lots of repetition.
Some special tools (accelerators) are like those one-job machines — a bread slicer only slices bread, but it's the absolute fastest at it. Same idea with TPUs for AI and FPGAs for specific jobs.
Flashcards
#flashcards/hardware
What is heterogeneous computing? :: A computing architecture that uses two or more different types of processors (e.g., CPU + GPU, CPU + FPGA) with distinct capabilities, working together by partitioning tasks based on each processor's strengths.
What is the primary advantage of GPUs over CPUs?
What is arithmetic intensity and why does it matter for GPU speedup?
Derive the heterogeneous Amdahl's Law speedup formula :: For serial fraction , parallel fraction , GPU speedup , and transfer overhead : Original time =1. New time = . Therefore, . This shows serial code and transfer overhead limit speedup even with infinite GPU performance.
What is the break-even condition for using a GPU?
What are the three task partitioning models in heterogeneous computing?
Why do GPUs require thousands of threads for full utilization?
What is the work and span of parallel tree reduction?
What is the primary advantage of heterogeneous computing in data centers?
When should you use an FPGA instead of a GPU?
Concept Map
Hinglish (regional understanding)
Intuition Hinglish mein samjho
Hinglish (regional understanding)
Intuition Hinglish mein samjho
Dekho, heterogeneous computing ka matlab hai kiek hi system mein alag-alag types ke processors use karna, jaise CPU, GPU, ya special accelerators sath mein kaam karein. Socho jaise kitchen mein different tools hote hain na - blender smoothie ke liye, knife cutting ke liye, rice cooker sirf chawal ke liye. Exactly waisa hi! CPU bohot versatile hai, complex sequential tasks handle karta hai jaise operating system ya control flow. GPU hai to massively parallel kaam ke liye perfect, jaise millions of numbers ko ek sath process karna ya graphics rendering. Aur TPU, FPGA jaise specialized accelerators ek specific kaam ko super efficiently karte hain. Kyunki koi ek processor sab kuch efficiently nahi kar sakta - CPU latency mein best hai, GPU throughput mein master hai.
Iska real benefit kya hai? Performance-per-watt bohot drastically improve ho jata hai certain workloads ke liye. Jaise agar tumhe 1 million numbers process karne hain with same operation, to CPU se sequential karo to50ms lagega, but GPU ke2048 cores use karo to sirf 5ms - that's 10x speedup! Lekin challenge bhi hai: different processors ka apna memory hota hai, to data transfer CPU se GPU tak time leta hai. Agar computation chhota hai aur data transfer zyada, to benefit kam ho jata hai. Isliye programmer ko samajhna padta hai ki kaunsa kaam CPU pe best rahega aur kaunsa GPU pe, aur data movement ko minimize kaise karein. Yeh approach modern AI, gaming, scientific computing mein essential hai kyunki har processor apni strength mein contribute karta hai.
Hinglish (regional understanding)
Intuition Hinglish mein samjho
Dekho beta, heterogeneous computing ka core idea bilkul simple hai — ek hi system mein hum alag-alag types ke processors use karte hain, aur har processor apne particular kaam mein master hota hai. Jaise kitchen mein tum blender se bread nahi kaatte aur knife se smoothie nahi banate, waise hi yahan CPU ek Swiss Army knife hai jo complex sequential tasks aur decision-making (if-else, control flow) sambhalta hai, GPU ek industrial food processor jaisa hai jo ek saath hazaaron simple calculations parallel mein karta hai, aur specialized accelerators (jaise TPU, FPGA) single-purpose tools hain jo ek hi kaam ko super-efficiently karte hain. Point yeh hai ki koi bhi ek processor sabhi kaam ke liye best nahi hota — CPU latency ke liye optimize hota hai (matlab ek task jaldi khatam ho), GPU throughput ke liye (matlab bahut saare tasks ek saath ho).
Ab yeh matter kyun karta hai? Kyunki alag-alag processors ko combine karke tumhe ek particular workload par orders of magnitude better performance aur energy efficiency milti hai. Jaise agar tumhe 1 million numbers process karne hain jisme same operation baar-baar lagta hai, toh CPU shayad 50ms lega par GPU sirf 5ms — matlab 10x speedup! Isiliye aaj ke phones, laptops, aur data centers sabmein CPU + GPU + neural processing unit saath mein kaam karte hain, taaki har task uss hardware par chale jo uske liye sabse achha hai.
Lekin ek important catch bhi hai jo tumhe yaad rakhna chahiye — data movement ka cost. Jab CPU se GPU ko data bhejte hain aur wapas laate hain, uss transfer mein bhi time lagta hai. Toh total time = data bhejne ka time + GPU par compute ka time + data wapas laane ka time. Agar actual computation chota hai par data bahut bada hai, toh yeh transfer hi bottleneck ban jaata hai aur GPU ka fayda hi nahi milta. Isiliye smart programming mein hum tabhi GPU use karte hain jab computation kaafi heavy ho ki transfer overhead worth it ho jaaye — yahi break-even point ka concept hai, aur yahi heterogeneous programming ki asli challenge hai.