3

The Efficiency Bottleneck of Traditional Serial CPU Loops

AI999第4课:现代计算底座与张量化并行演化
00:00

Evolutionary processes depend on population diversity, and diversity means population size and the number of evaluations grow multiplicatively. When candidate evaluations reach the tens of thousands,traditional serial CPU loopsbecome the narrowest segment of the entire pipeline: they process only one individual at a time, leaving the hardware's parallel capability almost entirely idle.

Serial CPU Loops vs. Batch Parallelism: Total Time Grows with the Number of Candidate EvaluationsSerial one-by-one processingBatch parallel processingWall-clock time (normalized)≈ 100 sSerial: near-linear growthParallel: stepwise growthSerial one-by-one: fetch individual → decode → evaluate → write backAdjacent iterations cannot overlap; parallel units sit idle most of the timeBatch parallel: organized by batch; time is determined by the number of batches10³ evals10⁴ evals10⁵ evalsNumber of candidate evaluationsNote: Darker segments represent scheduling and data-transfer overhead. For the same workload, parallel time growth is driven mainly by the number of batches rather than the number of individuals.

One at a Time: The Execution Model of Serial Loops

The most straightforward implementation treats the entire population as a list and pulls out individuals one by one in a loop: fetch individual → decode into concrete parameters → call the evaluation function → write back the fitness. Adjacent iterations can barely overlap: until the evaluation result returns, the write-back cannot proceed; until the write-back completes, there is nowhere to put the next individual's result. As a result, parallel units such as multi-core CPUs, SIMD, and GPUs sit idle most of the time, watching a single individual run through the pipeline.

Where Does the Overhead Actually Come From?

  • Linearly ballooning evaluation counts: total evaluations are roughly population size × number of generations. At the 10⁵ scale, serial wall-clock time grows approximately linearly.
  • Interpreter-level one-by-one execution: per-individual looping, bounds checking, and type dispatch introduce a fixed yet substantial constant overhead.
  • Non-contiguous memory access and data movement: individuals fetched one by one are often non-contiguous in memory, resulting in low cache hit rates and repeatedly incurred transfer costs.
  • Synchronization and scheduling: to fetch the next individual, the execution flow must repeatedly pause and resume.

Translating Scale into Time

Take a population of 1000 over 100 generations as an example: roughly 100,000 candidate evaluations in total. At an average of 1 ms per evaluation, the evaluation step alone takes about 100 seconds when run serially, and this does not yet include operator computation or scheduling overhead. If restarts are increased from 1 to 5 to maintain diversity, the cost rises approximately linearly to about 500 seconds. For the same workload organized into batches and handed to parallel hardware, wall-clock time is determined mainly by the number of batches rather than the number of individuals.

When Does This Bottleneck Narrow?

Boundary conditions matter just as much: when a single evaluation is extremely cheap (microsecond-level) or the population is very small (fewer than a hundred), scheduling and memory overhead may outweigh computation, the gap between serial and parallel narrows substantially, the marginal benefit of tensorization diminishes, and the bottleneck shifts to scheduling granularity and memory bandwidth. So whether it is worth reworking the execution model must be assessed by weighing evaluation cost together with scale.

A Structural Bottleneck, Not a Code Defect
The efficiency bottleneck of serial CPU loops is at the execution-model level: localized code tuning cannot eliminate it. To truly solve it, you need to refactor one-by-one into batch-by-batch — batching, tensorization, and parallel scheduling — which also becomes the direct motivation for the tensorized computation graph design that follows.