~ /phase-1 /results
Phase I · Results

Four processes, never faster.

Going from 1 → 4 processes did not reduce execution time in any configuration. In most cases runtime went up, because process creation and synchronization overhead outweighed the parallel work.

Collected 2026-02-09Ubuntu 24.04.3 · ARM64GCC 11.4.0 -Wallσ ≤ 0.00094 s

Summary#

1.00×
Best speedup, at N = 1200 (a tie)
0.33×
Worst speedup, at N = 1800 (3× slower)
200%
Peak overhead factor, 4 vs 1 process
18
Timed runs, 3 per configuration
average seconds · 1 vs 4 processes PROCS = 1PROCS = 4
N = 1200300 rows/proc
0.0016
1.00×
N = 1800450 rows/proc
0.00100.0030
0.33×
N = 2400600 rows/proc
0.00130.0033
0.39×

Raw execution times#

Three runs per configuration, with the average and standard deviation.

N PROCS Run 1 (s) Run 2 (s) Run 3 (s) Avg (s) Std dev
1200 1 0.001 0.001 0.003 0.0016 0.00094
1200 4 0.002 0.002 0.001 0.0016 0.00047
1800 1 0.001 0.001 0.001 0.0010 0.00000
1800 4 0.003 0.003 0.003 0.0030 0.00000
2400 1 0.002 0.001 0.001 0.0013 0.00047
2400 4 0.004 0.003 0.003 0.0033 0.00047

Derived metrics#

For each fixed N, with T₁ the 1-process average and Tₚ the 4-process average:

Speedup#

T₁ / Tₚ. Values above 1 mean the parallel version was faster.

Efficiency#

Speedup / p. The share of ideal scaling achieved with p processes.

Overhead factor#

(Tₚ − T₁) / T₁. How much extra time the parallel version took.

N Speedup (4 vs 1) Efficiency (P = 4) Overhead factor
1200 1.00× 0.25 0%
1800 0.33× 0.083 200%
2400 0.39× 0.098 154%

At N = 1800 and N = 2400, speedup is below 1: four processes were slower than one. This is negative scaling.

More processes#

  • N = 1200: a tie, 0.0016 s vs 0.0016 s
  • N = 1800: 3× slower with 4 processes
  • N = 2400: about 2.5× slower with 4 processes

Larger N#

With one process, times are tiny and don't grow steadily at this timer resolution. With four, runtime rises clearly from N = 1200 to 1800 to 2400.

Variability#

The standard deviations are small next to the gaps between 1 and 4 processes at N = 1800 and 2400, so the slowdown is consistent, not noise.

Why four processes were slower#

Process creation#

fork() has a real cost: process metadata, scheduling and memory mapping. It shows most when the total runtime is very small.

Synchronization#

The parent waits for every child with wait(), so the total time includes coordination overhead.

Scheduling and context switching#

More runnable processes mean more context switches. For fine-grained work, that cost can outweigh the benefit.

Memory behaviour#

With large arrays, memory bandwidth and cache behaviour can dominate. Multiple processes may add contention instead of saving time.

Anomalies and measurement notes#

Observed anomalies

  • With N = 1800, P = 1 the program ran faster than with N = 1200, P = 1.
  • The single-process timings are very small, so timer resolution and VM noise can affect them.

Measurement considerations

  • clock() measures CPU time, not wall-clock time.
  • Near one millisecond, small effects from the scheduler, the VM or the cache can make results non-monotonic.
  • Even so, the 4-process slowdowns at N = 1800 and 2400 are large and consistent.

Conclusion#

Simple process-based parallelism with fork() and wait() was inefficient at the tested sizes (N ≤ 2400). Overhead outweighed the computation, so four processes produced negative scaling.

The results support a core OS principle: parallelism only helps when the workload is large enough to pay back the cost of managing processes.

Data collected
2026-02-09
Environment
Ubuntu ARM64
Compiler
GCC 11.4.0
Timer
clock()