Measurements on a Loongson 3A6000, recorded on 2026-09-28. Sources and binaries were isolated for the run; source checksums matched the local copies after result retrieval. | Property | Value | |---|---| | CPU | Loongson 3A6000, LoongArch64 | | Topology | One socket, four cores, two threads per core; eight logical CPUs | | Reported maximum frequency | 2,000 MHz | | Run affinity | Logical CPU 2; SMT sibling 3 | | OS | Kylin Linux Desktop V10 SP1; Linux 5.4.18-167-generic | | Compiler | GCC 15.2.0, `/opt/loongson-gcc-15.2.0/bin/g++` | | Flags | `-std=c++26 -O3 -DNDEBUG -march=native -fno-lto` | | Native target | `-march=la664 -mtune=la664 -msimd=lasx` | | Scalar extra flags | `-fno-tree-loop-vectorize -fno-tree-slp-vectorize` | | C++ runtime search path | `/opt/loongson-gcc-15.2.0/lib`, embedded as executable RPATH | | Governor | `performance`, already set on the host; no power settings changed | | Timing | Same 15-sample, 4,096-input, shuffled-case harness as the M4 and Xeon runs | Median nanoseconds per value: | Operation | Normal optimization | Vectorization disabled | |---|---:|---:| | Runtime `/` | 0.905720 | 5.817311 | | Literal `/ 3` | 0.094703 | 5.817084 | | Precomputed `Divide` | 0.345486 | 1.391714 | The precomputed class achieved 2.62 times the throughput of runtime division in the normal build, using 61.9% less time per value. Its scalar version achieved 4.18 times the throughput of scalar runtime division. The normal runtime loop uses LASX `xvdiv.w`, with eight signed 32-bit elements per instruction and four such instructions per main loop iteration. It has an LSX `vdiv.w` path for smaller batches and a scalar `div.w` tail. At 4,096 elements, the measured loop runs the LASX path. The scalar build uses `div.w` throughout. The constant-divisor vector loop uses `xvmuh.w` plus sign correction. With vectorization disabled, GCC 15.2 retained `div.w` even for the literal divisor 3. The similar scalar runtime and constant results therefore reflect the generated instructions. Comparing the scalar and vectorized constant case changes both the division algorithm and the degree of parallelism. The precomputed class also uses LASX multiply/shift arithmetic in the normal build, and scalar multiply/shift arithmetic with vectorization disabled. All four kernels were reported as vectorized with 32-byte vectors, with additional 16-byte paths and alias checks, in the normal build. This is a CPU/compiler/flags comparison; it does not establish a universal latency for any instruction or isolate hardware differences from compiler differences. Construction-inclusive results, normal optimization, in nanoseconds per value: | Values per batch | Runtime `/` | Construct once, then `Divide` | |---|---:|---:| | 1 | 6.012418 | 6.515206 | | 4 | 1.814198 | 1.759673 | | 16 | 1.798449 | 0.594285 | | 64 | 0.907054 | 0.470592 | | 256 | 0.907033 | 0.380951 | | 1,024 | 0.906315 | 0.355004 | | 4,096 | 0.905724 | 0.346966 | Among the tested sizes, the first winning batch size was four values. The size-specific scalar, LSX, and LASX paths and their setup overhead matter; the crossover is not a property of the divisor alone. The release correctness test passed 43,143,231 comparisons against built-in division. Each kernel and batch size was also verified before timing. The GCC 15 installation returned bare `libasan.so` and `libubsan.so` names from `-print-file-name`, rather than paths to available libraries; the sanitizer run was explicitly skipped and recorded as such. Sanitizer runs on the M4 and Xeon passed, but that does not constitute a sanitizer run on this host. - [Normal samples](auto-samples.csv), [summary](auto-summary.csv), [run log](auto-run.log). - [Scalar samples](scalar-samples.csv), [summary](scalar-summary.csv), [run log](scalar-run.log). - [Normal assembly](kernels-auto.s), [scalar assembly](kernels-scalar.s), [vectorizer report](vectorization.log). - [Release correctness log](test-release.log), [sanitizer availability log](test-sanitized.log). - [Machine metadata](metadata.json), [CPU description](lscpu.txt), [compiler](compiler.txt), [source hashes](source-sha256.txt). To reproduce from a fresh directory containing the six source/runner files: ```sh DIVIDE_BENCH_CXX=/opt/loongson-gcc-15.2.0/bin/g++ DIVIDE_BENCH_STD=c++26 bash benchmark_linux.sh 2 results ``` [benchmark_linux.sh](../../benchmark_linux.sh) uses the chosen GCC's C++ runtime, checks correctness, writes assembly and metadata, and runs the timed suites sequentially. The scalar build disables both GCC loop and SLP vectorization. The runner's default language mode is C++20 for the older Xeon compiler; this run explicitly selected C++26 and GCC 15 as requested.