Skip to content

Performance: C

xcc compiles C (C programs): it reads a .c file through clang’s front end and generates the code itself. These are the seven par benchmarks as plain C, the same files for every compiler, timed on one machine: an AMD Ryzen 9 9955HX (32 hardware threads) running Linux, with xcc 0.87, GCC 15.2 and clang 21.1.

The two sections below measure different things and are never mixed: one thread is the code each core runs; every thread adds how a compiler spreads a loop across the cores.

Each compiler builds the plain C with no parallel code: xcc -O3 against gcc -O3 -march=native and clang -O3 -march=native.

Milliseconds; the median of up to fifteen runs.

benchmarkxccGCCclangxcc against GCCxcc against clang
mandel_deep859356236584346.5× faster6.8× faster
mandelbrot56.23263345.8× faster5.9× faster
md52293872121.69× faster1.08× slower
md5_mask1892771761.47× faster1.07× slower
nbody6.0227.396.14.5× faster16.0× faster
perlin84.164.474.81.31× slower1.12× slower
saxpy3.423.353.591.02× slower1.05× faster
geometric mean2.3× faster2.4× faster

The same C, run across all 32 threads:

  • xcc: xcc -O3 --par-auto on the unchanged files. --par-auto finds the loops that can run in parallel and runs them as par blocks; here they are kept on the CPU (XC_PAR=cpu), so this is CPU against CPU.
  • GCC and clang: -O3 -march=native -fopenmp, on a copy of each file with one #pragma omp parallel for line (with its reduction clause where the loop has one) before the timed loop: the work a programmer does to get OpenMP’s threads.

Milliseconds; the median of up to fifteen runs. xcc is ahead of both on 5 of the 7.

benchmarkxccGCCclangxcc against GCCxcc against clang
mandel_deep354205021475.8× faster6.1× faster
mandelbrot2.7412.313.54.5× faster4.9× faster
md514.016.115.21.15× faster1.09× faster
md5_mask9.9712.013.41.21× faster1.34× faster
nbody0.641.289.782.0× faster15.3× faster
perlin6.344.377.031.45× slower1.11× faster
saxpy2.322.192.251.06× slower1.03× slower
geometric mean1.74× faster2.6× faster

The same programs on GPUs, where --par-auto sends them by default, are on Performance: GPU.

Every program prints its checksum and its best time over its own repeats; each build was run several times, round-robin with the others, the machine idle before each round, and the figure is the median of those runs’ best times. The spread from run to run is wide for all three compilers on this machine (several tens of percent on the shortest programs), which is why one run is never the figure. Every build of a program gave the same checksum.

The C sources and their OpenMP copies are in xcc-c-bench-sources-0.87.tar.bz2, and in the repository’s benchmark/par/c/ and benchmark/par/c/openmp/; benchmark/par/c_run.py repeats the whole measurement.