Why parfor Loops Often Run Slower Than Standard for Loops

The parfor construct in the Parallel Computing Toolbox splits independent loop iterations across worker processes (pool workers). However, converting a standard for loop to parfor frequently results in slower execution or memory exhaustion errors.

This slowdown occurs because parallel workers run in separate process address spaces. For every iteration or chunk of iterations, MATLAB must serialize data from the client, transfer it across inter-process communication (IPC) sockets, deserialize it on the worker, execute the iteration, and serialize the results back. If the computation time per iteration is under 10 milliseconds, communication latency completely dominates computation, yielding negative speedup.

The Five Variable Classifications in parfor

To eliminate memory serialization bottlenecks, engineers must identify how MATLAB's static code analyzer categorizes every variable inside the parallel loop:

  • Sliced Variables: Arrays where each worker accesses only disjoint slices corresponding to the loop index (such as A(i, :)). Sliced variables are optimal because each worker receives only its assigned slice.
  • Broadcast Variables: Arrays defined outside the loop whose contents do not change, but are read inside the loop. The client sends a complete copy of the array to every worker. If an array is 500 MB and you run 12 workers, MATLAB transmits 6 GB across IPC channels.
  • Reduction Variables: Variables that accumulate values across iterations using commutative operators (such as sum = sum + x or [minVal, minIdx] = min(...)).
  • Temporary Variables: Variables created and destroyed inside the loop body. They do not persist across iterations and require zero communication.
  • Loop Variables: The index variable governing loop execution.

Rules for Effective Variable Slicing

To ensure MATLAB recognizes an array as a sliced variable:

  1. The first-level indexing expression must be the loop variable itself: Y(i) or Y(i, :). Expressions like Y(i + 1) or Y(idx(i)) cannot be resolved statically, causing MATLAB to treat the entire array as a broadcast variable.
  2. Do not access the same sliced array in both sliced and non-sliced contexts within the same parallel loop.
  3. Avoid passing large structures into parfor. If a worker needs only one field from a large configuration struct, extract that field into a local sliced array before the loop.

parfor vs. parfeval: Synchronous vs. Asynchronous Scheduling

While parfor is synchronous and blocks the client until all iterations finish, parfeval runs functions in the background without blocking. Key distinctions include:

Feature parfor parfeval
Execution Model Synchronous (blocking) Asynchronous (background queue)
Work Scheduling Static chunking per worker Dynamic queue-based dispatch
Iteration Heterogeneity Stalls if one iteration takes 10x longer Workers immediately take next task from queue
Progress Monitoring Requires ParallelDataQueue Native fetchNext completion callbacks

Leveraging GPU Acceleration with gpuArray

When operations involve dense linear algebra, matrix multiplies, 2D/3D convolutions, or FFTs, GPU vectorization provides far greater speedup than multicore CPU workers. Wrapping variables with gpuArray(X) routes execution directly to NVIDIA CUDA tensor/streaming multiprocessors, executing millions of data points simultaneously without IPC socket latency.