# Embarrassingly parallel A problem is **embarrassingly parallel** if it can be split into independent pieces of work that require no communication or synchronization between them while running. Each piece can be handed to a different core, thread, or machine, computed entirely on its own, and the results simply collected at the end. The name reflects that there's nothing clever involved in the parallelization itself, the difficulty of a "hard" parallel problem (data dependencies, synchronization, load balancing across uneven work) is largely absent. ```c #pragma omp parallel for for (int i = 0; i < N; i++) { result[i] = expensive_function(input[i]); // no dependency between iterations } ``` ## Why this maps to Gustafson, not Amdahl Embarrassingly parallel workloads are the best case for both [[amdahls-law|Amdahl's]] and [[gustafsons-law|Gustafson's]] models, since the sequential fraction $1-p$ is close to zero: nearly all the work is the independent per-item computation, with only trivial serial overhead (splitting the input, collecting results). This is exactly the regime where adding more cores keeps paying off almost linearly, which is why Monte Carlo simulations, parameter sweeps, and per-pixel image processing (all classic embarrassingly parallel examples) scale so well on large clusters. ## Where the "embarrassing" part still bites Independence between pieces doesn't guarantee equal-sized pieces. If some inputs take far longer to process than others (a ray-tracing scene where some pixels hit complex geometry and others hit empty background), a naive equal split leaves fast workers idle while waiting on the slowest one. This is a **load balancing** problem, not a synchronization problem, and it's usually solved by dynamic scheduling (a shared work queue that idle workers pull the next chunk from) rather than a static upfront split, exactly the difference between OpenMP's `schedule(static)` and `schedule(dynamic)` clauses.