diff --git a/.gitignore b/.gitignore index da05fd2..ba3b13f 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,8 @@ *.gif *.mp4 !reference/*.csv +!analysis/*.csv + # Benchmark outputs (keep .gitkeep, ignore results) benchmarks/* @@ -21,3 +23,4 @@ sizes .vscode .DS_Store +**__pycache__** diff --git a/analysis/fig_exp.png b/analysis/fig_exp.png deleted file mode 100644 index fb9c537..0000000 Binary files a/analysis/fig_exp.png and /dev/null differ diff --git a/analysis/fig_exp.svg b/analysis/fig_exp.svg new file mode 100644 index 0000000..2e551ba --- /dev/null +++ b/analysis/fig_exp.svg @@ -0,0 +1,1000 @@ + + + + + + + + 2026-06-17T10:45:24.889513 + image/svg+xml + + + Matplotlib v3.10.9, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/analysis/fig_ladder.png b/analysis/fig_ladder.png deleted file mode 100644 index 49d9d19..0000000 Binary files a/analysis/fig_ladder.png and /dev/null differ diff --git a/analysis/fig_ladder.svg b/analysis/fig_ladder.svg new file mode 100644 index 0000000..341f161 --- /dev/null +++ b/analysis/fig_ladder.svg @@ -0,0 +1,1440 @@ + + + + + + + + 2026-06-17T10:45:24.420037 + image/svg+xml + + + Matplotlib v3.10.9, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/analysis/fig_milestones.png b/analysis/fig_milestones.png deleted file mode 100644 index 6fdff91..0000000 Binary files a/analysis/fig_milestones.png and /dev/null differ diff --git a/analysis/fig_milestones.svg b/analysis/fig_milestones.svg new file mode 100644 index 0000000..12e234c --- /dev/null +++ b/analysis/fig_milestones.svg @@ -0,0 +1,2369 @@ + + + + + + + + 2026-06-17T10:45:25.175739 + image/svg+xml + + + Matplotlib v3.10.9, https://matplotlib.org/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/analysis/fig_roofline.svg b/analysis/fig_roofline.svg index f74690e..fe47367 100644 --- a/analysis/fig_roofline.svg +++ b/analysis/fig_roofline.svg @@ -6,7 +6,7 @@ - 2026-06-05T06:08:49.278850 + 2026-06-17T10:45:24.667709 image/svg+xml @@ -42,16 +42,16 @@ z +" clip-path="url(#pf201e75209)" style="fill: none; stroke: #ededed; stroke-width: 0.8; stroke-linecap: square"/> - - + @@ -109,11 +109,11 @@ z +" clip-path="url(#pf201e75209)" style="fill: none; stroke: #ededed; stroke-width: 0.8; stroke-linecap: square"/> - + @@ -127,11 +127,11 @@ L 151.373736 50.483625 +" clip-path="url(#pf201e75209)" style="fill: none; stroke: #ededed; stroke-width: 0.8; stroke-linecap: square"/> - + @@ -145,11 +145,11 @@ L 225.582514 50.483625 +" clip-path="url(#pf201e75209)" style="fill: none; stroke: #ededed; stroke-width: 0.8; stroke-linecap: square"/> - + @@ -196,11 +196,11 @@ z +" clip-path="url(#pf201e75209)" style="fill: none; stroke: #ededed; stroke-width: 0.8; stroke-linecap: square"/> - + @@ -215,11 +215,11 @@ L 374.000069 50.483625 +" clip-path="url(#pf201e75209)" style="fill: none; stroke: #ededed; stroke-width: 0.8; stroke-linecap: square"/> - + @@ -284,11 +284,11 @@ z +" clip-path="url(#pf201e75209)" style="fill: none; stroke: #ededed; stroke-width: 0.8; stroke-linecap: square"/> - + @@ -328,11 +328,11 @@ z +" clip-path="url(#pf201e75209)" style="fill: none; stroke: #ededed; stroke-width: 0.8; stroke-linecap: square"/> - + @@ -755,16 +755,16 @@ z +" clip-path="url(#pf201e75209)" style="fill: none; stroke: #ededed; stroke-width: 0.8; stroke-linecap: square"/> - - + @@ -778,11 +778,11 @@ L -3.5 0 +" clip-path="url(#pf201e75209)" style="fill: none; stroke: #ededed; stroke-width: 0.8; stroke-linecap: square"/> - + @@ -796,11 +796,11 @@ L 669.565625 246.474008 +" clip-path="url(#pf201e75209)" style="fill: none; stroke: #ededed; stroke-width: 0.8; stroke-linecap: square"/> - + @@ -814,11 +814,11 @@ L 669.565625 208.263914 +" clip-path="url(#pf201e75209)" style="fill: none; stroke: #ededed; stroke-width: 0.8; stroke-linecap: square"/> - + @@ -873,11 +873,11 @@ z +" clip-path="url(#pf201e75209)" style="fill: none; stroke: #ededed; stroke-width: 0.8; stroke-linecap: square"/> - + @@ -892,11 +892,11 @@ L 669.565625 131.843728 +" clip-path="url(#pf201e75209)" style="fill: none; stroke: #ededed; stroke-width: 0.8; stroke-linecap: square"/> - + @@ -945,11 +945,11 @@ z +" clip-path="url(#pf201e75209)" style="fill: none; stroke: #ededed; stroke-width: 0.8; stroke-linecap: square"/> - + @@ -967,22 +967,22 @@ L 195.598003 73.850165 L 198.818818 71.282163 L 669.057804 71.282163 L 669.057804 71.282163 -" clip-path="url(#pa8b7964e4d)" style="fill: none; stroke: #bbbbbb; stroke-width: 1.4; stroke-linecap: square"/> +" clip-path="url(#pf201e75209)" style="fill: none; stroke: #bbbbbb; stroke-width: 1.4; stroke-linecap: square"/> +" clip-path="url(#pf201e75209)" style="fill: none; stroke-dasharray: 3.7,1.6; stroke-dashoffset: 0; stroke: #aaaaaa"/> +" clip-path="url(#pf201e75209)" style="fill: none; stroke-dasharray: 3.7,1.6; stroke-dashoffset: 0; stroke: #aaaaaa"/> +" clip-path="url(#pf201e75209)" style="fill: none; stroke-dasharray: 3.7,1.6; stroke-dashoffset: 0; stroke: #aaaaaa"/> - + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + @@ -2279,7 +2264,7 @@ z - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - + + - - - - - - - - - - - - - - - + diff --git a/analysis/fig_speedup.svg b/analysis/fig_speedup.svg index 7292749..7194cdc 100644 --- a/analysis/fig_speedup.svg +++ b/analysis/fig_speedup.svg @@ -6,7 +6,7 @@ - 2026-06-05T10:51:02.035313 + 2026-06-17T10:45:25.506374 image/svg+xml @@ -42,16 +42,16 @@ z +" clip-path="url(#p83f650a52f)" style="fill: none; stroke: #e9e9e9; stroke-width: 0.8; stroke-linecap: square"/> - - + @@ -114,11 +114,11 @@ z +" clip-path="url(#p83f650a52f)" style="fill: none; stroke: #e9e9e9; stroke-width: 0.8; stroke-linecap: square"/> - + @@ -150,11 +150,11 @@ z +" clip-path="url(#p83f650a52f)" style="fill: none; stroke: #e9e9e9; stroke-width: 0.8; stroke-linecap: square"/> - + @@ -194,11 +194,11 @@ z +" clip-path="url(#p83f650a52f)" style="fill: none; stroke: #e9e9e9; stroke-width: 0.8; stroke-linecap: square"/> - + @@ -214,11 +214,11 @@ L 319.229339 50.413312 +" clip-path="url(#p83f650a52f)" style="fill: none; stroke: #e9e9e9; stroke-width: 0.8; stroke-linecap: square"/> - + @@ -249,11 +249,11 @@ z +" clip-path="url(#p83f650a52f)" style="fill: none; stroke: #e9e9e9; stroke-width: 0.8; stroke-linecap: square"/> - + @@ -268,11 +268,11 @@ L 484.334139 50.413312 +" clip-path="url(#p83f650a52f)" style="fill: none; stroke: #e9e9e9; stroke-width: 0.8; stroke-linecap: square"/> - + @@ -705,16 +705,16 @@ z +" clip-path="url(#p83f650a52f)" style="fill: none; stroke: #e9e9e9; stroke-width: 0.8; stroke-linecap: square"/> - - + @@ -746,11 +746,11 @@ z +" clip-path="url(#p83f650a52f)" style="fill: none; stroke: #e9e9e9; stroke-width: 0.8; stroke-linecap: square"/> - + @@ -765,11 +765,11 @@ L 633.535625 228.753071 +" clip-path="url(#p83f650a52f)" style="fill: none; stroke: #e9e9e9; stroke-width: 0.8; stroke-linecap: square"/> - + @@ -784,11 +784,11 @@ L 633.535625 166.832829 +" clip-path="url(#p83f650a52f)" style="fill: none; stroke: #e9e9e9; stroke-width: 0.8; stroke-linecap: square"/> - + @@ -804,11 +804,11 @@ L 633.535625 119.991975 +" clip-path="url(#p83f650a52f)" style="fill: none; stroke: #e9e9e9; stroke-width: 0.8; stroke-linecap: square"/> - + @@ -846,16 +846,16 @@ L 633.535625 73.15112 - + - - - - - - - - - + + + + + + + + - + - - - - - - - - - + + + + + + + + - + - - - - - - - - - + + + + + + + + - + - - - - - - - - - + + + + + + + + - + - - - - - - - - - + + + + + + + + - + - - - - - - - - - + + + + + + + + +" clip-path="url(#p83f650a52f)" style="fill: none; stroke-dasharray: 1.3,2.145; stroke-dashoffset: 0; stroke: #999999; stroke-width: 1.3"/> - + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + @@ -2133,4851 +2026,4851 @@ z - - - - - - - - - - - - - + diff --git a/analysis/fig_speedup_all.png b/analysis/fig_speedup_all.png deleted file mode 100644 index 0c656b6..0000000 Binary files a/analysis/fig_speedup_all.png and /dev/null differ diff --git a/analysis/fig_tracks.svg b/analysis/fig_tracks.svg index fcf59f2..078a79e 100644 --- a/analysis/fig_tracks.svg +++ b/analysis/fig_tracks.svg @@ -1,12 +1,12 @@ - + - 2026-06-04T08:33:44.968663 + 2026-06-17T10:45:24.236157 image/svg+xml @@ -21,42 +21,42 @@ - - - + - - + - + - + - + - + - + - + - + - + - + - + @@ -212,100 +212,217 @@ L 292.238437 50.483625 - + - + - - + + - - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - + - - + - + - + - - + + - + - + - + - + - - + + - + - + - - - - - - + + + + - - + + - + - + - - - - - - + + + + - - + + - + - + - + - - - - - + + - - + + - + - + - + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + - - + + - - - - - - - - - + + + + + + + + - - + + - - - - - - - - - - + + + + + + + + + - - + + - - - - - - - - - - + + + + + + + + + - - + + - - - - - - - - - - + + + + + + + + + - - + + - - - - - - - - - - + + + + + + + + + - - + + - - - - - - - - - - + + + + + + + + + - - + + - - - - - - - - - - + + + + + + + + + - - + + + + + + + + + + + + + + + - - + + - - - + + + + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1475,7 +1553,7 @@ z - + @@ -1487,10 +1565,18 @@ z - + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - + - + - - @@ -2074,9 +2107,9 @@ z - + - + - + - + - + - + + + + @@ -2237,9 +2302,9 @@ z - + - + - + - + @@ -2315,9 +2380,9 @@ z - + - + - - - + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + diff --git a/analysis/make_csv.py b/analysis/make_csv.py index dec63fd..937c940 100644 --- a/analysis/make_csv.py +++ b/analysis/make_csv.py @@ -1,75 +1,121 @@ +import csv +import importlib.util import os import re -import csv +import sys -# folder that holds one subfolder per variant, each with an x86/ dir full of *.log files -ROOT = "measurements" -OUT = "analysis/results.csv" +sys.path.insert(0, 'flopcounts') + +ROOT = 'measurements' +OUT = 'analysis/results_x86.csv' + +size_line = re.compile(r'=== N_P=(\d+) N_ITER=(\d+) ===') -# the benchmark prints one block per problem size, looks like: -# === N_P=500 N_ITER=200 === -# W(n) per iteration: ... -# Q(n) per iteration: ... -# I(n): ... -# W(n): ... -# T(n): ... <- cycles -# P(n): ... <- flops/cycle -# so I split each log on the "=== N_P=.. ===" lines and read the fields out of each block. -size_line = re.compile(r"=== N_P=(\d+) N_ITER=(\d+) ===") def num(pattern, text): - m = re.search(pattern, text) - if m: - return float(m.group(1)) + m = re.search(pattern, text) + if m: + return float(m.group(1)) + return None + + +_flopcount_modules = {} + + +def get_flops_per_iter(variant, n_p, n_obs=2): + variant = variant.strip() + + module_name = variant.replace('/', '_').replace('\\', '_') + module_path = f'flopcounts/x86/{module_name}' + + if module_name in _flopcount_modules: + module = _flopcount_modules[module_name] + elif os.path.exists(f'{module_path}.py'): + try: + spec = importlib.util.spec_from_file_location(module_name, + f'{module_path}.py') + assert spec is not None + assert spec.loader is not None + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + _flopcount_modules[module_name] = module + except Exception as e: + print(f'Warning: Failed to load flopcount for {variant}: {e}') + return None + else: + print(f'Warning: No flopcount module found for {variant}') return None -#we run every variant a few times (1.log, 2.log, ...). keep the fastest run per size, -#min cycles is the standard way to kill the OS/turbo noise. -best = {} + if hasattr(module, 'total'): + try: + return module.total(n_iter=1, n_p=int(n_p), n_obs=int(n_obs)) + except Exception as e: + print(f'Warning: Error calling total() for {variant}: {e}') + return None + else: + print(f'Warning: No total() function in {module_path}') + return None -# flop counter is uint32 and wraps at n=10000 (72*n^2+74*n = 7.2e9 > 2^32), so the logged -# W(n)/I(n) are garbage there. compute work ourselves; matches the good logs exactly. -# symmetry variants do half the pairs -> 36 n^2 + 110 n, everything else 72 n^2 + 74 n. -def flops_per_iter(variant, n): - if "symmetry" in variant: - return 36 * n * n + 110 * n - return 72 * n * n + 74 * n + +runs = {} for variant in sorted(os.listdir(ROOT)): - logdir = os.path.join(ROOT, variant, "x86") - if not os.path.isdir(logdir): + logdir = os.path.join(ROOT, variant, 'x86') + if not os.path.isdir(logdir): + continue + + for fn in os.listdir(logdir): + if not fn.endswith('.log'): + continue + text = open(os.path.join(logdir, fn)).read() + + marks = list(size_line.finditer(text)) + for i, m in enumerate(marks): + n = int(m.group(1)) + n_iter = int(m.group(2)) + start = m.end() + stop = marks[i + 1].start() if i + 1 < len(marks) else len(text) + block = text[start:stop] + + cycles = num(r'T\(n\):\s*([\d.]+)', block) + if cycles is None: continue - for fn in os.listdir(logdir): - if not fn.endswith(".log"): - continue - text = open(os.path.join(logdir, fn)).read() + key = (variant, n) + q = num(r'Q\(n\) per iteration:\s*([\d.]+)', block) + if key not in runs: + runs[key] = [] + runs[key].append((cycles, n_iter, q)) - marks = list(size_line.finditer(text)) - for i, m in enumerate(marks): - n = int(m.group(1)) - n_iter = int(m.group(2)) - start = m.end() - stop = marks[i + 1].start() if i + 1 < len(marks) else len(text) - block = text[start:stop] +with open(OUT, 'w', newline='') as f: + w = csv.writer(f) + w.writerow([ + 'variant', 'n', 'n_iter', 'W', 'Q_per_iter', 'I', 'cycles', + 'flops_per_cycle' + ]) + for variant, n in sorted(runs): + entries = runs[(variant, n)] + n_iter = entries[0][1] + q = entries[0][2] + for _, ni, qi in entries: + if ni != n_iter: + print(f'Warning: n_iter mismatch for {(variant, n)}: {ni} vs {n_iter}') + if qi != q: + print(f'Warning: Q_per_iter mismatch for {(variant, n)}: {qi} vs {q}') - cycles = num(r"T\(n\):\s*([\d.]+)", block) - if cycles is None: - continue + cycles = sum(e[0] for e in entries) / len(entries) - key = (variant, n) - if key not in best or cycles < best[key][0]: - best[key] = (cycles, n_iter, - num(r"Q\(n\) per iteration:\s*([\d.]+)", block)) + w_iter = get_flops_per_iter(variant, n) -with open(OUT, "w", newline="") as f: - w = csv.writer(f) - w.writerow(["variant", "n", "n_iter", "W", "Q_per_iter", "I", "cycles", "flops_per_cycle"]) - for variant, n in sorted(best): - cycles, n_iter, q = best[(variant, n)] - w_iter = flops_per_iter(variant, n) - W = w_iter * n_iter - I = w_iter / q - fc = W / cycles - w.writerow([variant, n, n_iter, W, q, round(I, 2), round(cycles, 1), round(fc, 3)]) -print("wrote", OUT, "with", len(best), "rows") \ No newline at end of file + assert w_iter is not None + + W = w_iter * n_iter + I = w_iter / q if q else w_iter + fc = W / cycles if cycles else 0 + w.writerow( + [variant, n, n_iter, W, q, + round(I, 2), + round(cycles, 1), + round(fc, 3)]) + +print('wrote', OUT, 'with', len(runs), 'rows') diff --git a/analysis/memory_x86.py b/analysis/memory_x86.py new file mode 100644 index 0000000..a9a33f6 --- /dev/null +++ b/analysis/memory_x86.py @@ -0,0 +1,63 @@ +from pathlib import Path +import re + +LOG_DIR = Path('measurements/memory/x86') +CPU_FREQ_GHZ = 2.0 + + +def parse_sysbench_log(file_path): + """Parses a single sysbench log file to extract memory bandwidth in MiB/s.""" + try: + with open(file_path, 'r') as f: + content = f.read() + + match = re.search(r'(\d+\.?\d*)\s+MiB/sec', content) + + if match: + return float(match.group(1)) + else: + print(f"Warning: Could not find 'MiB/sec' in {file_path.name}") + return None + except Exception as e: + print(f'Error reading {file_path}: {e}') + return None + + +def main(): + if not LOG_DIR.exists(): + print(f"Error: Directory '{LOG_DIR}' not found.") + return + + bandwidths_mib_s = [] + + log_files = sorted(LOG_DIR.glob('*.log')) + + print(f'Found {len(log_files)} log files.') + + for file_path in log_files: + val = parse_sysbench_log(file_path) + if val is not None: + bandwidths_mib_s.append(val) + + if not bandwidths_mib_s: + print('No valid bandwidth data found.') + return + + avg_mi_b_s = sum(bandwidths_mib_s) / len(bandwidths_mib_s) + + bytes_per_second = avg_mi_b_s * (1024**2) + cycles_per_second = CPU_FREQ_GHZ * 1e9 + + bytes_per_cycle = bytes_per_second / cycles_per_second + + print('-' * 40) + print(f'Files analyzed: {len(bandwidths_mib_s)}') + print(f'Average Bandwidth: {avg_mi_b_s:.2f} MiB/sec') + print(f'CPU Frequency: {CPU_FREQ_GHZ} GHz') + print('-' * 40) + print(f'Result: {bytes_per_cycle:.2f} bytes/cycle') + print('-' * 40) + + +if __name__ == '__main__': + main() diff --git a/analysis/plots.py b/analysis/plots.py index 5e6d729..37e17f4 100644 --- a/analysis/plots.py +++ b/analysis/plots.py @@ -5,14 +5,15 @@ import matplotlib.pyplot as plt import matplotlib.patheffects as pe #import seaborn as sns # tried it, the default look was worse -df = pd.read_csv("analysis/results.csv") +df = pd.read_csv("analysis/results_x86.csv") -# peaks for the ryzen ai 7 350 (zen5) at 2GHz. 2 fma units and the datapath is 256 bit +# peaks for the ryzen ai 7 350 (zen5) at 2GHz. 2 fma + 2 fadd units and the datapath is 256 bit # -> scalar 6, double 24, float 48 flops/cycle SCALAR = 6 PEAK_D = 24 PEAK_F = 48 maroon = "#A71D5B" +crimson = "#DC143C" def get(v, n=5000): @@ -20,13 +21,13 @@ def get(v, n=5000): def getline(v): - s = df[df.variant == v].sort_values("n") + s = df[df.variant == v].sort_values("n") # pyright: ignore[reportCallIssue] return s.n.values, s["flops_per_cycle"].values def label_lines_above(ax, entries, - fontsize=9, + fontsize: float = 9, rotate=False, dy_frac=0.012, halo=0): @@ -108,79 +109,66 @@ tracks = [ ("variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt", "AVX-256 + PolyExp + RSQRT (float)", "#d05a82", "--"), ("variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt", - "AVX-512 + PolyExp + RSQRT + ILP (float)", maroon, "-"), + "AVX-512 + PolyExp + RSQRT + ILP-Inner (float)", maroon, "-"), + ("variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved_moreilp", + "AVX-512 + PolyExp + RSQRT + ILP-Outer (float)", crimson, "-"), ] -tick_vals = np.array([50, 100, 200, 500, 1000, 2000, 5000, 10000]) -target_positions = np.arange(len(tick_vals)) - - -def map_x_to_linear(x_val): - return np.interp(x_val, tick_vals, target_positions) - - fig, ax = plt.subplots(figsize=(9, 4.7)) ends = [] for v, lab, c, ls in tracks: - x_raw, y = getline(v) - x_mapped = map_x_to_linear(x_raw) + x, y = getline(v) + ax.plot( + x, + y, # pyright: ignore[reportArgumentType] + ls, + color=c, + marker="o", + ms=4, + lw=2.4 if c == maroon else 1.8) + if c == maroon: + side = "below" + xpos = 5600 + else: + side = "above" + xpos = None + ends.append((x, y, lab, c, xpos, side)) - ax.plot(x_mapped, - y, - ls, - color=c, - marker="o", - ms=4, - lw=2.4 if c == maroon else 1.8) - - ends.append((x_mapped, y, lab, c)) - -tick_vals = [50, 100, 200, 500, 1000, 2000, 5000, 10000] -target_positions = list(range(len(tick_vals))) - -start_x_pos = 0 - -for yv, t in [(PEAK_D, f"Peak π par. w/ doubles ({PEAK_D} flops/cycle)"), - (PEAK_F, f"Peak π par. w/ floats ({PEAK_F} flops/cycle)")]: +for yv, t in [ + (27.43, f"Peak π based on instruction mix [{27.43} flops/cycle]"), + # (PEAK_D, f"Peak π par. w/ doubles ({PEAK_D} flops/cycle)"), + # (PEAK_F, f"Peak π par. w/ floats ({PEAK_F} flops/cycle)") +]: ax.axhline(yv, ls=":", color="#999", lw=1.2) - ax.text(start_x_pos + 0.2, - yv * 1.03, - t, - fontsize=9, - color="#888", - fontweight="bold") + ax.text(52, yv * 1.03, t, fontsize=9, color="#888", fontweight="bold") -ax.set_yscale("log", base=2) - -ax.set_xticks(target_positions) -ax.set_xticklabels(["50", "100", "200", "500", "1k", "2k", "5k", "10k"], - fontweight="bold", - fontsize=9) - -ax.set_xlim(-0.5, len(tick_vals) - 0.5) - -ax.yaxis.set_major_formatter(ticker.FuncFormatter(lambda x, _: str(int(x)))) +ax.set_xscale("log", base=10) +ax.set_xticks([50, 100, 200, 500, 1000, 2000, 5000, 10000]) +ax.set_xticklabels(["50", "100", "200", "500", "1K", "2K", "5K", "10K"]) +ax.set_xlim(46, 13000) +ax.set_ylim(0, 30) for label in ax.get_yticklabels(): label.set_fontweight('bold') label.set_fontsize(9) -ax.set_ylim(1, 64) +for label in ax.get_xticklabels(): + label.set_fontweight('bold') + label.set_fontsize(9) ax.set_xlabel("Number of Pedestrians", fontweight="bold", fontsize=9) ax.grid(color="#e9e9e9") ax.spines["top"].set_visible(False) ax.spines["right"].set_visible(False) plt.title( - 'Performance [flops/cycle]\nCPU: AMD Ryzen AI 7 350 w/ Radeon 860M @ 2 GHz\nCompiler: g++ (Debian 15.2.0-17) 15.2.0\nFlags: -O3 -march=native -std=c++23 -Wall -Wextra -flto', + 'Performance (flops/cycle) [N = 3]\nCPU: AMD Ryzen AI 7 350 @ 2 GHz\nCompiler: g++ (Debian 15.2.0-17) 15.2.0\nFlags: -O3 -march=native -std=c++23 -Wall -Wextra -flto', loc='left', size=9, fontweight="bold") +ax.grid(color="#e9e9e9") plt.tight_layout() - -label_lines_above(ax, ends, fontsize=7.5, dy_frac=0.012) - +label_lines_above(ax, ends, fontsize=7.25, dy_frac=0.012) plt.savefig("analysis/fig_tracks.svg", bbox_inches="tight") -# plot 2: all te milestones + the symmetry one that got slower +# plot 2: all the milestones + the symmetry one that got slower bars = [ ("baseline", "variant_baseline"), ("AVX2 (double)", "variant_inlining_7_SoA_AVX2"), @@ -219,7 +207,7 @@ ax.grid(axis="y", visible=False) ax.spines["top"].set_visible(False) ax.spines["right"].set_visible(False) plt.tight_layout() -plt.savefig("analysis/fig_ladder.png", dpi=170, bbox_inches="tight") +plt.savefig("analysis/fig_ladder.svg", bbox_inches="tight") # plot 3: roofline (n = 5000). same 7 variants as fig_tracks, same colors, inline labels. @@ -318,7 +306,7 @@ ax.set_xticklabels(ax.get_xticklabels(), fontweight="bold") ax.set_yticklabels(ax.get_yticklabels(), fontweight="bold") # ax.set_ylabel("Performance [flops/cycle]", fontweight="bold", fontsize=9) plt.title( - 'Performance [flops/cycle]\nCPU: AMD Ryzen AI 7 350 w/ Radeon 860M @ 2 GHz\nCompiler: g++ (Debian 15.2.0-17) 15.2.0\nFlags: -O3 -march=native -std=c++23 -Wall -Wextra -flto', + 'Performance [flops/cycle]\nCPU: AMD Ryzen AI 7 350 @ 2 GHz\nCompiler: g++ (Debian 15.2.0-17) 15.2.0\nFlags: -O3 -march=native -std=c++23 -Wall -Wextra -flto', loc='left', size=9, fontweight="bold") @@ -344,7 +332,7 @@ ax.spines["top"].set_visible(False) ax.spines["right"].set_visible(False) ax.legend(frameon=False, fontsize=10) plt.tight_layout() -plt.savefig("analysis/fig_exp.png", dpi=170, bbox_inches="tight") +plt.savefig("analysis/fig_exp.svg", bbox_inches="tight") # plot 5: the milestone ladder as lines (this is plot0 + line1, line2, ... for the doc). # one line per relevant optimization step across n, baseline at the bottom. @@ -399,7 +387,7 @@ ax.spines["top"].set_visible(False) ax.spines["right"].set_visible(False) plt.tight_layout() label_lines_above(ax, ends, fontsize=6.5, dy_frac=0.02, halo=0) -plt.savefig("analysis/fig_milestones.png", dpi=170, bbox_inches="tight") +plt.savefig("analysis/fig_milestones.svg", bbox_inches="tight") #plt.show() @@ -449,7 +437,8 @@ ax.set_xscale("log") ax.set_yscale("log") ax.set_xticks([50, 100, 200, 500, 1000, 2000, 5000]) -ax.set_xticklabels(["50", "100", "200", "500", "1k", "2k", "5k"], fontweight="bold") +ax.set_xticklabels(["50", "100", "200", "500", "1k", "2k", "5k"], + fontweight="bold") ax.set_yticks([1, 2, 5, 10, 20]) ax.set_yticklabels(["1x", "2x", "5x", "10x", "20x"], fontweight="bold") @@ -462,7 +451,7 @@ ax.set_ylim(0.8, 28) ax.set_xlabel("Number of Pedestrians", fontweight="bold", fontsize=9) # ax.set_ylabel("Speedup", fontweight="bold", fontsize=9) plt.title( - 'Runtime Speedup\nCPU: AMD Ryzen AI 7 350 w/ Radeon 860M @ 2 GHz\nCompiler: g++ (Debian 15.2.0-17) 15.2.0\nFlags: -O3 -march=native -std=c++23 -Wall -Wextra -flto', + 'Runtime Speedup\nCPU: AMD Ryzen AI 7 350 @ 2 GHz\nCompiler: g++ (Debian 15.2.0-17) 15.2.0\nFlags: -O3 -march=native -std=c++23 -Wall -Wextra -flto', loc='left', size=9, fontweight="bold") diff --git a/analysis/results_x86.csv b/analysis/results_x86.csv new file mode 100644 index 0000000..fc516ef --- /dev/null +++ b/analysis/results_x86.csv @@ -0,0 +1,316 @@ +variant,n,n_iter,W,Q_per_iter,I,cycles,flops_per_cycle +variant_AVX512_1,50,200,40690000,6512.0,31.24,12357341.2,3.293 +variant_AVX512_1,100,200,157220000,12912.0,60.88,42690045.0,3.683 +variant_AVX512_1,200,200,619080000,25712.0,120.39,149289520.0,4.147 +variant_AVX512_1,500,200,3826100000,64112.0,298.39,895752980.0,4.271 +variant_AVX512_1,1000,200,15255400000,128112.0,595.39,3427521146.7,4.451 +variant_AVX512_1,2000,200,60910800000,256112.0,1189.14,13524851386.7,4.504 +variant_AVX512_1,5000,200,380277000000,640112.0,2970.39,83786559000.0,4.539 +variant_AVX512_1,10000,200,1520554000000,1280112.0,5939.14,346902390090.0,4.383 +variant_baseline,50,200,36740000,6512.0,28.21,27452843.3,1.338 +variant_baseline,100,200,145480000,12912.0,56.34,108607106.7,1.34 +variant_baseline,200,200,578960000,25712.0,112.59,435167353.3,1.33 +variant_baseline,500,200,3607400000,64112.0,281.34,2807013360.0,1.285 +variant_baseline,1000,200,14414800000,128112.0,562.59,11381234466.7,1.267 +variant_baseline,2000,200,57629600000,256112.0,1125.09,46436426300.0,1.241 +variant_baseline,5000,200,360074000000,640112.0,2812.59,312703123826.7,1.151 +variant_branchless,50,200,37920000,6512.0,29.12,32528650.0,1.166 +variant_branchless,100,200,149840000,12912.0,58.02,130689786.7,1.147 +variant_branchless,200,200,595680000,25712.0,115.84,544820746.7,1.093 +variant_branchless,500,200,3709200000,64112.0,289.28,3560289460.0,1.042 +variant_branchless,1000,200,14818400000,128112.0,578.34,14393150806.7,1.03 +variant_branchless,2000,200,59236800000,256112.0,1156.46,59210476113.3,1.0 +variant_branchless,5000,200,370092000000,640112.0,2890.84,385464816373.3,0.96 +variant_branchless_sqrtfree,50,200,37920000,6512.0,29.12,31693365.0,1.196 +variant_branchless_sqrtfree,100,200,149840000,12912.0,58.02,124691126.7,1.202 +variant_branchless_sqrtfree,200,200,595680000,25712.0,115.84,494602046.7,1.204 +variant_branchless_sqrtfree,500,200,3709200000,64112.0,289.28,3078930946.7,1.205 +variant_branchless_sqrtfree,1000,200,14818400000,128112.0,578.34,12280066680.0,1.207 +variant_branchless_sqrtfree,2000,200,59236800000,256112.0,1156.46,49188518600.0,1.204 +variant_branchless_sqrtfree,5000,200,370092000000,640112.0,2890.84,308663505060.0,1.199 +variant_cutoff,50,200,36900000,6512.0,28.33,17730605.8,2.081 +variant_cutoff,100,200,145800000,12912.0,56.46,76248960.0,1.912 +variant_cutoff,200,200,579600000,25712.0,112.71,267962706.7,2.163 +variant_cutoff,500,200,3609000000,64112.0,281.46,1895310460.0,1.904 +variant_cutoff,1000,200,14418000000,128112.0,562.71,7727298866.7,1.866 +variant_cutoff,2000,200,57636000000,256112.0,1125.21,32411782673.3,1.778 +variant_cutoff,5000,200,360090000000,640112.0,2812.71,216604501193.3,1.662 +variant_cutoff_callsite,50,200,36900000,6512.0,28.33,16724109.2,2.206 +variant_cutoff_callsite,100,200,145800000,12912.0,56.46,71482436.7,2.04 +variant_cutoff_callsite,200,200,579600000,25712.0,112.71,254096566.7,2.281 +variant_cutoff_callsite,500,200,3609000000,64112.0,281.46,1819565306.7,1.983 +variant_cutoff_callsite,1000,200,14418000000,128112.0,562.71,7520631446.7,1.917 +variant_cutoff_callsite,2000,200,57636000000,256112.0,1125.21,31026276366.7,1.858 +variant_cutoff_callsite,5000,200,360090000000,640112.0,2812.71,211550331440.0,1.702 +variant_float_baseline,50,200,21950000,3256.0,33.71,24694491.3,0.889 +variant_float_baseline,100,200,86900000,6456.0,67.3,96417530.7,0.901 +variant_float_baseline,200,200,345800000,12856.0,134.49,383608277.3,0.901 +variant_float_baseline,500,200,2154500000,32056.0,336.05,2749099520.0,0.784 +variant_float_baseline,1000,200,8609000000,64056.0,671.99,11748012373.3,0.733 +variant_float_baseline,2000,200,34418000000,128056.0,1343.87,51879605589.3,0.663 +variant_float_baseline,5000,200,215045000000,320056.0,3359.49,369651034794.7,0.582 +variant_float_inlining,50,200,36750000,3256.0,56.43,20938618.7,1.755 +variant_float_inlining,100,200,145500000,6456.0,112.69,83407050.7,1.744 +variant_float_inlining,200,200,579000000,12856.0,225.19,338390005.3,1.711 +variant_float_inlining,500,200,3607500000,32056.0,562.69,2457371306.7,1.468 +variant_float_inlining,1000,200,14415000000,64056.0,1125.19,10667126784.0,1.351 +variant_float_inlining,2000,200,57630000000,128056.0,2250.19,47520261461.3,1.213 +variant_float_inlining,5000,200,360075000000,320056.0,5625.19,341753222485.3,1.054 +variant_float_inlining_SoA,50,200,36750000,3256.0,56.43,21048408.0,1.746 +variant_float_inlining_SoA,100,200,145500000,6456.0,112.69,84708077.3,1.718 +variant_float_inlining_SoA,200,200,579000000,12856.0,225.19,336827125.3,1.719 +variant_float_inlining_SoA,500,200,3607500000,32056.0,562.69,2477081600.0,1.456 +variant_float_inlining_SoA,1000,200,14415000000,64056.0,1125.19,10766873600.0,1.339 +variant_float_inlining_SoA,2000,200,57630000000,128056.0,2250.19,47988983125.3,1.201 +variant_float_inlining_SoA,5000,200,360075000000,320056.0,5625.19,345895436288.0,1.041 +variant_float_inlining_SoA_AVX2,50,200,42520000,3256.0,65.29,9238852.3,4.602 +variant_float_inlining_SoA_AVX2,100,200,155120000,6456.0,120.14,31443590.0,4.933 +variant_float_inlining_SoA_AVX2,200,200,590560000,12856.0,229.68,117080762.7,5.044 +variant_float_inlining_SoA_AVX2,500,200,3695600000,32056.0,576.43,715304192.0,5.166 +variant_float_inlining_SoA_AVX2,1000,200,14632800000,64056.0,1142.19,2914458538.7,5.021 +variant_float_inlining_SoA_AVX2,2000,200,58465600000,128056.0,2282.81,12570639018.7,4.651 +variant_float_inlining_SoA_AVX2,5000,200,365164000000,320056.0,5704.69,91014157653.3,4.012 +variant_float_inlining_SoA_AVX2,10000,200,1460328000000,640056.0,11407.81,410624917504.0,3.556 +variant_float_inlining_SoA_AVX2_polyexp,50,200,42520000,3256.0,65.29,5861893.7,7.254 +variant_float_inlining_SoA_AVX2_polyexp,100,200,155120000,6456.0,120.14,19739642.7,7.858 +variant_float_inlining_SoA_AVX2_polyexp,200,200,590560000,12856.0,229.68,71656157.3,8.242 +variant_float_inlining_SoA_AVX2_polyexp,500,200,3695600000,32056.0,576.43,435824629.3,8.48 +variant_float_inlining_SoA_AVX2_polyexp,1000,200,14632800000,64056.0,1142.19,1699931264.0,8.608 +variant_float_inlining_SoA_AVX2_polyexp,2000,200,58465600000,128056.0,2282.81,6739927722.7,8.675 +variant_float_inlining_SoA_AVX2_polyexp,5000,200,365164000000,320056.0,5704.69,42246128981.3,8.644 +variant_float_inlining_SoA_AVX2_polyexp,10000,200,1460328000000,640056.0,11407.81,167398135125.3,8.724 +variant_float_inlining_SoA_AVX2_polyexp_rsqrt,50,200,44760000,3256.0,68.73,5092671.3,8.789 +variant_float_inlining_SoA_AVX2_polyexp_rsqrt,100,200,163440000,6456.0,126.58,16935302.7,9.651 +variant_float_inlining_SoA_AVX2_polyexp_rsqrt,200,200,622560000,12856.0,242.13,60867113.3,10.228 +variant_float_inlining_SoA_AVX2_polyexp_rsqrt,500,200,3897200000,32056.0,607.87,368188341.3,10.585 +variant_float_inlining_SoA_AVX2_polyexp_rsqrt,1000,200,15432800000,64056.0,1204.63,1433606229.3,10.765 +variant_float_inlining_SoA_AVX2_polyexp_rsqrt,2000,200,61665600000,128056.0,2407.76,5675097941.3,10.866 +variant_float_inlining_SoA_AVX2_polyexp_rsqrt,5000,200,385164000000,320056.0,6017.13,35604179626.7,10.818 +variant_float_inlining_SoA_AVX2_polyexp_rsqrt,10000,200,1540328000000,640056.0,12032.76,142421229568.0,10.815 +variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt,50,200,44200000,3256.0,67.87,4881582.7,9.054 +variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt,100,200,161360000,6456.0,124.97,15658073.7,10.305 +variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt,200,200,614560000,12856.0,239.02,55530342.7,11.067 +variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt,500,200,3846800000,32056.0,600.01,332591989.3,11.566 +variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt,1000,200,15232800000,64056.0,1189.02,1292824832.0,11.783 +variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt,2000,200,60865600000,128056.0,2376.52,5134484992.0,11.854 +variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt,5000,200,380164000000,320056.0,5939.02,32074893312.0,11.852 +variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt,10000,200,1520328000000,640056.0,11876.52,128325312512.0,11.847 +variant_float_inlining_SoA_AVX512_polyexp,50,200,48510000,3256.0,74.49,4637544.0,10.46 +variant_float_inlining_SoA_AVX512_polyexp,100,200,167100000,6456.0,129.41,14045100.0,11.897 +variant_float_inlining_SoA_AVX512_polyexp,200,200,614520000,12856.0,239.0,47525244.0,12.93 +variant_float_inlining_SoA_AVX512_polyexp,500,200,3755500000,32056.0,585.77,272034645.3,13.805 +variant_float_inlining_SoA_AVX512_polyexp,1000,200,14752600000,64056.0,1151.54,1048487445.3,14.07 +variant_float_inlining_SoA_AVX512_polyexp,2000,200,58471600000,128056.0,2283.05,4093863424.0,14.283 +variant_float_inlining_SoA_AVX512_polyexp,5000,200,365763000000,320056.0,5714.05,25352017237.3,14.427 +variant_float_inlining_SoA_AVX512_polyexp,10000,200,1460358000000,640056.0,11408.05,100878147584.0,14.476 +variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt,50,200,48640000,3256.0,74.69,4900494.3,9.926 +variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt,100,200,167360000,6456.0,129.62,14697632.0,11.387 +variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt,200,200,615040000,12856.0,239.2,48755792.0,12.615 +variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt,500,200,3756800000,32056.0,585.97,275589760.0,13.632 +variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt,1000,200,14755200000,64056.0,1151.74,1056675861.3,13.964 +variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt,2000,200,58476800000,128056.0,2283.25,4125949952.0,14.173 +variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt,5000,200,365776000000,320056.0,5714.25,25582010368.0,14.298 +variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt,10000,200,1460384000000,640056.0,11408.25,101411954688.0,14.401 +variant_float_inlining_SoA_AVX512_polyexp_moreavx,50,200,48565600,3256.0,74.58,4427194.8,10.97 +variant_float_inlining_SoA_AVX512_polyexp_moreavx,100,200,167124800,6456.0,129.43,13805986.0,12.105 +variant_float_inlining_SoA_AVX512_polyexp_moreavx,200,200,614483200,12856.0,238.99,47360122.7,12.975 +variant_float_inlining_SoA_AVX512_polyexp_moreavx,500,200,3755364800,32056.0,585.75,275211349.3,13.645 +variant_float_inlining_SoA_AVX512_polyexp_moreavx,1000,200,14752243200,64056.0,1151.51,1064273109.3,13.861 +variant_float_inlining_SoA_AVX512_polyexp_moreavx,2000,200,58470800000,128056.0,2283.02,4162095445.3,14.048 +variant_float_inlining_SoA_AVX512_polyexp_moreavx,5000,200,365761043200,320056.0,5714.02,26013326677.3,14.061 +variant_float_inlining_SoA_AVX512_polyexp_moreavx,10000,200,1460354000000,640056.0,11408.02,103437175466.7,14.118 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2,50,200,48885600,3256.0,75.07,4118233.3,11.871 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2,100,200,191211200,6456.0,148.09,14171592.7,13.493 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2,200,200,662569600,12856.0,257.69,46241824.0,14.328 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2,500,200,3758564800,32056.0,586.25,250078272.0,15.03 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2,1000,200,14992329600,64056.0,1170.25,978147584.0,15.327 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2,2000,200,58950886400,128056.0,2301.76,3802809770.7,15.502 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2,5000,200,366961129600,320056.0,5732.76,23565800789.3,15.572 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2,10000,200,1462754086400,640056.0,11426.77,93711062357.3,15.609 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp,50,200,48885600,3256.0,75.07,4128367.9,11.841 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp,100,200,191211200,6456.0,148.09,14211595.0,13.455 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp,200,200,662569600,12856.0,257.69,46258992.0,14.323 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp,500,200,3758564800,32056.0,586.25,249568197.3,15.06 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp,1000,200,14992329600,64056.0,1170.25,975399104.0,15.37 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp,2000,200,58950886400,128056.0,2301.76,3793620480.0,15.539 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp,5000,200,366961129600,320056.0,5732.76,23545909930.7,15.585 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp,10000,200,1462754086400,640056.0,11426.77,93541878442.7,15.637 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt,50,200,48936800,3256.0,75.15,4115576.2,11.891 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt,100,200,191313600,6456.0,148.17,14176439.7,13.495 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt,200,200,662748800,12856.0,257.76,46456041.3,14.266 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt,500,200,3758974400,32056.0,586.31,250008314.7,15.035 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt,1000,200,14993148800,64056.0,1170.32,980856746.7,15.286 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt,2000,200,58952499200,128056.0,2301.82,3823654485.3,15.418 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt,5000,200,366965148800,320056.0,5732.83,23661115392.0,15.509 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt,10000,200,1462762099200,640056.0,11426.83,94207066112.0,15.527 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt,50,200,51458400,3256.0,79.02,3483682.3,14.771 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt,100,200,201476800,6456.0,156.04,11811947.3,17.057 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt,200,200,698454400,12856.0,271.65,38043610.7,18.359 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt,500,200,3963467200,32056.0,618.21,203642453.3,19.463 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt,1000,200,15811734400,64056.0,1234.21,812575168.0,19.459 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt,2000,200,62176889600,128056.0,2427.72,3099994965.3,20.057 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt,5000,200,387058134400,320056.0,6046.73,19214568789.3,20.144 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt,10000,200,1542884089600,640056.0,12052.73,76092566186.7,20.276 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved,50,200,51618400,3256.0,79.27,3425376.1,15.069 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved,100,200,201796800,6456.0,156.29,11372835.7,17.744 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved,200,200,699094400,12856.0,271.89,36467076.0,19.171 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved,500,200,3965067200,32056.0,618.46,195375242.7,20.295 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved,1000,200,15814934400,64056.0,1234.46,757288490.7,20.884 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved,2000,200,62183289600,128056.0,2427.97,2960859477.3,21.002 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved,5000,200,387074134400,320056.0,6046.98,18368346112.0,21.073 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved,10000,200,1542916089600,640056.0,12052.98,72963047424.0,21.147 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved_moreilp,50,200,51238400,3256.0,78.68,2439821.7,21.001 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved_moreilp,100,200,175907200,6456.0,136.24,8335320.3,21.104 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved_moreilp,200,200,647004800,12856.0,251.64,30687906.7,21.083 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved_moreilp,500,200,3958067200,32056.0,617.37,186111381.3,21.267 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved_moreilp,1000,200,15554044800,64056.0,1214.1,732997781.3,21.22 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved_moreilp,2000,200,61661200000,128056.0,2407.59,2924175018.7,21.087 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved_moreilp,5000,200,385769244800,320056.0,6026.59,18349806250.7,21.023 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved_moreilp,10000,200,1540306000000,640056.0,12032.59,73231152469.3,21.033 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4,50,200,49525600,3256.0,76.05,3890111.5,12.731 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4,100,200,192491200,6456.0,149.08,13501827.7,14.257 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4,200,200,758742400,12856.0,295.09,49975976.0,15.182 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4,500,200,3764964800,32056.0,587.25,239680656.0,15.708 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4,1000,200,15005129600,64056.0,1171.25,945644394.7,15.868 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4,2000,200,59911059200,128056.0,2339.25,3715754325.3,16.124 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4,5000,200,369361302400,320056.0,5770.26,22745182890.7,16.239 +variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4,10000,200,1467554259200,640056.0,11464.26,90144694272.0,16.28 +variant_float_inlining_SoA_symmetry,50,200,35280000,3256.0,54.18,20621257.3,1.711 +variant_float_inlining_SoA_symmetry,100,200,139560000,6456.0,108.09,81476053.3,1.713 +variant_float_inlining_SoA_symmetry,200,200,555120000,12856.0,215.9,333481098.7,1.665 +variant_float_inlining_SoA_symmetry,500,200,3457800000,32056.0,539.34,2568502357.3,1.346 +variant_float_inlining_SoA_symmetry,1000,200,13815600000,64056.0,1078.4,11066851669.3,1.248 +variant_float_inlining_SoA_symmetry,2000,200,55231200000,128056.0,2156.53,49006380373.3,1.127 +variant_float_inlining_SoA_symmetry,5000,200,345078000000,320056.0,5390.9,349641758037.3,0.987 +variant_float_inlining_SoA_symmetry_ILP_16,50,200,35920000,3256.0,55.16,17984374.0,1.997 +variant_float_inlining_SoA_symmetry_ILP_16,100,200,140840000,6456.0,109.08,64325713.3,2.189 +variant_float_inlining_SoA_symmetry_ILP_16,200,200,557680000,12856.0,216.89,252748229.3,2.206 +variant_float_inlining_SoA_symmetry_ILP_16,500,200,3464200000,32056.0,540.34,1863017770.7,1.859 +variant_float_inlining_SoA_symmetry_ILP_16,1000,200,13828400000,64056.0,1079.4,8033498282.7,1.721 +variant_float_inlining_SoA_symmetry_ILP_16,2000,200,55256800000,128056.0,2157.52,33723052032.0,1.639 +variant_float_inlining_SoA_symmetry_ILP_16,5000,200,345142000000,320056.0,5391.9,219469376170.7,1.573 +variant_float_inlining_SoA_symmetry_ILP_2,50,200,35360000,3256.0,54.3,18593934.7,1.902 +variant_float_inlining_SoA_symmetry_ILP_2,100,200,139720000,6456.0,108.21,73156496.0,1.91 +variant_float_inlining_SoA_symmetry_ILP_2,200,200,555440000,12856.0,216.02,293520213.3,1.892 +variant_float_inlining_SoA_symmetry_ILP_2,500,200,3458600000,32056.0,539.46,2178498048.0,1.588 +variant_float_inlining_SoA_symmetry_ILP_2,1000,200,13817200000,64056.0,1078.53,9321413973.3,1.482 +variant_float_inlining_SoA_symmetry_ILP_2,2000,200,55234400000,128056.0,2156.65,40795664384.0,1.354 +variant_float_inlining_SoA_symmetry_ILP_2,5000,200,345086000000,320056.0,5391.03,287744611669.3,1.199 +variant_float_inlining_SoA_symmetry_ILP_4,50,200,35440000,3256.0,54.42,17059464.0,2.077 +variant_float_inlining_SoA_symmetry_ILP_4,100,200,139880000,6456.0,108.33,65813640.0,2.125 +variant_float_inlining_SoA_symmetry_ILP_4,200,200,555760000,12856.0,216.15,266939221.3,2.082 +variant_float_inlining_SoA_symmetry_ILP_4,500,200,3459400000,32056.0,539.59,1956788906.7,1.768 +variant_float_inlining_SoA_symmetry_ILP_4,1000,200,13818800000,64056.0,1078.65,8363417088.0,1.652 +variant_float_inlining_SoA_symmetry_ILP_4,2000,200,55237600000,128056.0,2156.78,35347298986.7,1.563 +variant_float_inlining_SoA_symmetry_ILP_4,5000,200,345094000000,320056.0,5391.15,238227024554.7,1.449 +variant_float_inlining_SoA_symmetry_ILP_8,50,200,35600000,3256.0,54.67,15194553.3,2.343 +variant_float_inlining_SoA_symmetry_ILP_8,100,200,140200000,6456.0,108.58,56247389.3,2.493 +variant_float_inlining_SoA_symmetry_ILP_8,200,200,556400000,12856.0,216.4,226057952.0,2.461 +variant_float_inlining_SoA_symmetry_ILP_8,500,200,3461000000,32056.0,539.84,1703800277.3,2.031 +variant_float_inlining_SoA_symmetry_ILP_8,1000,200,13822000000,64056.0,1078.9,7384531456.0,1.872 +variant_float_inlining_SoA_symmetry_ILP_8,2000,200,55244000000,128056.0,2157.03,31106564096.0,1.776 +variant_float_inlining_SoA_symmetry_ILP_8,5000,200,345110000000,320056.0,5391.4,205839695872.0,1.677 +variant_inlining_7,50,200,36910000,6512.0,28.34,26121151.7,1.413 +variant_inlining_7,100,200,145820000,12912.0,56.47,102845253.3,1.418 +variant_inlining_7,200,200,579640000,25712.0,112.72,414933826.7,1.397 +variant_inlining_7,500,200,3609100000,64112.0,281.47,2696322800.0,1.339 +variant_inlining_7,1000,200,14418200000,128112.0,562.72,10910614700.0,1.321 +variant_inlining_7,2000,200,57636400000,256112.0,1125.22,44697241900.0,1.289 +variant_inlining_7,5000,200,360091000000,640112.0,2812.72,301883852420.0,1.193 +variant_inlining_7_SoA,50,200,36910000,6512.0,28.34,35321441.7,1.045 +variant_inlining_7_SoA,100,200,145820000,12912.0,56.47,135295173.3,1.078 +variant_inlining_7_SoA,200,200,579640000,25712.0,112.72,568212960.0,1.02 +variant_inlining_7_SoA,500,200,3609100000,64112.0,281.47,3522666700.0,1.025 +variant_inlining_7_SoA,1000,200,14418200000,128112.0,562.72,13818697526.7,1.043 +variant_inlining_7_SoA,2000,200,57636400000,256112.0,1125.22,55165644633.3,1.045 +variant_inlining_7_SoA,5000,200,360091000000,640112.0,2812.72,339567715040.0,1.06 +variant_inlining_7_SoA_AVX2,50,200,39660000,6512.0,30.45,16930248.3,2.343 +variant_inlining_7_SoA_AVX2,100,200,149400000,12912.0,57.85,57593386.7,2.594 +variant_inlining_7_SoA_AVX2,200,200,590800000,25712.0,114.89,221606086.7,2.666 +variant_inlining_7_SoA_AVX2,500,200,3667000000,64112.0,285.98,1355735366.7,2.705 +variant_inlining_7_SoA_AVX2,1000,200,14634000000,128112.0,571.14,5363998226.7,2.728 +variant_inlining_7_SoA_AVX2,2000,200,58468000000,256112.0,1141.45,21340824240.0,2.74 +variant_inlining_7_SoA_AVX2,5000,200,365170000000,640112.0,2852.39,118313683993.3,3.086 +variant_inlining_7_SoA_AVX2,10000,200,1460340000000,1280112.0,5703.95,483403608680.0,3.021 +variant_inlining_7_SoA_AVX2_polyexp,50,200,39660000,6512.0,30.45,11360558.3,3.491 +variant_inlining_7_SoA_AVX2_polyexp,100,200,149400000,12912.0,57.85,39974676.7,3.737 +variant_inlining_7_SoA_AVX2_polyexp,200,200,590800000,25712.0,114.89,152454126.7,3.875 +variant_inlining_7_SoA_AVX2_polyexp,500,200,3667000000,64112.0,285.98,924841613.3,3.965 +variant_inlining_7_SoA_AVX2_polyexp,1000,200,14634000000,128112.0,571.14,3677548486.7,3.979 +variant_inlining_7_SoA_AVX2_polyexp,2000,200,58468000000,256112.0,1141.45,14646151666.7,3.992 +variant_inlining_7_SoA_AVX2_polyexp,5000,200,365170000000,640112.0,2852.39,91635680486.7,3.985 +variant_inlining_7_SoA_AVX2_polyexp,10000,200,1460340000000,1280112.0,5703.95,362144000826.7,4.032 +variant_inlining_7_symmetry_1,50,200,35440000,6512.0,27.21,26691613.3,1.328 +variant_inlining_7_symmetry_1,100,200,139880000,12912.0,54.17,104115826.7,1.344 +variant_inlining_7_symmetry_1,200,200,555760000,25712.0,108.07,420221973.3,1.323 +variant_inlining_7_symmetry_1,500,200,3459400000,64112.0,269.79,2784195260.0,1.243 +variant_inlining_7_symmetry_1,1000,200,13818800000,128112.0,539.32,11440548280.0,1.208 +variant_inlining_7_symmetry_1,2000,200,55237600000,256112.0,1078.39,46724088026.7,1.182 +variant_inlining_7_symmetry_1,5000,200,345094000000,640112.0,2695.58,208238979073.3,1.657 +variant_inlining_7_symmetry_2,50,200,35440000,6512.0,27.21,26825500.0,1.321 +variant_inlining_7_symmetry_2,100,200,139880000,12912.0,54.17,104047720.0,1.344 +variant_inlining_7_symmetry_2,200,200,555760000,25712.0,108.07,418572093.3,1.328 +variant_inlining_7_symmetry_2,500,200,3459400000,64112.0,269.79,2796809913.3,1.237 +variant_inlining_7_symmetry_2,1000,200,13818800000,128112.0,539.32,11473883373.3,1.204 +variant_inlining_7_symmetry_2,2000,200,55237600000,256112.0,1078.39,47218873140.0,1.17 +variant_inlining_7_symmetry_2,5000,200,345094000000,640112.0,2695.58,212940538246.7,1.621 +variant_inlining_7_symmetry_2_ilp_1,50,200,35520000,6512.0,27.27,26576390.0,1.337 +variant_inlining_7_symmetry_2_ilp_1,100,200,140040000,12912.0,54.23,102705346.7,1.364 +variant_inlining_7_symmetry_2_ilp_1,200,200,556080000,25712.0,108.14,414853306.7,1.34 +variant_inlining_7_symmetry_2_ilp_1,500,200,3460200000,64112.0,269.86,2745536040.0,1.26 +variant_inlining_7_symmetry_2_ilp_1,1000,200,13820400000,128112.0,539.39,11346744286.7,1.218 +variant_inlining_7_symmetry_2_ilp_1,2000,200,55240800000,256112.0,1078.45,45827858580.0,1.205 +variant_inlining_7_symmetry_2_ilp_1,5000,200,345102000000,640112.0,2695.64,216145504520.0,1.597 +variant_inlining_7_symmetry_2_ilp_2,50,200,35600000,6512.0,27.33,26837608.3,1.326 +variant_inlining_7_symmetry_2_ilp_2,100,200,140200000,12912.0,54.29,104635440.0,1.34 +variant_inlining_7_symmetry_2_ilp_2,200,200,556400000,25712.0,108.2,421424786.7,1.32 +variant_inlining_7_symmetry_2_ilp_2,500,200,3461000000,64112.0,269.92,2800723726.7,1.236 +variant_inlining_7_symmetry_2_ilp_2,1000,200,13822000000,128112.0,539.45,11627472146.7,1.189 +variant_inlining_7_symmetry_2_ilp_2,2000,200,55244000000,256112.0,1078.51,47722643580.0,1.158 +variant_inlining_7_symmetry_2_ilp_2,5000,200,345110000000,640112.0,2695.7,316224530286.7,1.091 +variant_inlining_8,50,200,36750000,6512.0,28.22,25967831.7,1.415 +variant_inlining_8,100,200,145500000,12912.0,56.34,102344446.7,1.422 +variant_inlining_8,200,200,579000000,25712.0,112.59,412337820.0,1.404 +variant_inlining_8,500,200,3607500000,64112.0,281.34,2712489206.7,1.33 +variant_inlining_8,1000,200,14415000000,128112.0,562.59,10911941346.7,1.321 +variant_inlining_8,2000,200,57630000000,256112.0,1125.09,44617296533.3,1.292 +variant_inlining_8,5000,200,360075000000,640112.0,2812.59,302676303926.7,1.19 +variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt,50,200,42720000,6512.0,32.8,8373508.8,5.102 +variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt,100,200,155520000,12912.0,60.22,28637320.0,5.431 +variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt,200,200,591360000,25712.0,115.0,104580140.0,5.655 +variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt,500,200,3697600000,64112.0,288.37,637315293.3,5.802 +variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt,1000,200,14636800000,128112.0,571.25,2508058493.3,5.836 +variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt,2000,200,58473600000,256112.0,1141.56,9964964006.7,5.868 +variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt,5000,200,365184000000,640112.0,2852.5,61862883653.3,5.903 +variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt,10000,200,1460368000000,1280112.0,5704.06,246835017580.0,5.916 +variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr,50,200,42720000,6512.0,32.8,8324976.2,5.132 +variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr,100,200,155520000,12912.0,60.22,28461063.3,5.464 +variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr,200,200,591360000,25712.0,115.0,104197200.0,5.675 +variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr,500,200,3697600000,64112.0,288.37,634698826.7,5.826 +variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr,1000,200,14636800000,128112.0,571.25,2497438973.3,5.861 +variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr,2000,200,58473600000,256112.0,1141.56,9905258186.7,5.903 +variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr,5000,200,365184000000,640112.0,2852.5,61800905773.3,5.909 +variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr,10000,200,1460368000000,1280112.0,5704.06,246638909100.0,5.921 +variant_inlining_8_SoA_AVX512_polyexp_moreavx,50,200,42522400,6512.0,32.65,8002191.7,5.314 +variant_inlining_8_SoA_AVX512_polyexp_moreavx,100,200,155081600,12912.0,60.05,27743588.3,5.59 +variant_inlining_8_SoA_AVX512_polyexp_moreavx,200,200,590440000,25712.0,114.82,102487693.3,5.761 +variant_inlining_8_SoA_AVX512_polyexp_moreavx,500,200,3695321600,64112.0,288.19,632610206.7,5.841 +variant_inlining_8_SoA_AVX512_polyexp_moreavx,1000,200,14632200000,128112.0,571.07,2470303860.0,5.923 +variant_inlining_8_SoA_AVX512_polyexp_moreavx,2000,200,58464400000,256112.0,1141.38,9838694466.7,5.942 +variant_inlining_8_SoA_AVX512_polyexp_moreavx,5000,200,365161000000,640112.0,2852.32,61438052786.7,5.944 +variant_inlining_8_SoA_AVX512_polyexp_moreavx,10000,200,1460322000000,1280112.0,5703.88,245546828340.0,5.947 +variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2,50,200,48565600,6512.0,37.29,8523056.7,5.698 +variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2,100,200,167124800,12912.0,64.72,27731721.7,6.026 +variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2,200,200,614483200,25712.0,119.49,98272536.7,6.253 +variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2,500,200,3755364800,64112.0,292.88,588475846.7,6.382 +variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2,1000,200,14752243200,128112.0,575.76,2281054360.0,6.467 +variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2,2000,200,58470800000,256112.0,1141.51,8988870633.3,6.505 +variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2,5000,200,365761043200,640112.0,2857.01,56207738100.0,6.507 +variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2,10000,200,1460354000000,1280112.0,5704.01,224126171313.3,6.516 +variant_lut_exp,50,200,36900000,6512.0,28.33,28594623.3,1.29 +variant_lut_exp,100,200,145800000,12912.0,56.46,108870166.7,1.339 +variant_lut_exp,200,200,579600000,25712.0,112.71,435786306.7,1.33 +variant_lut_exp,500,200,3609000000,64112.0,281.46,2898102033.3,1.245 +variant_lut_exp,1000,200,14418000000,128112.0,562.71,11825768686.7,1.219 +variant_lut_exp,2000,200,57636000000,256112.0,1125.21,47853617373.3,1.204 +variant_lut_exp,5000,200,360090000000,640112.0,2812.71,305260944300.0,1.18 diff --git a/benchmarks/.gitkeep b/benchmarks/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/flopcounts/x86/variant_AVX512_1.py b/flopcounts/x86/variant_AVX512_1.py new file mode 100644 index 0000000..bbb40bb --- /dev/null +++ b/flopcounts/x86/variant_AVX512_1.py @@ -0,0 +1,100 @@ +# ADDs: n_iter * n_p * 4 + +# n_iter * n_p * ceil(((double) (n_p - 7)) / 8) * (1 / (ceil(((double) (n_p - 7)) / 8))) * 7 * 14 + +# n_iter * n_p * ceil(((double) (n_p - 7)) / 8) * (1 - 1 / (ceil(((double) (n_p - 7)) / 8))) * 224 + +# n_iter * n_p * (n_p - floor((double) n_p / 8) * 8) * 14 + +# n_iter * n_p * board.n_obstacles * 12 + +# n_iter * n_p * 7 + +# MULTs: n_iter * n_p * 4 + +# n_iter * n_p * ceil(((double) (n_p - 7)) / 8) * (1 / (ceil(((double) (n_p - 7)) / 8))) * 7 * 24 + +# n_iter * n_p * ceil(((double) (n_p - 7)) / 8) * (1 - 1 / (ceil(((double) (n_p - 7)) / 8))) * 352 + +# n_iter * n_p * (n_p - floor((double) n_p / 8) * 8) * 24 + +# n_iter * n_p * board.n_obstacles * 19 + +# n_iter * n_p * 17 + +# DIVs: n_iter * n_p * ceil(((double) (n_p - 7)) / 8) * (1 / (ceil(((double) (n_p - 7)) / 8))) * 7 + +# n_iter * n_p * ceil(((double) (n_p - 7)) / 8) * (1 - 1 / (ceil(((double) (n_p - 7)) / 8))) * 8 + +# n_iter * n_p * (n_p - floor((double) n_p / 8) * 8) + +# n_iter * n_p * board.n_obstacles + +# n_iter * n_p * 2 + +# SQRTs: n_iter * n_p * ceil(((double) (n_p - 7)) / 8) * (1 / (ceil(((double) (n_p - 7)) / 8))) * 7 * 3 + +# n_iter * n_p * ceil(((double) (n_p - 7)) / 8) * (1 - 1 / (ceil(((double) (n_p - 7)) / 8))) * 24 + +# n_iter * n_p * (n_p - floor((double) n_p / 8) * 8) * 3 + +# n_iter * n_p * board.n_obstacles + +# n_iter * n_p * 3 + +# EXPs: n_iter * n_p * ceil(((double) (n_p - 7)) / 8) * (1 / (ceil(((double) (n_p - 7)) / 8))) * 7 + +# n_iter * n_p * (n_p - floor((double) n_p / 8) * 8) + +# n_iter * n_p * board.n_obstacles + +from math import ceil + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + chunks = ceil((n_p - 7) / 8) if n_p > 7 else 0 + remainder = n_p - int(n_p // 8) * 8 + if chunks > 0: + term1 = n_iter * n_p * chunks * (1 / chunks) * 7 * 14 + term2 = n_iter * n_p * chunks * (1 - 1 / chunks) * 224 + else: + term1 = 0 + term2 = 0 + return int(n_iter * n_p * 4 + term1 + term2 + n_iter * n_p * remainder * 14 + + n_iter * n_p * n_obs * 12 + n_iter * n_p * 7) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + chunks = ceil((n_p - 7) / 8) if n_p > 7 else 0 + remainder = n_p - int(n_p // 8) * 8 + if chunks > 0: + term1 = n_iter * n_p * chunks * (1 / chunks) * 7 * 24 + term2 = n_iter * n_p * chunks * (1 - 1 / chunks) * 352 + else: + term1 = 0 + term2 = 0 + return int(n_iter * n_p * 4 + term1 + term2 + n_iter * n_p * remainder * 24 + + n_iter * n_p * n_obs * 19 + n_iter * n_p * 17) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + chunks = ceil((n_p - 7) / 8) if n_p > 7 else 0 + remainder = n_p - int(n_p // 8) * 8 + if chunks > 0: + term1 = n_iter * n_p * chunks * (1 / chunks) * 7 + term2 = n_iter * n_p * chunks * (1 - 1 / chunks) * 8 + else: + term1 = 0 + term2 = 0 + return int(n_iter * n_p * 4 + term1 + term2 + n_iter * n_p * remainder + + n_iter * n_p * n_obs + n_iter * n_p * 2) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + chunks = ceil((n_p - 7) / 8) if n_p > 7 else 0 + remainder = n_p - int(n_p // 8) * 8 + if chunks > 0: + term1 = n_iter * n_p * chunks * (1 / chunks) * 7 * 3 + term2 = n_iter * n_p * chunks * (1 - 1 / chunks) * 24 + else: + term1 = 0 + term2 = 0 + return int(n_iter * n_p * 4 + term1 + term2 + n_iter * n_p * remainder * 3 + + n_iter * n_p * n_obs + n_iter * n_p * 3) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + chunks = ceil((n_p - 7) / 8) if n_p > 7 else 0 + remainder = n_p - int(n_p // 8) * 8 + if chunks > 0: + term1 = n_iter * n_p * chunks * (1 / chunks) * 7 + else: + term1 = 0 + return int(n_iter * n_p * 4 + term1 + n_iter * n_p * remainder + + n_iter * n_p * n_obs + n_iter * n_p * 3) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_baseline.py b/flopcounts/x86/variant_baseline.py new file mode 100644 index 0000000..adccae7 --- /dev/null +++ b/flopcounts/x86/variant_baseline.py @@ -0,0 +1,58 @@ +# ADDs: n_iter * ( +# n_p * 4 + +# n_p * (n_p - 1) * 14 + +# n_p * board.n_obstacles * 10 + +# n_p * 7 +# ) + +# MULTs: n_iter * ( +# n_p * 4 +# n_p * (n_p - 1) * 24 + +# n_p * board.n_obstacles * 13 + +# n_p * 16 +# ) + +# DIVs: n_iter * ( +# n_p * (n_p - 1) + +# n_p * board.n_obstacles + +# n_p * 2 +# ) + +# SQRTs: n_iter * ( +# n_p * (n_p - 1) * 3 + +# n_p * board.n_obstacles + +# n_p * 3 +# ) + +# EXPs: n_iter * ( +# n_p * (n_p - 1) + +# n_p * board.n_obstacles +# ) + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * 4 + n_p * + (n_p - 1) * 14 + n_p * n_obs * 10 + n_p * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * 4 + n_p * + (n_p - 1) * 24 + n_p * n_obs * 13 + n_p * 16)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) + n_p * n_obs + n_p * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) * 3 + n_p * n_obs + n_p * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) + n_p * n_obs)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_branchless.py b/flopcounts/x86/variant_branchless.py new file mode 100644 index 0000000..36f1ca3 --- /dev/null +++ b/flopcounts/x86/variant_branchless.py @@ -0,0 +1,27 @@ +# n_iter * [n_p ** 2 * (15 A + 24 M + 1 D + 4 S + 1 E) + n_p * (- 4 A - 4 M + 1 D - 1 S - 1 E) + n_obstacles * n_p * (13 A + 19 M + 1 D + 2 S + 1 E)] + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 15 + n_p * (-4) + n_obs * n_p * 13)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 24 + n_p * (-4) + n_obs * n_p * 19)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 1 + n_p * 1 + n_obs * n_p * 1)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 4 + n_p * (-1) + n_obs * n_p * 2)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 1 + n_p * (-1) + n_obs * n_p * 1)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_branchless_sqrtfree.py b/flopcounts/x86/variant_branchless_sqrtfree.py new file mode 100644 index 0000000..4c9158a --- /dev/null +++ b/flopcounts/x86/variant_branchless_sqrtfree.py @@ -0,0 +1,27 @@ +# n_iter * [n_p ** 2 * (15 A + 25 M + 1 D + 3 S + 1 E) + n_p * (- 4 A - 5 M + 1 D - 1 E) + n_obstacles * n_p * (13 A + 20 M + 1 D + 1 S + 1 E)] + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 15 + n_p * (-4) + n_obs * n_p * 13)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 25 + n_p * (-5) + n_obs * n_p * 20)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 1 + n_p * 1 + n_obs * n_p * 1)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 3 + n_obs * n_p * 1)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 1 + n_p * (-1) + n_obs * n_p * 1)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_cutoff.py b/flopcounts/x86/variant_cutoff.py new file mode 100644 index 0000000..cd3a418 --- /dev/null +++ b/flopcounts/x86/variant_cutoff.py @@ -0,0 +1,27 @@ +# n_iter * [ n_p ** 2 * (14 A + 23 M + 1 D + 4 S + 1 E) + n_p * (- 3 A - 3 M + 1 D - 1 S - 1 E) + n_obstacles * n_p * (12 A + 18 M + 1 D + 2 S + 1 E) ] + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 14 + n_p * (-3) + n_obs * n_p * 12)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 23 + n_p * (-3) + n_obs * n_p * 18)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 1 + n_p * 1 + n_obs * n_p * 1)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 4 + n_p * (-1) + n_obs * n_p * 2)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 1 + n_p * (-1) + n_obs * n_p * 1)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_cutoff_callsite.py b/flopcounts/x86/variant_cutoff_callsite.py new file mode 100644 index 0000000..cd3a418 --- /dev/null +++ b/flopcounts/x86/variant_cutoff_callsite.py @@ -0,0 +1,27 @@ +# n_iter * [ n_p ** 2 * (14 A + 23 M + 1 D + 4 S + 1 E) + n_p * (- 3 A - 3 M + 1 D - 1 S - 1 E) + n_obstacles * n_p * (12 A + 18 M + 1 D + 2 S + 1 E) ] + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 14 + n_p * (-3) + n_obs * n_p * 12)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 23 + n_p * (-3) + n_obs * n_p * 18)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 1 + n_p * 1 + n_obs * n_p * 1)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 4 + n_p * (-1) + n_obs * n_p * 2)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 1 + n_p * (-1) + n_obs * n_p * 1)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_float_baseline.py b/flopcounts/x86/variant_float_baseline.py new file mode 100644 index 0000000..c41efdf --- /dev/null +++ b/flopcounts/x86/variant_float_baseline.py @@ -0,0 +1,57 @@ +# ADDs: n_iter * ( +# n_p * 4 + +# n_p * (n_p - 1) * 14 + +# n_p * board.n_obstacles * 10 + +# n_p * 7 +# ) + +# MULTs: n_iter * ( +# n_p * 4 +# n_p * (n_p - 1) * 24 + +# n_p * board.n_obstacles * 13 + +# n_p * 16 +# ) + +# DIVs: n_iter * ( +# n_p * (n_p - 1) + +# n_p * board.n_obstacles + +# n_p * 2 +# ) + +# SQRTs: n_iter * ( +# n_p * (n_p - 1) * 3 + +# n_p * board.n_obstacles + +# n_p * 3 +# ) + +# EXPs: n_iter * ( +# n_p * (n_p - 1) + +# n_p * board.n_obstacles +# ) + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * 4 + n_p * + (n_p - 1) * 14 + n_p * n_obs * 10 + n_p * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * 4 + n_p * + (n_p - 1) * 24 + n_p * n_obs * 13 + n_p * 16)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) + n_p * n_obs + n_p * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) * 3 + n_p * n_obs + n_p * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) + n_p * n_obs)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, n_obs) + exps(n_iter, n_p, n_obs) diff --git a/flopcounts/x86/variant_float_inlining.py b/flopcounts/x86/variant_float_inlining.py new file mode 100644 index 0000000..164f8b1 --- /dev/null +++ b/flopcounts/x86/variant_float_inlining.py @@ -0,0 +1,58 @@ +# ADDs: n_iter * ( +# n_p * 4 + +# n_p * (n_p - 1) * 14 + +# n_p * board.n_obstacles * 10 + +# n_p * 7 +# ) + +# MULTs: n_iter * ( +# n_p * 4 +# n_p * (n_p - 1) * 24 + +# n_p * board.n_obstacles * 13 + +# n_p * 17 +# ) + +# DIVs: n_iter * ( +# n_p * (n_p - 1) + +# n_p * board.n_obstacles + +# n_p * 2 +# ) + +# SQRTs: n_iter * ( +# n_p * (n_p - 1) * 3 + +# n_p * board.n_obstacles + +# n_p * 3 +# ) + +# EXPs: n_iter * ( +# n_p * (n_p - 1) + +# n_p * board.n_obstacles +# ) + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * 4 + n_p * + (n_p - 1) * 14 + n_p * n_obs * 10 + n_p * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * 4 + n_p * + (n_p - 1) * 24 + n_p * n_obs * 13 + n_p * 17)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) + n_p * n_obs + n_p * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) * 3 + n_p * n_obs + n_p * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) + n_p * n_obs)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_float_inlining_SoA.py b/flopcounts/x86/variant_float_inlining_SoA.py new file mode 100644 index 0000000..164f8b1 --- /dev/null +++ b/flopcounts/x86/variant_float_inlining_SoA.py @@ -0,0 +1,58 @@ +# ADDs: n_iter * ( +# n_p * 4 + +# n_p * (n_p - 1) * 14 + +# n_p * board.n_obstacles * 10 + +# n_p * 7 +# ) + +# MULTs: n_iter * ( +# n_p * 4 +# n_p * (n_p - 1) * 24 + +# n_p * board.n_obstacles * 13 + +# n_p * 17 +# ) + +# DIVs: n_iter * ( +# n_p * (n_p - 1) + +# n_p * board.n_obstacles + +# n_p * 2 +# ) + +# SQRTs: n_iter * ( +# n_p * (n_p - 1) * 3 + +# n_p * board.n_obstacles + +# n_p * 3 +# ) + +# EXPs: n_iter * ( +# n_p * (n_p - 1) + +# n_p * board.n_obstacles +# ) + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * 4 + n_p * + (n_p - 1) * 14 + n_p * n_obs * 10 + n_p * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * 4 + n_p * + (n_p - 1) * 24 + n_p * n_obs * 13 + n_p * 17)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) + n_p * n_obs + n_p * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) * 3 + n_p * n_obs + n_p * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) + n_p * n_obs)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_float_inlining_SoA_AVX2.py b/flopcounts/x86/variant_float_inlining_SoA_AVX2.py new file mode 100644 index 0000000..2cc0f8e --- /dev/null +++ b/flopcounts/x86/variant_float_inlining_SoA_AVX2.py @@ -0,0 +1,41 @@ +# const int n_p_pad = (n_p + 7) & ~7; + +# flops per iteration (one pass of the outer time loop): +# ADDs: n_p * 22 + n_p * n_p_pad * 15 + n_p * board.n_obstacles * 10 + n_p * 7 +# MULTs: n_p * 4 + n_p * n_p_pad * 24 + n_p * board.n_obstacles * 13 + n_p * 16 +# DIVs: n_p * n_p_pad * 1 + n_p * board.n_obstacles + n_p * 2 +# SQRTs: n_p * n_p_pad * 3 + n_p * board.n_obstacles + n_p * 3 +# EXPs: n_p * n_p_pad * 1 + n_p * board.n_obstacles + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * + (n_p * 22 + n_p * n_p_pad * 15 + n_p * n_obs * 10 + n_p * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * + (n_p * 4 + n_p * n_p_pad * 24 + n_p * n_obs * 13 + n_p * 16)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * (n_p * n_p_pad * 1 + n_p * n_obs + n_p * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * (n_p * n_p_pad * 3 + n_p * n_obs + n_p * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * (n_p * n_p_pad * 1 + n_p * n_obs)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_float_inlining_SoA_AVX2_polyexp.py b/flopcounts/x86/variant_float_inlining_SoA_AVX2_polyexp.py new file mode 100644 index 0000000..b6782b2 --- /dev/null +++ b/flopcounts/x86/variant_float_inlining_SoA_AVX2_polyexp.py @@ -0,0 +1,41 @@ +# const int n_p_pad = (n_p + 7) & ~7; + +# flops per iteration (one pass of the outer time loop): +# ADDs: n_p * 22 + n_p * n_p_pad * 29 + n_p * board.n_obstacles * 10 + n_p * 7 +# MULTs: n_p * 4 + n_p * n_p_pad * 40 + n_p * board.n_obstacles * 13 + n_p * 16 +# DIVs: n_p * n_p_pad * 1 + n_p * board.n_obstacles + n_p * 2 +# SQRTs: n_p * n_p_pad * 3 + n_p * board.n_obstacles + n_p * 3 +# EXPs: n_p * board.n_obstacles + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * + (n_p * 22 + n_p * n_p_pad * 29 + n_p * n_obs * 10 + n_p * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * + (n_p * 4 + n_p * n_p_pad * 40 + n_p * n_obs * 13 + n_p * 16)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * (n_p * n_p_pad * 1 + n_p * n_obs + n_p * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * (n_p * n_p_pad * 3 + n_p * n_obs + n_p * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * (n_p * n_obs)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_float_inlining_SoA_AVX2_polyexp_rsqrt.py b/flopcounts/x86/variant_float_inlining_SoA_AVX2_polyexp_rsqrt.py new file mode 100644 index 0000000..fc34b9f --- /dev/null +++ b/flopcounts/x86/variant_float_inlining_SoA_AVX2_polyexp_rsqrt.py @@ -0,0 +1,41 @@ +# const int n_p_pad = (n_p + 7) & ~7; + +# flops per iteration (one pass of the outer time loop): +# ADDs: n_p * 22 + n_p * n_p_pad * 29 + n_p * board.n_obstacles * 10 + n_p * 7 +# MULTs: n_p * 4 + n_p * n_p_pad * 42 + n_p * board.n_obstacles * 13 + n_p * 16 +# DIVs: n_p * n_p_pad * 3 + n_p * board.n_obstacles + n_p * 2 +# SQRTs: n_p * n_p_pad * 3 + n_p * board.n_obstacles + n_p * 3 +# EXPs: n_p * board.n_obstacles + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * + (n_p * 22 + n_p * n_p_pad * 29 + n_p * n_obs * 10 + n_p * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * + (n_p * 4 + n_p * n_p_pad * 42 + n_p * n_obs * 13 + n_p * 16)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * (n_p * n_p_pad * 3 + n_p * n_obs + n_p * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * (n_p * n_p_pad * 3 + n_p * n_obs + n_p * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * (n_p * n_obs)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt.py b/flopcounts/x86/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt.py new file mode 100644 index 0000000..d2f15d8 --- /dev/null +++ b/flopcounts/x86/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt.py @@ -0,0 +1,41 @@ +# const int n_p_pad = (n_p + 7) & ~7; + +# flops per iteration (one pass of the outer time loop): +# ADDs: n_p * 22 + n_p * n_p_pad * 28 + n_p * board.n_obstacles * 10 + n_p * 7 +# MULTs: n_p * 4 + n_p * n_p_pad * 42 + n_p * board.n_obstacles * 13 + n_p * 16 +# DIVs: n_p * n_p_pad * 3 + n_p * board.n_obstacles + n_p * 2 +# SQRTs: n_p * n_p_pad * 3 + n_p * board.n_obstacles + n_p * 3 +# EXPs: n_p * board.n_obstacles + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * + (n_p * 22 + n_p * n_p_pad * 28 + n_p * n_obs * 10 + n_p * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * + (n_p * 4 + n_p * n_p_pad * 42 + n_p * n_obs * 13 + n_p * 16)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * (n_p * n_p_pad * 3 + n_p * n_obs + n_p * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * (n_p * n_p_pad * 3 + n_p * n_obs + n_p * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * (n_p * n_obs)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp.py b/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp.py new file mode 100644 index 0000000..7c7b970 --- /dev/null +++ b/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp.py @@ -0,0 +1,62 @@ +# const int n_p_pad = (n_p + 15) & ~15; + +# ADDs: n_iter * ( +# n_p * 36 + +# n_p * n_p_pad * 29 + +# n_p * board.n_obstacles * 10 + +# n_p * 7 +# ) +# +# MULTs: n_iter * ( +# n_p * 4 + +# n_p * n_p_pad * 40 + +# n_p * board.n_obstacles * 13 + +# n_p * 17 +# ) +# +# DIVs: n_iter * ( +# n_p * n_p_pad + +# n_p * board.n_obstacles + +# n_p * 2 +# ) +# +# SQRTs: n_iter * ( +# n_p * n_p_pad * 3 + +# n_p * board.n_obstacles + +# n_p * 3 +# ) +# +# EXPs: n_iter * n_p * board.n_obstacles + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int(n_iter * + (n_p * 36 + n_p * n_p_pad * 29 + n_p * n_obs * 10 + n_p * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int(n_iter * + (n_p * 4 + n_p * n_p_pad * 40 + n_p * n_obs * 13 + n_p * 17)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int(n_iter * (n_p * n_p_pad + n_p * n_obs + n_p * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int(n_iter * (n_p * n_p_pad * 3 + n_p * n_obs + n_p * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int(n_iter * n_p * n_obs) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt.py b/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt.py new file mode 100644 index 0000000..eadaa90 --- /dev/null +++ b/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt.py @@ -0,0 +1,61 @@ +# const int n_p_pad = (n_p + 15) & ~15; + +# ADDs: n_iter * ( +# n_p * 36 + +# n_p * n_p_pad * 29 + +# n_p * board.n_obstacles * 10 + +# n_p * 11 +# ) + +# MULTs: n_iter * ( +# n_p * 4 + +# n_p * n_p_pad * 40 + +# n_p * board.n_obstacles * 13 + +# n_p * 30 +# ) + +# DIVs: n_iter * ( +# n_p * n_p_pad + +# n_p * board.n_obstacles +# ) + +# SQRTs: n_iter * ( +# n_p * n_p_pad * 3 + +# n_p * board.n_obstacles + +# n_p +# ) + +# EXPs: n_iter * n_p * board.n_obstacles + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int(n_iter * + (n_p * 36 + n_p * n_p_pad * 29 + n_p * n_obs * 10 + n_p * 11)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int(n_iter * + (n_p * 4 + n_p * n_p_pad * 40 + n_p * n_obs * 13 + n_p * 30)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int(n_iter * (n_p * n_p_pad + n_p * n_obs)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int(n_iter * (n_p * n_p_pad * 3 + n_p * n_obs + n_p)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int(n_iter * n_p * n_obs) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx.py b/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx.py new file mode 100644 index 0000000..5f99895 --- /dev/null +++ b/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx.py @@ -0,0 +1,62 @@ +# const int n_p_pad = (n_p + 15) & ~15; + +# ADDs: n_iter * ( +# n_p * 36 + +# n_p * n_p_pad * 29 + +# n_p * board.n_obstacles * 10 + +# n_p_pad * 7 +# ) + +# MULTs: n_iter * ( +# n_p * 4 + +# n_p * n_p_pad * 40 + +# n_p * board.n_obstacles * 13 + +# n_p_pad * 15 +# ) + +# DIVs: n_iter * ( +# n_p * n_p_pad + +# n_p * board.n_obstacles + +# n_p_pad * 2 +# ) + +# SQRTs: n_iter * ( +# n_p * n_p_pad * 3 + +# n_p * board.n_obstacles + +# n_p_pad * 3 +# ) + +# EXPs: n_iter * n_p * board.n_obstacles + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int(n_iter * + (n_p * 36 + n_p * n_p_pad * 29 + n_p * n_obs * 10 + n_p_pad * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int(n_iter * + (n_p * 4 + n_p * n_p_pad * 40 + n_p * n_obs * 13 + n_p_pad * 15)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int(n_iter * (n_p * n_p_pad + n_p * n_obs + n_p_pad * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int(n_iter * (n_p * n_p_pad * 3 + n_p * n_obs + n_p_pad * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int(n_iter * n_p * n_obs) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2.py b/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2.py new file mode 100644 index 0000000..5144d2f --- /dev/null +++ b/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2.py @@ -0,0 +1,62 @@ +# const int n_p_pad = (n_p + 31) & ~31; + +# ADDs: n_iter * ( +# n_p * 68 + +# n_p * n_p_pad * 29 + +# n_p * board.n_obstacles * 10 + +# n_p_pad * 7 +# ) + +# MULTs: n_iter * ( +# n_p * 4 + +# n_p * n_p_pad * 40 + +# n_p * board.n_obstacles * 13 + +# n_p_pad * 15 +# ) + +# SQRTs: n_iter * ( +# n_p * n_p_pad * 3 + +# n_p * board.n_obstacles + +# n_p_pad * 3 +# ) + +# DIVs: n_iter * ( +# n_p * n_p_pad + +# n_p * board.n_obstacles + +# n_p_pad * 2 +# ) + +# EXPs: n_iter * n_p * board.n_obstacles + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * + (n_p * 68 + n_p * n_p_pad * 29 + n_p * n_obs * 10 + n_p_pad * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * + (n_p * 4 + n_p * n_p_pad * 40 + n_p * n_obs * 13 + n_p_pad * 15)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * (n_p * n_p_pad + n_p * n_obs + n_p_pad * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * (n_p * n_p_pad * 3 + n_p * n_obs + n_p_pad * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * n_p * n_obs) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp.py b/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp.py new file mode 100644 index 0000000..94937e5 --- /dev/null +++ b/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp.py @@ -0,0 +1,62 @@ +# const int n_p_pad = (n_p + 31) & ~31; + +# ADDs: n_iter * ( +# n_p * 68 + +# n_p * n_p_pad * 29 + +# n_p * board.n_obstacles * 10 + +# n_p_pad * 7 +# ) + +# MULTs: n_iter * ( +# n_p * 4 + +# n_p * n_p_pad * 40 + +# n_p * board.n_obstacles * 13 + +# n_p_pad * 15 +# ) + +# DIVs: n_iter * ( +# n_p * n_p_pad + +# n_p * board.n_obstacles + +# n_p_pad * 2 +# ) + +# SQRTs: n_iter * ( +# n_p * n_p_pad * 3 + +# n_p * board.n_obstacles + +# n_p_pad * 3 +# ) + +# EXPs: n_iter * n_p * board.n_obstacles + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * + (n_p * 68 + n_p * n_p_pad * 29 + n_p * n_obs * 10 + n_p_pad * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * + (n_p * 4 + n_p * n_p_pad * 40 + n_p * n_obs * 13 + n_p_pad * 15)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * (n_p * n_p_pad + n_p * n_obs + n_p_pad * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * (n_p * n_p_pad * 3 + n_p * n_obs + n_p_pad * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * n_p * n_obs) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt.py b/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt.py new file mode 100644 index 0000000..e922446 --- /dev/null +++ b/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt.py @@ -0,0 +1,62 @@ +# const int n_p_pad = (n_p + 31) & ~31; + +# ADDs: n_iter * ( +# n_p * 68 + +# n_p * n_p_pad * 29 +# n_p * board.n_obstacles * 10 +# n_p_pad * 9 +# ) + +# MULTs: n_iter * ( +# n_p * 4 + +# n_p * n_p_pad * 40 +# n_p * board.n_obstacles * 13 +# n_p_pad * 17 +# ) + +# DIVs: n_iter * ( +# n_p * n_p_pad +# n_p * board.n_obstacles +# n_p_pad * 2 +# ) + +# SQRTs: n_iter * ( +# n_p * n_p_pad * 3 +# n_p * board.n_obstacles +# n_p_pad * 3 +# ) + +# EXPs: n_iter * n_p * board.n_obstacles + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * + (n_p * 68 + n_p * n_p_pad * 29 + n_p * n_obs * 10 + n_p_pad * 9)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * + (n_p * 4 + n_p * n_p_pad * 40 + n_p * n_obs * 13 + n_p_pad * 17)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * (n_p * n_p_pad + n_p * n_obs + n_p_pad * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * (n_p * n_p_pad * 3 + n_p * n_obs + n_p_pad * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * n_p * n_obs) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt.py b/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt.py new file mode 100644 index 0000000..6dc63c9 --- /dev/null +++ b/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt.py @@ -0,0 +1,61 @@ +# const int n_p_pad = (n_p + 31) & ~31; + +# ADDs: n_iter * ( +# n_p * 68 + +# n_p * n_p_pad * 29 + +# n_p * board.n_obstacles * 10 + +# n_p_pad * 7 +# ) + +# MULTs: n_iter * ( +# n_p * 4 + +# n_p * n_p_pad * 42 + +# n_p * board.n_obstacles * 13 + +# n_p_pad * 16 +# ) + +# DIVs: n_iter * ( +# n_p * n_p_pad * 3 + +# n_p * board.n_obstacles + +# n_p_pad * 2 +# ) + +# SQRTs: n_iter * ( +# n_p * n_p_pad * 3 + +# n_p * board.n_obstacles + +# n_p_pad * 3 +# ) + +# EXPs: n_iter * n_p * board.n_obstacles + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * + (n_p * 68 + n_p * n_p_pad * 29 + n_p * n_obs * 10 + n_p_pad * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * + (n_p * 4 + n_p * n_p_pad * 42 + n_p * n_obs * 13 + n_p_pad * 16)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * (n_p * n_p_pad * 3 + n_p * n_obs + n_p_pad * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * (n_p * n_p_pad * 3 + n_p * n_obs + n_p_pad * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * n_p * n_obs) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved.py b/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved.py new file mode 100644 index 0000000..363f7ee --- /dev/null +++ b/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved.py @@ -0,0 +1,61 @@ +# const int n_p_pad = (n_p + 31) & ~31; + +# ADDs: n_iter * ( +# n_p * 84 + +# n_p * n_p_pad * 29 + +# n_p * board.n_obstacles * 10 + +# n_p_pad * 7 +# ) + +# MULTs: n_iter * ( +# n_p * 4 + +# n_p * n_p_pad * 42 + +# n_p * board.n_obstacles * 13 + +# n_p_pad * 16 +# ) + +# DIVs: n_iter * ( +# n_p * n_p_pad * 3 + +# n_p * board.n_obstacles + +# n_p_pad * 2 +# ) + +# SQRTs: n_iter * ( +# n_p * n_p_pad * 3 + +# n_p * board.n_obstacles + +# n_p_pad * 3 +# ) + +# EXPs: n_iter * n_p * board.n_obstacles + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * + (n_p * 84 + n_p * n_p_pad * 29 + n_p * n_obs * 10 + n_p_pad * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * + (n_p * 4 + n_p * n_p_pad * 42 + n_p * n_obs * 13 + n_p_pad * 16)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * (n_p * n_p_pad * 3 + n_p * n_obs + n_p_pad * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * (n_p * n_p_pad * 3 + n_p * n_obs + n_p_pad * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 31) & ~31 + return int(n_iter * n_p * n_obs) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved_moreilp.py b/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved_moreilp.py new file mode 100644 index 0000000..616d546 --- /dev/null +++ b/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved_moreilp.py @@ -0,0 +1,62 @@ +# const int n_p_pad = (n_p + 15) & ~15; + +# ADDs: n_iter * ( +# n_p_pad * 7 + +# n_p_pad * n_p * 29 + +# n_p_pad * 2(=board.n_obstacles) * 24 + +# n_p_pad * 7 +# ) + +# MULTs: n_iter * ( +# n_p_pad * 4 + +# n_p_pad * n_p * 42 + +# n_p_pad * 2(=board.n_obstacles) * 31 + +# n_p_pad * 16 +# ) + +# DIVs: n_iter * ( +# n_p_pad * n_p * 3 + +# n_p_pad * 2(=board.n_obstacles) * 1 + +# n_p_pad * 2 +# ) + +# SQRTs: n_iter * ( +# n_p_pad * n_p * 3 + +# n_p_pad * 2(=board.n_obstacles) * 1 + +# n_p_pad * 3 +# ) + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int( + n_iter * + (n_p_pad * 7 + n_p_pad * n_p * 29 + n_p_pad * n_obs * 24 + n_p_pad * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int( + n_iter * + (n_p_pad * 4 + n_p_pad * n_p * 42 + n_p_pad * n_obs * 31 + n_p_pad * 16)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int(n_iter * (n_p_pad * n_p * 3 + n_p_pad * n_obs * 1 + n_p_pad * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int(n_iter * (n_p_pad * n_p * 3 + n_p_pad * n_obs * 1 + n_p_pad * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int(0) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4.py b/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4.py new file mode 100644 index 0000000..b1c9dc6 --- /dev/null +++ b/flopcounts/x86/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4.py @@ -0,0 +1,62 @@ +# const int n_p_pad = (n_p + 63) & ~63; + +# ADDs: n_iter * ( +# n_p * 132 + +# n_p * n_p_pad * 29 + +# n_p * board.n_obstacles * 10 + +# n_p_pad * 7 +# ) + +# MULTs: n_iter * ( +# n_p * 4 + +# n_p * n_p_pad * 40 + +# n_p * board.n_obstacles * 13 + +# n_p_pad * 15 +# ) + +# DIVs: n_iter * ( +# n_p * n_p_pad + +# n_p * board.n_obstacles + +# n_p_pad * 2 +# ) + +# SQRTs: n_iter * ( +# n_p * n_p_pad * 3 + +# n_p * board.n_obstacles + +# n_p_pad * 3 +# ) + +# EXPs: n_iter * n_p * board.n_obstacles + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 63) & ~63 + return int(n_iter * + (n_p * 132 + n_p * n_p_pad * 29 + n_p * n_obs * 10 + n_p_pad * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 63) & ~63 + return int(n_iter * + (n_p * 4 + n_p * n_p_pad * 40 + n_p * n_obs * 13 + n_p_pad * 15)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 63) & ~63 + return int(n_iter * (n_p * n_p_pad + n_p * n_obs + n_p_pad * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 63) & ~63 + return int(n_iter * (n_p * n_p_pad * 3 + n_p * n_obs + n_p_pad * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 63) & ~63 + return int(n_iter * n_p * n_obs) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_float_inlining_SoA_symmetry.py b/flopcounts/x86/variant_float_inlining_SoA_symmetry.py new file mode 100644 index 0000000..e85d49f --- /dev/null +++ b/flopcounts/x86/variant_float_inlining_SoA_symmetry.py @@ -0,0 +1,69 @@ +# FLOPCOUNT (everything inside the t-loop). EXP kept as its own op (one real exp() per call). +# section costs: overhead 4 ADD 4 MULT | distance pair 3 ADD 2 MULT 1 SQRT | +# ped-ped j 11 ADD 22 MULT 2 SQRT 1 DIV 1 EXP | +# obstacle 10 ADD 13 MULT 1 SQRT 1 DIV 1 EXP | update 7 ADD 17 MULT 3 SQRT 2 DIV + +# ADDs: n_iter * ( +# n_p * 4 + +# 0.5 * (n_p*n_p - n_p) * 3 + +# n_p * (n_p - 1) * 11 + +# n_p * board.n_obstacles * 10 + +# n_p * 7 +# ) + +# MULTs: n_iter * ( +# n_p * 4 + +# 0.5 * (n_p*n_p - n_p) * 2 + +# n_p * (n_p - 1) * 22 + +# n_p * board.n_obstacles * 13 + +# n_p * 17 +# ) + +# DIVs: n_iter * ( +# n_p * (n_p - 1) + +# n_p * board.n_obstacles + +# n_p * 2 +# ) + +# SQRTs: n_iter * ( +# 0.5 * (n_p*n_p - n_p) + +# n_p * (n_p - 1) * 2 + +# n_p * board.n_obstacles + +# n_p * 3 +# ) + +# EXPs: n_iter * ( +# n_p * (n_p - 1) + +# n_p * board.n_obstacles +# ) + +# total with EXP = 30: n_iter * ( 69 * n_p ** 2 - 32 * n_p + 55 * n_obstacles * n_p ) + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * 4 + 0.5 * (n_p * n_p - n_p) * 3 + n_p * + (n_p - 1) * 11 + n_p * n_obs * 10 + n_p * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * 4 + 0.5 * (n_p * n_p - n_p) * 2 + n_p * + (n_p - 1) * 22 + n_p * n_obs * 13 + n_p * 17)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) + n_p * n_obs + n_p * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (0.5 * (n_p * n_p - n_p) + n_p * + (n_p - 1) * 2 + n_p * n_obs + n_p * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) + n_p * n_obs)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_float_inlining_SoA_symmetry_ILP_16.py b/flopcounts/x86/variant_float_inlining_SoA_symmetry_ILP_16.py new file mode 100644 index 0000000..d48f213 --- /dev/null +++ b/flopcounts/x86/variant_float_inlining_SoA_symmetry_ILP_16.py @@ -0,0 +1,70 @@ +# FLOPCOUNT (everything inside the t-loop). EXP kept as its own op (one real exp() per call). +# section costs: overhead 4 ADD 4 MULT (+ reductions 4*K = 64 ADD, K=16) | +# distance pair 3 ADD 2 MULT 1 SQRT | +# ped-ped j 11 ADD 22 MULT 2 SQRT 1 DIV 1 EXP | +# obstacle 10 ADD 13 MULT 1 SQRT 1 DIV 1 EXP | update 7 ADD 17 MULT 3 SQRT 2 DIV + +# ADDs: n_iter * ( +# n_p * 68 + +# 0.5 * (n_p*n_p - n_p) * 3 + +# n_p * (n_p - 1) * 11 + +# n_p * board.n_obstacles * 10 + +# n_p * 7 +# ) + +# MULTs: n_iter * ( +# n_p * 4 + +# 0.5 * (n_p*n_p - n_p) * 2 + +# n_p * (n_p - 1) * 22 + +# n_p * board.n_obstacles * 13 + +# n_p * 17 +# ) + +# DIVs: n_iter * ( +# n_p * (n_p - 1) + +# n_p * board.n_obstacles + +# n_p * 2 +# ) + +# SQRTs: n_iter * ( +# 0.5 * (n_p*n_p - n_p) + +# n_p * (n_p - 1) * 2 + +# n_p * board.n_obstacles + +# n_p * 3 +# ) + +# EXPs: n_iter * ( +# n_p * (n_p - 1) + +# n_p * board.n_obstacles +# ) + +# total with EXP = 30: n_iter * ( 69 * n_p ** 2 + 32 * n_p + 55 * n_obstacles * n_p ) + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * 68 + 0.5 * (n_p * n_p - n_p) * 3 + n_p * + (n_p - 1) * 11 + n_p * n_obs * 10 + n_p * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * 4 + 0.5 * (n_p * n_p - n_p) * 2 + n_p * + (n_p - 1) * 22 + n_p * n_obs * 13 + n_p * 17)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) + n_p * n_obs + n_p * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (0.5 * (n_p * n_p - n_p) + n_p * + (n_p - 1) * 2 + n_p * n_obs + n_p * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) + n_p * n_obs)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_float_inlining_SoA_symmetry_ILP_2.py b/flopcounts/x86/variant_float_inlining_SoA_symmetry_ILP_2.py new file mode 100644 index 0000000..d598bca --- /dev/null +++ b/flopcounts/x86/variant_float_inlining_SoA_symmetry_ILP_2.py @@ -0,0 +1,70 @@ +# FLOPCOUNT (everything inside the t-loop). EXP kept as its own op (one real exp() per call). +# section costs: overhead 4 ADD 4 MULT (+ reductions 4*K = 8 ADD, K=2) | +# distance pair 3 ADD 2 MULT 1 SQRT | +# ped-ped j 11 ADD 22 MULT 2 SQRT 1 DIV 1 EXP | +# obstacle 10 ADD 13 MULT 1 SQRT 1 DIV 1 EXP | update 7 ADD 17 MULT 3 SQRT 2 DIV + +# ADDs: n_iter * ( +# n_p * 12 + +# 0.5 * (n_p*n_p - n_p) * 3 + +# n_p * (n_p - 1) * 11 + +# n_p * board.n_obstacles * 10 + +# n_p * 7 +# ) + +# MULTs: n_iter * ( +# n_p * 4 + +# 0.5 * (n_p*n_p - n_p) * 2 + +# n_p * (n_p - 1) * 22 + +# n_p * board.n_obstacles * 13 + +# n_p * 17 +# ) + +# DIVs: n_iter * ( +# n_p * (n_p - 1) + +# n_p * board.n_obstacles + +# n_p * 2 +# ) + +# SQRTs: n_iter * ( +# 0.5 * (n_p*n_p - n_p) + +# n_p * (n_p - 1) * 2 + +# n_p * board.n_obstacles + +# n_p * 3 +# ) + +# EXPs: n_iter * ( +# n_p * (n_p - 1) + +# n_p * board.n_obstacles +# ) + +# total with EXP = 30: n_iter * ( 69 * n_p ** 2 - 24 * n_p + 55 * n_obstacles * n_p ) + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * 12 + 0.5 * (n_p * n_p - n_p) * 3 + n_p * + (n_p - 1) * 11 + n_p * n_obs * 10 + n_p * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * 4 + 0.5 * (n_p * n_p - n_p) * 2 + n_p * + (n_p - 1) * 22 + n_p * n_obs * 13 + n_p * 17)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) + n_p * n_obs + n_p * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (0.5 * (n_p * n_p - n_p) + n_p * + (n_p - 1) * 2 + n_p * n_obs + n_p * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) + n_p * n_obs)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_float_inlining_SoA_symmetry_ILP_4.py b/flopcounts/x86/variant_float_inlining_SoA_symmetry_ILP_4.py new file mode 100644 index 0000000..dfefbb1 --- /dev/null +++ b/flopcounts/x86/variant_float_inlining_SoA_symmetry_ILP_4.py @@ -0,0 +1,70 @@ +# FLOPCOUNT (everything inside the t-loop). EXP kept as its own op (one real exp() per call). +# section costs: overhead 4 ADD 4 MULT (+ reductions 4*K = 16 ADD, K=4) | +# distance pair 3 ADD 2 MULT 1 SQRT | +# ped-ped j 11 ADD 22 MULT 2 SQRT 1 DIV 1 EXP | +# obstacle 10 ADD 13 MULT 1 SQRT 1 DIV 1 EXP | update 7 ADD 17 MULT 3 SQRT 2 DIV + +# ADDs: n_iter * ( +# n_p * 20 + +# 0.5 * (n_p*n_p - n_p) * 3 + +# n_p * (n_p - 1) * 11 + +# n_p * board.n_obstacles * 10 + +# n_p * 7 +# ) + +# MULTs: n_iter * ( +# n_p * 4 + +# 0.5 * (n_p*n_p - n_p) * 2 + +# n_p * (n_p - 1) * 22 + +# n_p * board.n_obstacles * 13 + +# n_p * 17 +# ) + +# DIVs: n_iter * ( +# n_p * (n_p - 1) + +# n_p * board.n_obstacles + +# n_p * 2 +# ) + +# SQRTs: n_iter * ( +# 0.5 * (n_p*n_p - n_p) + +# n_p * (n_p - 1) * 2 + +# n_p * board.n_obstacles + +# n_p * 3 +# ) + +# EXPs: n_iter * ( +# n_p * (n_p - 1) + +# n_p * board.n_obstacles +# ) + +# total with EXP = 30: n_iter * ( 69 * n_p ** 2 - 16 * n_p + 55 * n_obstacles * n_p ) + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * 20 + 0.5 * (n_p * n_p - n_p) * 3 + n_p * + (n_p - 1) * 11 + n_p * n_obs * 10 + n_p * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * 4 + 0.5 * (n_p * n_p - n_p) * 2 + n_p * + (n_p - 1) * 22 + n_p * n_obs * 13 + n_p * 17)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) + n_p * n_obs + n_p * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (0.5 * (n_p * n_p - n_p) + n_p * + (n_p - 1) * 2 + n_p * n_obs + n_p * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) + n_p * n_obs)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_float_inlining_SoA_symmetry_ILP_8.py b/flopcounts/x86/variant_float_inlining_SoA_symmetry_ILP_8.py new file mode 100644 index 0000000..d70ae4d --- /dev/null +++ b/flopcounts/x86/variant_float_inlining_SoA_symmetry_ILP_8.py @@ -0,0 +1,70 @@ +# FLOPCOUNT (everything inside the t-loop). EXP kept as its own op (one real exp() per call). +# section costs: overhead 4 ADD 4 MULT (+ reductions 4*K = 32 ADD, K=8) | +# distance pair 3 ADD 2 MULT 1 SQRT | +# ped-ped j 11 ADD 22 MULT 2 SQRT 1 DIV 1 EXP | +# obstacle 10 ADD 13 MULT 1 SQRT 1 DIV 1 EXP | update 7 ADD 17 MULT 3 SQRT 2 DIV + +# ADDs: n_iter * ( +# n_p * 36 + +# 0.5 * (n_p*n_p - n_p) * 3 + +# n_p * (n_p - 1) * 11 + +# n_p * board.n_obstacles * 10 + +# n_p * 7 +# ) + +# MULTs: n_iter * ( +# n_p * 4 + +# 0.5 * (n_p*n_p - n_p) * 2 + +# n_p * (n_p - 1) * 22 + +# n_p * board.n_obstacles * 13 + +# n_p * 17 +# ) + +# DIVs: n_iter * ( +# n_p * (n_p - 1) + +# n_p * board.n_obstacles + +# n_p * 2 +# ) + +# SQRTs: n_iter * ( +# 0.5 * (n_p*n_p - n_p) + +# n_p * (n_p - 1) * 2 + +# n_p * board.n_obstacles + +# n_p * 3 +# ) + +# EXPs: n_iter * ( +# n_p * (n_p - 1) + +# n_p * board.n_obstacles +# ) + +# total with EXP = 30: n_iter * ( 69 * n_p ** 2 + 55 * n_obstacles * n_p ) linear term cancels + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * 36 + 0.5 * (n_p * n_p - n_p) * 3 + n_p * + (n_p - 1) * 11 + n_p * n_obs * 10 + n_p * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * 4 + 0.5 * (n_p * n_p - n_p) * 2 + n_p * + (n_p - 1) * 22 + n_p * n_obs * 13 + n_p * 17)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) + n_p * n_obs + n_p * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (0.5 * (n_p * n_p - n_p) + n_p * + (n_p - 1) * 2 + n_p * n_obs + n_p * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) + n_p * n_obs)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_inlining_7.py b/flopcounts/x86/variant_inlining_7.py new file mode 100644 index 0000000..c6c5948 --- /dev/null +++ b/flopcounts/x86/variant_inlining_7.py @@ -0,0 +1,44 @@ +# ADDs: n_iter * n_p * 11 + +# n_iter * n_p * (n_p - 1) * 14 + +# n_iter * n_p * board.n_obstacles * 12 + +# MULTs: n_iter * n_p * 21 + +# n_iter * n_p * (n_p - 1) * 24 + +# n_iter * n_p * board.n_obstacles * 19 + +# DIVs: n_iter * n_p * 2 + +# n_iter * n_p * (n_p - 1) + +# n_iter * n_p * board.n_obstacles + +# SQRTs: n_iter * n_p * 3 + +# n_iter * n_p * (n_p - 1) * 3 + +# n_iter * n_p * board.n_obstacles + +# EXPs: n_iter * n_p * (n_p - 1) + +# n_iter * n_p * board.n_obstacles + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * n_p * (11 + (n_p - 1) * 14 + n_obs * 12)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * n_p * (21 + (n_p - 1) * 24 + n_obs * 19)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * n_p * (2 + (n_p - 1) + n_obs)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * n_p * (3 + (n_p - 1) * 3 + n_obs)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * n_p * ((n_p - 1) + n_obs)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_inlining_7_SoA.py b/flopcounts/x86/variant_inlining_7_SoA.py new file mode 100644 index 0000000..c6c5948 --- /dev/null +++ b/flopcounts/x86/variant_inlining_7_SoA.py @@ -0,0 +1,44 @@ +# ADDs: n_iter * n_p * 11 + +# n_iter * n_p * (n_p - 1) * 14 + +# n_iter * n_p * board.n_obstacles * 12 + +# MULTs: n_iter * n_p * 21 + +# n_iter * n_p * (n_p - 1) * 24 + +# n_iter * n_p * board.n_obstacles * 19 + +# DIVs: n_iter * n_p * 2 + +# n_iter * n_p * (n_p - 1) + +# n_iter * n_p * board.n_obstacles + +# SQRTs: n_iter * n_p * 3 + +# n_iter * n_p * (n_p - 1) * 3 + +# n_iter * n_p * board.n_obstacles + +# EXPs: n_iter * n_p * (n_p - 1) + +# n_iter * n_p * board.n_obstacles + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * n_p * (11 + (n_p - 1) * 14 + n_obs * 12)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * n_p * (21 + (n_p - 1) * 24 + n_obs * 19)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * n_p * (2 + (n_p - 1) + n_obs)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * n_p * (3 + (n_p - 1) * 3 + n_obs)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * n_p * ((n_p - 1) + n_obs)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_inlining_7_SoA_AVX2.py b/flopcounts/x86/variant_inlining_7_SoA_AVX2.py new file mode 100644 index 0000000..8036261 --- /dev/null +++ b/flopcounts/x86/variant_inlining_7_SoA_AVX2.py @@ -0,0 +1,41 @@ +# const int n_p_pad = (n_p + 3) & ~3; + +# flops per iteration (one pass of the outer time loop): +# ADDs: n_p * 12 + n_p * n_p_pad * 15 + n_p * board.n_obstacles * 12 + n_p * 7 +# MULTs: n_p * 4 + n_p * n_p_pad * 24 + n_p * board.n_obstacles * 19 + n_p * 16 +# DIVs: n_p * n_p_pad * 1 + n_p * board.n_obstacles + n_p * 2 +# SQRTs: n_p * n_p_pad * 3 + n_p * board.n_obstacles + n_p * 3 +# EXPs: n_p * n_p_pad * 1 + n_p * board.n_obstacles + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 3) & ~3 + return int(n_iter * + (n_p * 12 + n_p * n_p_pad * 15 + n_p * n_obs * 12 + n_p * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 3) & ~3 + return int(n_iter * + (n_p * 4 + n_p * n_p_pad * 24 + n_p * n_obs * 19 + n_p * 16)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 3) & ~3 + return int(n_iter * (n_p * n_p_pad * 1 + n_p * n_obs + n_p * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 3) & ~3 + return int(n_iter * (n_p * n_p_pad * 3 + n_p * n_obs + n_p * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 3) & ~3 + return int(n_iter * (n_p * n_p_pad * 1 + n_p * n_obs)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_inlining_7_SoA_AVX2_polyexp.py b/flopcounts/x86/variant_inlining_7_SoA_AVX2_polyexp.py new file mode 100644 index 0000000..d68dc11 --- /dev/null +++ b/flopcounts/x86/variant_inlining_7_SoA_AVX2_polyexp.py @@ -0,0 +1,41 @@ +# const int n_p_pad = (n_p + 3) & ~3; + +# flops per iteration (one pass of the outer time loop): +# ADDs: n_p * 12 + n_p * n_p_pad * 29 + n_p * board.n_obstacles * 12 + n_p * 7 +# MULTs: n_p * 4 + n_p * n_p_pad * 40 + n_p * board.n_obstacles * 19 + n_p * 16 +# DIVs: n_p * n_p_pad * 1 + n_p * board.n_obstacles + n_p * 2 +# SQRTs: n_p * n_p_pad * 3 + n_p * board.n_obstacles + n_p * 3 +# EXPs: n_p * board.n_obstacles + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 3) & ~3 + return int(n_iter * + (n_p * 12 + n_p * n_p_pad * 29 + n_p * n_obs * 12 + n_p * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 3) & ~3 + return int(n_iter * + (n_p * 4 + n_p * n_p_pad * 40 + n_p * n_obs * 19 + n_p * 16)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 3) & ~3 + return int(n_iter * (n_p * n_p_pad * 1 + n_p * n_obs + n_p * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 3) & ~3 + return int(n_iter * (n_p * n_p_pad * 3 + n_p * n_obs + n_p * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 3) & ~3 + return int(n_iter * (n_p * n_obs)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_inlining_7_symmetry_1.py b/flopcounts/x86/variant_inlining_7_symmetry_1.py new file mode 100644 index 0000000..cdafbef --- /dev/null +++ b/flopcounts/x86/variant_inlining_7_symmetry_1.py @@ -0,0 +1,27 @@ +# n_iter * [ n_p ** 2 * (12.5 ADD + 23 MULT + 1 DIV + 1 EXP + 2.5 SQRT) + n_p * (- 1.5 ADD + 0.5 SQRT - 2 MULT - 1 EXP + 1 DIV) + n_obstacles * n_p * (12 ADD + 19 MULT + 1 SQRT + 1 DIV + 1 EXP) ] + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 12.5 + n_p * (-1.5) + n_obs * n_p * 12)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 23 + n_p * (-2) + n_obs * n_p * 19)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 1 + n_p * 1 + n_obs * n_p * 1)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 2.5 + n_p * 0.5 + n_obs * n_p * 1)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 1 + n_p * (-1) + n_obs * n_p * 1)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_inlining_7_symmetry_2.py b/flopcounts/x86/variant_inlining_7_symmetry_2.py new file mode 100644 index 0000000..cdafbef --- /dev/null +++ b/flopcounts/x86/variant_inlining_7_symmetry_2.py @@ -0,0 +1,27 @@ +# n_iter * [ n_p ** 2 * (12.5 ADD + 23 MULT + 1 DIV + 1 EXP + 2.5 SQRT) + n_p * (- 1.5 ADD + 0.5 SQRT - 2 MULT - 1 EXP + 1 DIV) + n_obstacles * n_p * (12 ADD + 19 MULT + 1 SQRT + 1 DIV + 1 EXP) ] + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 12.5 + n_p * (-1.5) + n_obs * n_p * 12)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 23 + n_p * (-2) + n_obs * n_p * 19)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 1 + n_p * 1 + n_obs * n_p * 1)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 2.5 + n_p * 0.5 + n_obs * n_p * 1)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 1 + n_p * (-1) + n_obs * n_p * 1)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_inlining_7_symmetry_2_ilp_1.py b/flopcounts/x86/variant_inlining_7_symmetry_2_ilp_1.py new file mode 100644 index 0000000..9eb3c8e --- /dev/null +++ b/flopcounts/x86/variant_inlining_7_symmetry_2_ilp_1.py @@ -0,0 +1,27 @@ +# n_iter * [ n_p ** 2 * (12.5 A + 2.5 S + 23 M + 1 D + 1 E) + n_p * (6.5 A + 0.5 S - 2 M + 1 D - 1 E) + n_obstacles * n_p * (12 A + 19 M + 1 S + 1 D + 1 E)] + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 12.5 + n_p * 6.5 + n_obs * n_p * 12)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 23 + n_p * (-2) + n_obs * n_p * 19)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 1 + n_p * 1 + n_obs * n_p * 1)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 2.5 + n_p * 0.5 + n_obs * n_p * 1)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 1 + n_p * (-1) + n_obs * n_p * 1)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_inlining_7_symmetry_2_ilp_2.py b/flopcounts/x86/variant_inlining_7_symmetry_2_ilp_2.py new file mode 100644 index 0000000..e08a559 --- /dev/null +++ b/flopcounts/x86/variant_inlining_7_symmetry_2_ilp_2.py @@ -0,0 +1,27 @@ +# n_iter * [ n_p ** 2 * (12.5 A + 23 M + 2.5 S + 1 D + 1 E) + n_p * (14.5 A - 2 M + 0.5 S + 1 D - 1 E) + n_obstacles * n_p * (12 A + 19 M + 1 S + 1 D + 1 E) ] + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 12.5 + n_p * 14.5 + n_obs * n_p * 12)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 23 + n_p * (-2) + n_obs * n_p * 19)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 1 + n_p * 1 + n_obs * n_p * 1)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 2.5 + n_p * 0.5 + n_obs * n_p * 1)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p**2 * 1 + n_p * (-1) + n_obs * n_p * 1)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_inlining_8.py b/flopcounts/x86/variant_inlining_8.py new file mode 100644 index 0000000..9955d52 --- /dev/null +++ b/flopcounts/x86/variant_inlining_8.py @@ -0,0 +1,44 @@ +# ADDs: n_iter * n_p * 11 + +# n_iter * n_p * (n_p - 1) * 14 + +# n_iter * n_p * board.n_obstacles * 10 + +# MULTs: n_iter * n_p * 21 + +# n_iter * n_p * (n_p - 1) * 24 + +# n_iter * n_p * board.n_obstacles * 13 + +# DIVs: n_iter * n_p * 2 + +# n_iter * n_p * (n_p - 1) + +# n_iter * n_p * board.n_obstacles + +# SQRTs: n_iter * n_p * 3 + +# n_iter * n_p * (n_p - 1) * 3 + +# n_iter * n_p * board.n_obstacles + +# EXPs: n_iter * n_p * (n_p - 1) + +# n_iter * n_p * board.n_obstacles + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * n_p * (11 + (n_p - 1) * 14 + n_obs * 10)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * n_p * (21 + (n_p - 1) * 24 + n_obs * 13)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * n_p * (2 + (n_p - 1) + n_obs)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * n_p * (3 + (n_p - 1) * 3 + n_obs)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * n_p * ((n_p - 1) + n_obs)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt.py b/flopcounts/x86/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt.py new file mode 100644 index 0000000..c680193 --- /dev/null +++ b/flopcounts/x86/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt.py @@ -0,0 +1,49 @@ +# const int n_p_pad = (n_p + 7) & ~7; + +# ADDs: n_iter * n_p * 33 + +# n_iter * n_p * (n_p_pad / 8) * 232 + +# n_iter * n_p * board.n_obstacles * 10 + +# MULTs: n_iter * n_p * 40 + +# n_iter * n_p * (n_p_pad / 8) * 320 + +# n_iter * n_p * board.n_obstacles * 13 + +# DIVs: n_iter * n_p * (n_p_pad / 8) * 8 + +# n_iter * n_p * board.n_obstacles + +# SQRTs: n_iter * n_p + +# n_iter * n_p * (n_p_pad / 8) * 24 + +# n_iter * n_p * board.n_obstacles + +# EXPs: n_iter * n_p * board.n_obstacles + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * n_p * (33 + (n_p_pad // 8) * 232 + n_obs * 10)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * n_p * (40 + (n_p_pad // 8) * 320 + n_obs * 13)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * n_p * ((n_p_pad // 8) * 8 + n_obs)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * n_p * (1 + (n_p_pad // 8) * 24 + n_obs)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * n_p * n_obs) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr.py b/flopcounts/x86/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr.py new file mode 100644 index 0000000..c680193 --- /dev/null +++ b/flopcounts/x86/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr.py @@ -0,0 +1,49 @@ +# const int n_p_pad = (n_p + 7) & ~7; + +# ADDs: n_iter * n_p * 33 + +# n_iter * n_p * (n_p_pad / 8) * 232 + +# n_iter * n_p * board.n_obstacles * 10 + +# MULTs: n_iter * n_p * 40 + +# n_iter * n_p * (n_p_pad / 8) * 320 + +# n_iter * n_p * board.n_obstacles * 13 + +# DIVs: n_iter * n_p * (n_p_pad / 8) * 8 + +# n_iter * n_p * board.n_obstacles + +# SQRTs: n_iter * n_p + +# n_iter * n_p * (n_p_pad / 8) * 24 + +# n_iter * n_p * board.n_obstacles + +# EXPs: n_iter * n_p * board.n_obstacles + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * n_p * (33 + (n_p_pad // 8) * 232 + n_obs * 10)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * n_p * (40 + (n_p_pad // 8) * 320 + n_obs * 13)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * n_p * ((n_p_pad // 8) * 8 + n_obs)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * n_p * (1 + (n_p_pad // 8) * 24 + n_obs)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * n_p * n_obs) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_inlining_8_SoA_AVX512_polyexp_moreavx.py b/flopcounts/x86/variant_inlining_8_SoA_AVX512_polyexp_moreavx.py new file mode 100644 index 0000000..c0d4372 --- /dev/null +++ b/flopcounts/x86/variant_inlining_8_SoA_AVX512_polyexp_moreavx.py @@ -0,0 +1,57 @@ +# const int n_p_pad = (n_p + 7) & ~7; + +# ADDs: n_iter * n_p * 20 + +# n_iter * n_p * (n_p_pad / 8) * 232 + +# n_iter * n_p * board.n_obstacles * 10 + +# n_iter * (n_p_pad / 8) * 56 + +# MULTs: n_iter * n_p * 4 + +# n_iter * n_p * (n_p_pad / 8) * 320 + +# n_iter * n_p * board.n_obstacles * 13 + +# n_iter * (n_p_pad / 8) * 120 + +# DIVs: n_iter * n_p * (n_p_pad / 8) * 8 + +# n_iter * n_p * board.n_obstacles + +# n_iter * (n_p_pad / 8) * 16 + +# SQRTs: n_iter * n_p * (n_p_pad / 8) * 24 + +# n_iter * n_p * board.n_obstacles + +# n_iter * (n_p_pad / 8) * 24 + +# EXPs: n_iter * n_p * board.n_obstacles + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * + (n_p * 20 + n_p * (n_p_pad // 8) * 232 + n_p * n_obs * 10 + + (n_p_pad // 8) * 56)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * (n_p * 4 + n_p * (n_p_pad // 8) * 320 + n_p * n_obs * 13 + + (n_p_pad // 8) * 120)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * (n_p * (n_p_pad // 8) * 8 + n_p * n_obs + + (n_p_pad // 8) * 16)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * (n_p * (n_p_pad // 8) * 24 + n_p * n_obs + + (n_p_pad // 8) * 24)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 7) & ~7 + return int(n_iter * n_p * n_obs) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2.py b/flopcounts/x86/variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2.py new file mode 100644 index 0000000..d1be6bb --- /dev/null +++ b/flopcounts/x86/variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2.py @@ -0,0 +1,58 @@ +# const int n_p_pad = (n_p + 15) & ~15; + +# ADDs: n_iter * n_p * 36 + +# n_iter * n_p * (n_p_pad / 16) * 464 + +# n_iter * n_p * board.n_obstacles * 10 + +# n_iter * (n_p_pad / 8) * 56 + +# MULTs: n_iter * n_p * 4 + +# n_iter * n_p * (n_p_pad / 16) * 640 + +# n_iter * n_p * board.n_obstacles * 13 + +# n_iter * (n_p_pad / 8) * 120 + +# DIVs: n_iter * n_p * (n_p_pad / 16) * 16 + +# n_iter * n_p * board.n_obstacles + +# n_iter * (n_p_pad / 8) * 16 + +# SQRTs: n_iter * n_p * (n_p_pad / 16) * 48 + +# n_iter * n_p * board.n_obstacles + +# n_iter * (n_p_pad / 8) * 24 + +# EXPs: n_iter * n_p * board.n_obstacles + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int(n_iter * + (n_p * 36 + n_p * (n_p_pad // 16) * 464 + n_p * n_obs * 10 + + (n_p_pad // 8) * 56)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int(n_iter * + (n_p * 4 + n_p * (n_p_pad // 16) * 640 + n_p * n_obs * 13 + + (n_p_pad // 8) * 120)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int(n_iter * (n_p * (n_p_pad // 16) * 16 + n_p * n_obs + + (n_p_pad // 8) * 16)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int(n_iter * (n_p * (n_p_pad // 16) * 48 + n_p * n_obs + + (n_p_pad // 8) * 24)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + n_p_pad = (n_p + 15) & ~15 + return int(n_iter * n_p * n_obs) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/flopcounts/x86/variant_lut_exp.py b/flopcounts/x86/variant_lut_exp.py new file mode 100644 index 0000000..c52adea --- /dev/null +++ b/flopcounts/x86/variant_lut_exp.py @@ -0,0 +1,58 @@ +# ADDs: n_iter * ( +# n_p * 4 + +# n_p * (n_p - 1) * 14 + +# n_p * board.n_obstacles * 12 + +# n_p * 7 +# ) + +# MULTs: n_iter * ( +# n_p * 4 + +# n_p * (n_p - 1) * 23 + +# n_p * board.n_obstacles * 18 + +# n_p * 16 +# ) + +# DIVs: n_iter * ( +# n_p * (n_p - 1) + +# n_p * board.n_obstacles + +# n_p * 2 +# ) + +# SQRTs: n_iter * ( +# n_p * (n_p - 1) * 4 + +# n_p * board.n_obstacles * 2 + +# n_p * 3 +# ) + +# EXPs (fast_exp, LUT): n_iter * ( +# n_p * (n_p - 1) + +# n_p * board.n_obstacles +# ) + + +def adds(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * 4 + n_p * + (n_p - 1) * 14 + n_p * n_obs * 12 + n_p * 7)) + + +def mults(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * 4 + n_p * + (n_p - 1) * 23 + n_p * n_obs * 18 + n_p * 16)) + + +def divs(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) + n_p * n_obs + n_p * 2)) + + +def sqrts(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) * 4 + n_p * n_obs * 2 + n_p * 3)) + + +def exps(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return int(n_iter * (n_p * (n_p - 1) + n_p * n_obs)) + + +def total(n_iter: int, n_p: int, n_obs: int = 2) -> int: + return adds(n_iter, n_p, n_obs) + mults(n_iter, n_p, n_obs) + divs( + n_iter, n_p, n_obs) + sqrts(n_iter, n_p, + n_obs) + exps(n_iter, n_p, n_obs) * 30 diff --git a/measurements/variant_float_inlining_SoA_AVX2_polyexp/x86/1.log b/measurements/variant_float_inlining_SoA_AVX2_polyexp/x86/1.log index 696cf09..6062c1a 100644 --- a/measurements/variant_float_inlining_SoA_AVX2_polyexp/x86/1.log +++ b/measurements/variant_float_inlining_SoA_AVX2_polyexp/x86/1.log @@ -1,58 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX2_polyexp.cpp -o main_float_inlining_SoA_AVX2_polyexp -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX2_polyexp_expfix.cpp -o main_float_inlining_SoA_AVX2_polyexp_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 3256 bytes I(n): 56.42 flops/byte W(n): 36740000.00 flops -T(n): 4538634.50 cycles -P(n): 8.09 flops/cycle +T(n): 5860437.00 cycles +P(n): 6.27 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 6456 bytes I(n): 112.67 flops/byte W(n): 145480000.00 flops -T(n): 14836382.00 cycles -P(n): 9.81 flops/cycle +T(n): 19736818.00 cycles +P(n): 7.37 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 12856 bytes I(n): 225.17 flops/byte W(n): 578960000.00 flops -T(n): 52866688.00 cycles -P(n): 10.95 flops/cycle +T(n): 71295200.00 cycles +P(n): 8.12 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 32056 bytes I(n): 562.67 flops/byte W(n): 3607399936.00 flops -T(n): 314877088.00 cycles -P(n): 11.46 flops/cycle +T(n): 434200736.00 cycles +P(n): 8.31 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 64056 bytes I(n): 1125.17 flops/byte W(n): 14414799872.00 flops -T(n): 1228216448.00 cycles -P(n): 11.74 flops/cycle +T(n): 1690932352.00 cycles +P(n): 8.52 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 128056 bytes I(n): 2250.17 flops/byte W(n): 57629601792.00 flops -T(n): 4888108544.00 cycles -P(n): 11.79 flops/cycle +T(n): 6726832128.00 cycles +P(n): 8.57 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800369920.00 flops Q(n) per iteration: 320056 bytes I(n): 5625.17 flops/byte W(n): 360073986048.00 flops -T(n): 30235383808.00 cycles -P(n): 11.91 flops/cycle +T(n): 41595662336.00 cycles +P(n): 8.66 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 166348996608.00 cycles +P(n): 3.49 flops/cycle diff --git a/measurements/variant_float_inlining_SoA_AVX2_polyexp/x86/2.log b/measurements/variant_float_inlining_SoA_AVX2_polyexp/x86/2.log index 13f9f97..652e0a6 100644 --- a/measurements/variant_float_inlining_SoA_AVX2_polyexp/x86/2.log +++ b/measurements/variant_float_inlining_SoA_AVX2_polyexp/x86/2.log @@ -1,66 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX2_polyexp.cpp -o main_float_inlining_SoA_AVX2_polyexp -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX2_polyexp_expfix.cpp -o main_float_inlining_SoA_AVX2_polyexp_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 3256 bytes I(n): 56.42 flops/byte W(n): 36740000.00 flops -T(n): 4573347.00 cycles -P(n): 8.03 flops/cycle +T(n): 5885449.00 cycles +P(n): 6.24 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 6456 bytes I(n): 112.67 flops/byte W(n): 145480000.00 flops -T(n): 14972852.00 cycles -P(n): 9.72 flops/cycle +T(n): 19775262.00 cycles +P(n): 7.36 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 12856 bytes I(n): 225.17 flops/byte W(n): 578960000.00 flops -T(n): 53246808.00 cycles -P(n): 10.87 flops/cycle +T(n): 71759640.00 cycles +P(n): 8.07 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 32056 bytes I(n): 562.67 flops/byte W(n): 3607399936.00 flops -T(n): 317441728.00 cycles -P(n): 11.36 flops/cycle +T(n): 442073856.00 cycles +P(n): 8.16 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 64056 bytes I(n): 1125.17 flops/byte W(n): 14414799872.00 flops -T(n): 1237166592.00 cycles -P(n): 11.65 flops/cycle +T(n): 1698162944.00 cycles +P(n): 8.49 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 128056 bytes I(n): 2250.17 flops/byte W(n): 57629601792.00 flops -T(n): 4899325440.00 cycles -P(n): 11.76 flops/cycle +T(n): 6719285248.00 cycles +P(n): 8.58 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800369920.00 flops Q(n) per iteration: 320056 bytes I(n): 5625.17 flops/byte W(n): 360073986048.00 flops -T(n): 30502610944.00 cycles -P(n): 11.80 flops/cycle +T(n): 41795964928.00 cycles +P(n): 8.62 flops/cycle === N_P=10000 N_ITER=200 === W(n) per iteration: 2905772800.00 flops Q(n) per iteration: 640056 bytes I(n): 4539.87 flops/byte W(n): 581154570240.00 flops -T(n): 122120396800.00 cycles -P(n): 4.76 flops/cycle +T(n): 166340608000.00 cycles +P(n): 3.49 flops/cycle diff --git a/measurements/variant_float_inlining_SoA_AVX2_polyexp/x86/3.log b/measurements/variant_float_inlining_SoA_AVX2_polyexp/x86/3.log new file mode 100644 index 0000000..543ba85 --- /dev/null +++ b/measurements/variant_float_inlining_SoA_AVX2_polyexp/x86/3.log @@ -0,0 +1,64 @@ +=== N_P=50 N_ITER=200 === +W(n) per iteration: 183700.00 flops +Q(n) per iteration: 3256 bytes +I(n): 56.42 flops/byte +W(n): 36740000.00 flops +T(n): 5839795.00 cycles +P(n): 6.29 flops/cycle + +=== N_P=100 N_ITER=200 === +W(n) per iteration: 727400.00 flops +Q(n) per iteration: 6456 bytes +I(n): 112.67 flops/byte +W(n): 145480000.00 flops +T(n): 19706848.00 cycles +P(n): 7.38 flops/cycle + +=== N_P=200 N_ITER=200 === +W(n) per iteration: 2894800.00 flops +Q(n) per iteration: 12856 bytes +I(n): 225.17 flops/byte +W(n): 578960000.00 flops +T(n): 71913632.00 cycles +P(n): 8.05 flops/cycle + +=== N_P=500 N_ITER=200 === +W(n) per iteration: 18037000.00 flops +Q(n) per iteration: 32056 bytes +I(n): 562.67 flops/byte +W(n): 3607399936.00 flops +T(n): 431199296.00 cycles +P(n): 8.37 flops/cycle + +=== N_P=1000 N_ITER=200 === +W(n) per iteration: 72074000.00 flops +Q(n) per iteration: 64056 bytes +I(n): 1125.17 flops/byte +W(n): 14414799872.00 flops +T(n): 1710698496.00 cycles +P(n): 8.43 flops/cycle + +=== N_P=2000 N_ITER=200 === +W(n) per iteration: 288148000.00 flops +Q(n) per iteration: 128056 bytes +I(n): 2250.17 flops/byte +W(n): 57629601792.00 flops +T(n): 6773665792.00 cycles +P(n): 8.51 flops/cycle + +=== N_P=5000 N_ITER=200 === +W(n) per iteration: 1800369920.00 flops +Q(n) per iteration: 320056 bytes +I(n): 5625.17 flops/byte +W(n): 360073986048.00 flops +T(n): 43346759680.00 cycles +P(n): 8.31 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 169504800768.00 cycles +P(n): 3.43 flops/cycle + diff --git a/measurements/variant_float_inlining_SoA_AVX2_polyexp_rsqrt/x86/1.log b/measurements/variant_float_inlining_SoA_AVX2_polyexp_rsqrt/x86/1.log index a34df7a..7e95d51 100644 --- a/measurements/variant_float_inlining_SoA_AVX2_polyexp_rsqrt/x86/1.log +++ b/measurements/variant_float_inlining_SoA_AVX2_polyexp_rsqrt/x86/1.log @@ -1,58 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX2_polyexp_rsqrt.cpp -o main_float_inlining_SoA_AVX2_polyexp_rsqrt -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_expfix.cpp -o main_float_inlining_SoA_AVX2_polyexp_rsqrt_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 3256 bytes I(n): 56.42 flops/byte W(n): 36740000.00 flops -T(n): 3922583.00 cycles -P(n): 9.37 flops/cycle +T(n): 5075402.00 cycles +P(n): 7.24 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 6456 bytes I(n): 112.67 flops/byte W(n): 145480000.00 flops -T(n): 12656640.00 cycles -P(n): 11.49 flops/cycle +T(n): 16874942.00 cycles +P(n): 8.62 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 12856 bytes I(n): 225.17 flops/byte W(n): 578960000.00 flops -T(n): 44724200.00 cycles -P(n): 12.95 flops/cycle +T(n): 60586048.00 cycles +P(n): 9.56 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 32056 bytes I(n): 562.67 flops/byte W(n): 3607399936.00 flops -T(n): 264998976.00 cycles -P(n): 13.61 flops/cycle +T(n): 363991840.00 cycles +P(n): 9.91 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 64056 bytes I(n): 1125.17 flops/byte W(n): 14414799872.00 flops -T(n): 1051923712.00 cycles -P(n): 13.70 flops/cycle +T(n): 1424352768.00 cycles +P(n): 10.12 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 128056 bytes I(n): 2250.17 flops/byte W(n): 57629601792.00 flops -T(n): 4077504256.00 cycles -P(n): 14.13 flops/cycle +T(n): 5638619648.00 cycles +P(n): 10.22 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800369920.00 flops Q(n) per iteration: 320056 bytes I(n): 5625.17 flops/byte W(n): 360073986048.00 flops -T(n): 25317951488.00 cycles -P(n): 14.22 flops/cycle +T(n): 35081228288.00 cycles +P(n): 10.26 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 140734889984.00 cycles +P(n): 4.13 flops/cycle diff --git a/measurements/variant_float_inlining_SoA_AVX2_polyexp_rsqrt/x86/2.log b/measurements/variant_float_inlining_SoA_AVX2_polyexp_rsqrt/x86/2.log index 67fb138..322109b 100644 --- a/measurements/variant_float_inlining_SoA_AVX2_polyexp_rsqrt/x86/2.log +++ b/measurements/variant_float_inlining_SoA_AVX2_polyexp_rsqrt/x86/2.log @@ -1,66 +1,64 @@ -rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX2_polyexp_rsqrt.cpp -o main_float_inlining_SoA_AVX2_polyexp_rsqrt -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 3256 bytes I(n): 56.42 flops/byte W(n): 36740000.00 flops -T(n): 3968185.50 cycles -P(n): 9.26 flops/cycle +T(n): 5095124.00 cycles +P(n): 7.21 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 6456 bytes I(n): 112.67 flops/byte W(n): 145480000.00 flops -T(n): 12830122.00 cycles -P(n): 11.34 flops/cycle +T(n): 16958378.00 cycles +P(n): 8.58 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 12856 bytes I(n): 225.17 flops/byte W(n): 578960000.00 flops -T(n): 45279400.00 cycles -P(n): 12.79 flops/cycle +T(n): 60894740.00 cycles +P(n): 9.51 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 32056 bytes I(n): 562.67 flops/byte W(n): 3607399936.00 flops -T(n): 268426256.00 cycles -P(n): 13.44 flops/cycle +T(n): 364922464.00 cycles +P(n): 9.89 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 64056 bytes I(n): 1125.17 flops/byte W(n): 14414799872.00 flops -T(n): 1064596800.00 cycles -P(n): 13.54 flops/cycle +T(n): 1432131456.00 cycles +P(n): 10.07 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 128056 bytes I(n): 2250.17 flops/byte W(n): 57629601792.00 flops -T(n): 4126754304.00 cycles -P(n): 13.96 flops/cycle +T(n): 5669585408.00 cycles +P(n): 10.16 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800369920.00 flops Q(n) per iteration: 320056 bytes I(n): 5625.17 flops/byte W(n): 360073986048.00 flops -T(n): 25623275520.00 cycles -P(n): 14.05 flops/cycle +T(n): 35706060800.00 cycles +P(n): 10.08 flops/cycle === N_P=10000 N_ITER=200 === W(n) per iteration: 2905772800.00 flops Q(n) per iteration: 640056 bytes I(n): 4539.87 flops/byte W(n): 581154570240.00 flops -T(n): 102223626240.00 cycles -P(n): 5.69 flops/cycle +T(n): 143150546944.00 cycles +P(n): 4.06 flops/cycle diff --git a/measurements/variant_float_inlining_SoA_AVX2_polyexp_rsqrt/x86/3.log b/measurements/variant_float_inlining_SoA_AVX2_polyexp_rsqrt/x86/3.log new file mode 100644 index 0000000..a1c9040 --- /dev/null +++ b/measurements/variant_float_inlining_SoA_AVX2_polyexp_rsqrt/x86/3.log @@ -0,0 +1,64 @@ +=== N_P=50 N_ITER=200 === +W(n) per iteration: 183700.00 flops +Q(n) per iteration: 3256 bytes +I(n): 56.42 flops/byte +W(n): 36740000.00 flops +T(n): 5107488.00 cycles +P(n): 7.19 flops/cycle + +=== N_P=100 N_ITER=200 === +W(n) per iteration: 727400.00 flops +Q(n) per iteration: 6456 bytes +I(n): 112.67 flops/byte +W(n): 145480000.00 flops +T(n): 16972588.00 cycles +P(n): 8.57 flops/cycle + +=== N_P=200 N_ITER=200 === +W(n) per iteration: 2894800.00 flops +Q(n) per iteration: 12856 bytes +I(n): 225.17 flops/byte +W(n): 578960000.00 flops +T(n): 61120552.00 cycles +P(n): 9.47 flops/cycle + +=== N_P=500 N_ITER=200 === +W(n) per iteration: 18037000.00 flops +Q(n) per iteration: 32056 bytes +I(n): 562.67 flops/byte +W(n): 3607399936.00 flops +T(n): 375650720.00 cycles +P(n): 9.60 flops/cycle + +=== N_P=1000 N_ITER=200 === +W(n) per iteration: 72074000.00 flops +Q(n) per iteration: 64056 bytes +I(n): 1125.17 flops/byte +W(n): 14414799872.00 flops +T(n): 1444334464.00 cycles +P(n): 9.98 flops/cycle + +=== N_P=2000 N_ITER=200 === +W(n) per iteration: 288148000.00 flops +Q(n) per iteration: 128056 bytes +I(n): 2250.17 flops/byte +W(n): 57629601792.00 flops +T(n): 5717088768.00 cycles +P(n): 10.08 flops/cycle + +=== N_P=5000 N_ITER=200 === +W(n) per iteration: 1800369920.00 flops +Q(n) per iteration: 320056 bytes +I(n): 5625.17 flops/byte +W(n): 360073986048.00 flops +T(n): 36025249792.00 cycles +P(n): 10.00 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 143378251776.00 cycles +P(n): 4.05 flops/cycle + diff --git a/measurements/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt/x86/1.log b/measurements/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt/x86/1.log index 6fc604a..eab143b 100644 --- a/measurements/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt/x86/1.log +++ b/measurements/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt/x86/1.log @@ -1,58 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt.cpp -o main_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt_expfix.cpp -o main_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 3256 bytes I(n): 56.42 flops/byte W(n): 36740000.00 flops -T(n): 3857942.00 cycles -P(n): 9.52 flops/cycle +T(n): 4870774.50 cycles +P(n): 7.54 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 6456 bytes I(n): 112.67 flops/byte W(n): 145480000.00 flops -T(n): 11939004.00 cycles -P(n): 12.19 flops/cycle +T(n): 15640118.00 cycles +P(n): 9.30 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 12856 bytes I(n): 225.17 flops/byte W(n): 578960000.00 flops -T(n): 41343432.00 cycles -P(n): 14.00 flops/cycle +T(n): 55310808.00 cycles +P(n): 10.47 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 32056 bytes I(n): 562.67 flops/byte W(n): 3607399936.00 flops -T(n): 242607552.00 cycles -P(n): 14.87 flops/cycle +T(n): 329563872.00 cycles +P(n): 10.95 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 64056 bytes I(n): 1125.17 flops/byte W(n): 14414799872.00 flops -T(n): 939774144.00 cycles -P(n): 15.34 flops/cycle +T(n): 1283268352.00 cycles +P(n): 11.23 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 128056 bytes I(n): 2250.17 flops/byte W(n): 57629601792.00 flops -T(n): 3710422272.00 cycles -P(n): 15.53 flops/cycle +T(n): 5083250688.00 cycles +P(n): 11.34 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800369920.00 flops Q(n) per iteration: 320056 bytes I(n): 5625.17 flops/byte W(n): 360073986048.00 flops -T(n): 23019415552.00 cycles -P(n): 15.64 flops/cycle +T(n): 31586570240.00 cycles +P(n): 11.40 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 126882955264.00 cycles +P(n): 4.58 flops/cycle diff --git a/measurements/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt/x86/2.log b/measurements/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt/x86/2.log index c4e45b2..e4dcd7a 100644 --- a/measurements/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt/x86/2.log +++ b/measurements/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt/x86/2.log @@ -1,66 +1,64 @@ -rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt.cpp -o main_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 3256 bytes I(n): 56.42 flops/byte W(n): 36740000.00 flops -T(n): 3896576.25 cycles -P(n): 9.43 flops/cycle +T(n): 4872185.50 cycles +P(n): 7.54 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 6456 bytes I(n): 112.67 flops/byte W(n): 145480000.00 flops -T(n): 12081705.00 cycles -P(n): 12.04 flops/cycle +T(n): 15664138.00 cycles +P(n): 9.29 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 12856 bytes I(n): 225.17 flops/byte W(n): 578960000.00 flops -T(n): 41848524.00 cycles -P(n): 13.83 flops/cycle +T(n): 55368740.00 cycles +P(n): 10.46 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 32056 bytes I(n): 562.67 flops/byte W(n): 3607399936.00 flops -T(n): 245348896.00 cycles -P(n): 14.70 flops/cycle +T(n): 329987008.00 cycles +P(n): 10.93 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 64056 bytes I(n): 1125.17 flops/byte W(n): 14414799872.00 flops -T(n): 950120256.00 cycles -P(n): 15.17 flops/cycle +T(n): 1293044736.00 cycles +P(n): 11.15 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 128056 bytes I(n): 2250.17 flops/byte W(n): 57629601792.00 flops -T(n): 3760375296.00 cycles -P(n): 15.33 flops/cycle +T(n): 5130688512.00 cycles +P(n): 11.23 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800369920.00 flops Q(n) per iteration: 320056 bytes I(n): 5625.17 flops/byte W(n): 360073986048.00 flops -T(n): 23338608640.00 cycles -P(n): 15.43 flops/cycle +T(n): 32060348416.00 cycles +P(n): 11.23 flops/cycle === N_P=10000 N_ITER=200 === W(n) per iteration: 2905772800.00 flops Q(n) per iteration: 640056 bytes I(n): 4539.87 flops/byte W(n): 581154570240.00 flops -T(n): 93044531200.00 cycles -P(n): 6.25 flops/cycle +T(n): 129057972224.00 cycles +P(n): 4.50 flops/cycle diff --git a/measurements/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt/x86/3.log b/measurements/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt/x86/3.log new file mode 100644 index 0000000..da0c24a --- /dev/null +++ b/measurements/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt/x86/3.log @@ -0,0 +1,64 @@ +=== N_P=50 N_ITER=200 === +W(n) per iteration: 183700.00 flops +Q(n) per iteration: 3256 bytes +I(n): 56.42 flops/byte +W(n): 36740000.00 flops +T(n): 4901788.00 cycles +P(n): 7.50 flops/cycle + +=== N_P=100 N_ITER=200 === +W(n) per iteration: 727400.00 flops +Q(n) per iteration: 6456 bytes +I(n): 112.67 flops/byte +W(n): 145480000.00 flops +T(n): 15669965.00 cycles +P(n): 9.28 flops/cycle + +=== N_P=200 N_ITER=200 === +W(n) per iteration: 2894800.00 flops +Q(n) per iteration: 12856 bytes +I(n): 225.17 flops/byte +W(n): 578960000.00 flops +T(n): 55911480.00 cycles +P(n): 10.35 flops/cycle + +=== N_P=500 N_ITER=200 === +W(n) per iteration: 18037000.00 flops +Q(n) per iteration: 32056 bytes +I(n): 562.67 flops/byte +W(n): 3607399936.00 flops +T(n): 338225088.00 cycles +P(n): 10.67 flops/cycle + +=== N_P=1000 N_ITER=200 === +W(n) per iteration: 72074000.00 flops +Q(n) per iteration: 64056 bytes +I(n): 1125.17 flops/byte +W(n): 14414799872.00 flops +T(n): 1302161408.00 cycles +P(n): 11.07 flops/cycle + +=== N_P=2000 N_ITER=200 === +W(n) per iteration: 288148000.00 flops +Q(n) per iteration: 128056 bytes +I(n): 2250.17 flops/byte +W(n): 57629601792.00 flops +T(n): 5189515776.00 cycles +P(n): 11.11 flops/cycle + +=== N_P=5000 N_ITER=200 === +W(n) per iteration: 1800369920.00 flops +Q(n) per iteration: 320056 bytes +I(n): 5625.17 flops/byte +W(n): 360073986048.00 flops +T(n): 32577761280.00 cycles +P(n): 11.05 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 129035010048.00 cycles +P(n): 4.50 flops/cycle + diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp/x86/1.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp/x86/1.log index 1d8658f..533d3a6 100644 --- a/measurements/variant_float_inlining_SoA_AVX512_polyexp/x86/1.log +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp/x86/1.log @@ -1,58 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp.cpp -o main_float_inlining_SoA_AVX512_polyexp -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 3256 bytes I(n): 56.42 flops/byte W(n): 36740000.00 flops -T(n): 3952082.50 cycles -P(n): 9.30 flops/cycle +T(n): 4618692.00 cycles +P(n): 7.95 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 6456 bytes I(n): 112.67 flops/byte W(n): 145480000.00 flops -T(n): 11806225.00 cycles -P(n): 12.32 flops/cycle +T(n): 14020708.00 cycles +P(n): 10.38 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 12856 bytes I(n): 225.17 flops/byte W(n): 578960000.00 flops -T(n): 39147728.00 cycles -P(n): 14.79 flops/cycle +T(n): 47426524.00 cycles +P(n): 12.21 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 32056 bytes I(n): 562.67 flops/byte W(n): 3607399936.00 flops -T(n): 220870336.00 cycles -P(n): 16.33 flops/cycle +T(n): 271672832.00 cycles +P(n): 13.28 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 64056 bytes I(n): 1125.17 flops/byte W(n): 14414799872.00 flops -T(n): 843467072.00 cycles -P(n): 17.09 flops/cycle +T(n): 1041892096.00 cycles +P(n): 13.84 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 128056 bytes I(n): 2250.17 flops/byte W(n): 57629601792.00 flops -T(n): 3297570560.00 cycles -P(n): 17.48 flops/cycle +T(n): 4086357760.00 cycles +P(n): 14.10 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800369920.00 flops Q(n) per iteration: 320056 bytes I(n): 5625.17 flops/byte W(n): 360073986048.00 flops -T(n): 20527921152.00 cycles -P(n): 17.54 flops/cycle +T(n): 25345890304.00 cycles +P(n): 14.21 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 100797374464.00 cycles +P(n): 5.77 flops/cycle diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp/x86/2.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp/x86/2.log index 5f8aac9..1d0ae94 100644 --- a/measurements/variant_float_inlining_SoA_AVX512_polyexp/x86/2.log +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp/x86/2.log @@ -1,66 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp.cpp -o main_float_inlining_SoA_AVX512_polyexp -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 3256 bytes I(n): 56.42 flops/byte W(n): 36740000.00 flops -T(n): 3995093.75 cycles -P(n): 9.20 flops/cycle +T(n): 4660804.50 cycles +P(n): 7.88 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 6456 bytes I(n): 112.67 flops/byte W(n): 145480000.00 flops -T(n): 11929089.00 cycles -P(n): 12.20 flops/cycle +T(n): 14015782.00 cycles +P(n): 10.38 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 12856 bytes I(n): 225.17 flops/byte W(n): 578960000.00 flops -T(n): 39616448.00 cycles -P(n): 14.61 flops/cycle +T(n): 47630040.00 cycles +P(n): 12.16 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 32056 bytes I(n): 562.67 flops/byte W(n): 3607399936.00 flops -T(n): 223771808.00 cycles -P(n): 16.12 flops/cycle +T(n): 272007200.00 cycles +P(n): 13.26 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 64056 bytes I(n): 1125.17 flops/byte W(n): 14414799872.00 flops -T(n): 854663616.00 cycles -P(n): 16.87 flops/cycle +T(n): 1042778816.00 cycles +P(n): 13.82 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 128056 bytes I(n): 2250.17 flops/byte W(n): 57629601792.00 flops -T(n): 3338979072.00 cycles -P(n): 17.26 flops/cycle +T(n): 4092400640.00 cycles +P(n): 14.08 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800369920.00 flops Q(n) per iteration: 320056 bytes I(n): 5625.17 flops/byte W(n): 360073986048.00 flops -T(n): 20689987584.00 cycles -P(n): 17.40 flops/cycle +T(n): 25352386560.00 cycles +P(n): 14.20 flops/cycle === N_P=10000 N_ITER=200 === W(n) per iteration: 2905772800.00 flops Q(n) per iteration: 640056 bytes I(n): 4539.87 flops/byte W(n): 581154570240.00 flops -T(n): 82361786368.00 cycles -P(n): 7.06 flops/cycle +T(n): 101285814272.00 cycles +P(n): 5.74 flops/cycle diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp/x86/3.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp/x86/3.log new file mode 100644 index 0000000..49a7e56 --- /dev/null +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp/x86/3.log @@ -0,0 +1,66 @@ +rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +=== N_P=50 N_ITER=200 === +W(n) per iteration: 183700.00 flops +Q(n) per iteration: 3256 bytes +I(n): 56.42 flops/byte +W(n): 36740000.00 flops +T(n): 4633135.50 cycles +P(n): 7.93 flops/cycle + +=== N_P=100 N_ITER=200 === +W(n) per iteration: 727400.00 flops +Q(n) per iteration: 6456 bytes +I(n): 112.67 flops/byte +W(n): 145480000.00 flops +T(n): 14098810.00 cycles +P(n): 10.32 flops/cycle + +=== N_P=200 N_ITER=200 === +W(n) per iteration: 2894800.00 flops +Q(n) per iteration: 12856 bytes +I(n): 225.17 flops/byte +W(n): 578960000.00 flops +T(n): 47519168.00 cycles +P(n): 12.18 flops/cycle + +=== N_P=500 N_ITER=200 === +W(n) per iteration: 18037000.00 flops +Q(n) per iteration: 32056 bytes +I(n): 562.67 flops/byte +W(n): 3607399936.00 flops +T(n): 272423904.00 cycles +P(n): 13.24 flops/cycle + +=== N_P=1000 N_ITER=200 === +W(n) per iteration: 72074000.00 flops +Q(n) per iteration: 64056 bytes +I(n): 1125.17 flops/byte +W(n): 14414799872.00 flops +T(n): 1060791424.00 cycles +P(n): 13.59 flops/cycle + +=== N_P=2000 N_ITER=200 === +W(n) per iteration: 288148000.00 flops +Q(n) per iteration: 128056 bytes +I(n): 2250.17 flops/byte +W(n): 57629601792.00 flops +T(n): 4102831872.00 cycles +P(n): 14.05 flops/cycle + +=== N_P=5000 N_ITER=200 === +W(n) per iteration: 1800369920.00 flops +Q(n) per iteration: 320056 bytes +I(n): 5625.17 flops/byte +W(n): 360073986048.00 flops +T(n): 25357774848.00 cycles +P(n): 14.20 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 100551254016.00 cycles +P(n): 5.78 flops/cycle + diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt/x86/1.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt/x86/1.log index 7be9195..7cc9274 100644 --- a/measurements/variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt/x86/1.log +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt/x86/1.log @@ -1,58 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt.cpp -o main_float_inlining_SoA_AVX512_polyexp_fastinvsqrt -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_fastinvsqrt_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 3256 bytes I(n): 56.42 flops/byte W(n): 36740000.00 flops -T(n): 4235088.00 cycles -P(n): 8.68 flops/cycle +T(n): 4899351.00 cycles +P(n): 7.50 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 6456 bytes I(n): 112.67 flops/byte W(n): 145480000.00 flops -T(n): 12301878.00 cycles -P(n): 11.83 flops/cycle +T(n): 14704840.00 cycles +P(n): 9.89 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 12856 bytes I(n): 225.17 flops/byte W(n): 578960000.00 flops -T(n): 40178688.00 cycles -P(n): 14.41 flops/cycle +T(n): 48870456.00 cycles +P(n): 11.85 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 32056 bytes I(n): 562.67 flops/byte W(n): 3607399936.00 flops -T(n): 223423168.00 cycles -P(n): 16.15 flops/cycle +T(n): 274548320.00 cycles +P(n): 13.14 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 64056 bytes I(n): 1125.17 flops/byte W(n): 14414799872.00 flops -T(n): 848105152.00 cycles -P(n): 17.00 flops/cycle +T(n): 1067638016.00 cycles +P(n): 13.50 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 128056 bytes I(n): 2250.17 flops/byte W(n): 57629601792.00 flops -T(n): 3303374080.00 cycles -P(n): 17.45 flops/cycle +T(n): 4133780736.00 cycles +P(n): 13.94 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800369920.00 flops Q(n) per iteration: 320056 bytes I(n): 5625.17 flops/byte W(n): 360073986048.00 flops -T(n): 20445360128.00 cycles -P(n): 17.61 flops/cycle +T(n): 25536294912.00 cycles +P(n): 14.10 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 101531860992.00 cycles +P(n): 5.72 flops/cycle diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt/x86/2.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt/x86/2.log index af94299..b038931 100644 --- a/measurements/variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt/x86/2.log +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt/x86/2.log @@ -1,66 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt.cpp -o main_float_inlining_SoA_AVX512_polyexp_fastinvsqrt -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_fastinvsqrt_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 3256 bytes I(n): 56.42 flops/byte W(n): 36740000.00 flops -T(n): 4261088.00 cycles -P(n): 8.62 flops/cycle +T(n): 4906050.00 cycles +P(n): 7.49 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 6456 bytes I(n): 112.67 flops/byte W(n): 145480000.00 flops -T(n): 12455221.00 cycles -P(n): 11.68 flops/cycle +T(n): 14798538.00 cycles +P(n): 9.83 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 12856 bytes I(n): 225.17 flops/byte W(n): 578960000.00 flops -T(n): 40661000.00 cycles -P(n): 14.24 flops/cycle +T(n): 48817384.00 cycles +P(n): 11.86 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 32056 bytes I(n): 562.67 flops/byte W(n): 3607399936.00 flops -T(n): 226296576.00 cycles -P(n): 15.94 flops/cycle +T(n): 276943584.00 cycles +P(n): 13.03 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 64056 bytes I(n): 1125.17 flops/byte W(n): 14414799872.00 flops -T(n): 859257920.00 cycles -P(n): 16.78 flops/cycle +T(n): 1052295168.00 cycles +P(n): 13.70 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 128056 bytes I(n): 2250.17 flops/byte W(n): 57629601792.00 flops -T(n): 3344503808.00 cycles -P(n): 17.23 flops/cycle +T(n): 4133724672.00 cycles +P(n): 13.94 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800369920.00 flops Q(n) per iteration: 320056 bytes I(n): 5625.17 flops/byte W(n): 360073986048.00 flops -T(n): 20797153280.00 cycles -P(n): 17.31 flops/cycle +T(n): 25570220032.00 cycles +P(n): 14.08 flops/cycle === N_P=10000 N_ITER=200 === W(n) per iteration: 2905772800.00 flops Q(n) per iteration: 640056 bytes I(n): 4539.87 flops/byte W(n): 581154570240.00 flops -T(n): 82334916608.00 cycles -P(n): 7.06 flops/cycle +T(n): 101490999296.00 cycles +P(n): 5.73 flops/cycle diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt/x86/3.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt/x86/3.log new file mode 100644 index 0000000..ed48881 --- /dev/null +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt/x86/3.log @@ -0,0 +1,66 @@ +rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_fastinvsqrt_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +=== N_P=50 N_ITER=200 === +W(n) per iteration: 183700.00 flops +Q(n) per iteration: 3256 bytes +I(n): 56.42 flops/byte +W(n): 36740000.00 flops +T(n): 4896082.00 cycles +P(n): 7.50 flops/cycle + +=== N_P=100 N_ITER=200 === +W(n) per iteration: 727400.00 flops +Q(n) per iteration: 6456 bytes +I(n): 112.67 flops/byte +W(n): 145480000.00 flops +T(n): 14589518.00 cycles +P(n): 9.97 flops/cycle + +=== N_P=200 N_ITER=200 === +W(n) per iteration: 2894800.00 flops +Q(n) per iteration: 12856 bytes +I(n): 225.17 flops/byte +W(n): 578960000.00 flops +T(n): 48579536.00 cycles +P(n): 11.92 flops/cycle + +=== N_P=500 N_ITER=200 === +W(n) per iteration: 18037000.00 flops +Q(n) per iteration: 32056 bytes +I(n): 562.67 flops/byte +W(n): 3607399936.00 flops +T(n): 275277376.00 cycles +P(n): 13.10 flops/cycle + +=== N_P=1000 N_ITER=200 === +W(n) per iteration: 72074000.00 flops +Q(n) per iteration: 64056 bytes +I(n): 1125.17 flops/byte +W(n): 14414799872.00 flops +T(n): 1050094400.00 cycles +P(n): 13.73 flops/cycle + +=== N_P=2000 N_ITER=200 === +W(n) per iteration: 288148000.00 flops +Q(n) per iteration: 128056 bytes +I(n): 2250.17 flops/byte +W(n): 57629601792.00 flops +T(n): 4110344448.00 cycles +P(n): 14.02 flops/cycle + +=== N_P=5000 N_ITER=200 === +W(n) per iteration: 1800369920.00 flops +Q(n) per iteration: 320056 bytes +I(n): 5625.17 flops/byte +W(n): 360073986048.00 flops +T(n): 25639516160.00 cycles +P(n): 14.04 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 101213003776.00 cycles +P(n): 5.74 flops/cycle + diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx/x86/1.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx/x86/1.log index 2c8917d..29aad47 100644 --- a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx/x86/1.log +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx/x86/1.log @@ -1,58 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 3256 bytes I(n): 56.42 flops/byte W(n): 36740000.00 flops -T(n): 3667923.00 cycles -P(n): 10.02 flops/cycle +T(n): 4444855.00 cycles +P(n): 8.27 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 6456 bytes I(n): 112.67 flops/byte W(n): 145480000.00 flops -T(n): 11422578.00 cycles -P(n): 12.74 flops/cycle +T(n): 13834708.00 cycles +P(n): 10.52 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 12856 bytes I(n): 225.17 flops/byte W(n): 578960000.00 flops -T(n): 37820328.00 cycles -P(n): 15.31 flops/cycle +T(n): 47410956.00 cycles +P(n): 12.21 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 32056 bytes I(n): 562.67 flops/byte W(n): 3607399936.00 flops -T(n): 216471376.00 cycles -P(n): 16.66 flops/cycle +T(n): 276381408.00 cycles +P(n): 13.05 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 64056 bytes I(n): 1125.17 flops/byte W(n): 14414799872.00 flops -T(n): 832166400.00 cycles -P(n): 17.32 flops/cycle +T(n): 1067362496.00 cycles +P(n): 13.51 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 128056 bytes I(n): 2250.17 flops/byte W(n): 57629601792.00 flops -T(n): 3253410304.00 cycles -P(n): 17.71 flops/cycle +T(n): 4156325376.00 cycles +P(n): 13.87 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800369920.00 flops Q(n) per iteration: 320056 bytes I(n): 5625.17 flops/byte W(n): 360073986048.00 flops -T(n): 20200312832.00 cycles -P(n): 17.83 flops/cycle +T(n): 26170245120.00 cycles +P(n): 13.76 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 104163885056.00 cycles +P(n): 5.58 flops/cycle diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx/x86/2.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx/x86/2.log index d2df607..dcd470c 100644 --- a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx/x86/2.log +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx/x86/2.log @@ -1,66 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 3256 bytes I(n): 56.42 flops/byte W(n): 36740000.00 flops -T(n): 3700145.00 cycles -P(n): 9.93 flops/cycle +T(n): 4415419.00 cycles +P(n): 8.32 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 6456 bytes I(n): 112.67 flops/byte W(n): 145480000.00 flops -T(n): 11292105.00 cycles -P(n): 12.88 flops/cycle +T(n): 13731945.00 cycles +P(n): 10.59 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 12856 bytes I(n): 225.17 flops/byte W(n): 578960000.00 flops -T(n): 38161324.00 cycles -P(n): 15.17 flops/cycle +T(n): 47216112.00 cycles +P(n): 12.26 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 32056 bytes I(n): 562.67 flops/byte W(n): 3607399936.00 flops -T(n): 218794224.00 cycles -P(n): 16.49 flops/cycle +T(n): 273902208.00 cycles +P(n): 13.17 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 64056 bytes I(n): 1125.17 flops/byte W(n): 14414799872.00 flops -T(n): 840880000.00 cycles -P(n): 17.14 flops/cycle +T(n): 1066031616.00 cycles +P(n): 13.52 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 128056 bytes I(n): 2250.17 flops/byte W(n): 57629601792.00 flops -T(n): 3292569344.00 cycles -P(n): 17.50 flops/cycle +T(n): 4168480512.00 cycles +P(n): 13.83 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800369920.00 flops Q(n) per iteration: 320056 bytes I(n): 5625.17 flops/byte W(n): 360073986048.00 flops -T(n): 20442466304.00 cycles -P(n): 17.61 flops/cycle +T(n): 25959776256.00 cycles +P(n): 13.87 flops/cycle === N_P=10000 N_ITER=200 === W(n) per iteration: 2905772800.00 flops Q(n) per iteration: 640056 bytes I(n): 4539.87 flops/byte W(n): 581154570240.00 flops -T(n): 81447813120.00 cycles -P(n): 7.14 flops/cycle +T(n): 103256596480.00 cycles +P(n): 5.63 flops/cycle diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx/x86/3.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx/x86/3.log new file mode 100644 index 0000000..a66e481 --- /dev/null +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx/x86/3.log @@ -0,0 +1,66 @@ +rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +=== N_P=50 N_ITER=200 === +W(n) per iteration: 183700.00 flops +Q(n) per iteration: 3256 bytes +I(n): 56.42 flops/byte +W(n): 36740000.00 flops +T(n): 4421310.50 cycles +P(n): 8.31 flops/cycle + +=== N_P=100 N_ITER=200 === +W(n) per iteration: 727400.00 flops +Q(n) per iteration: 6456 bytes +I(n): 112.67 flops/byte +W(n): 145480000.00 flops +T(n): 13851305.00 cycles +P(n): 10.50 flops/cycle + +=== N_P=200 N_ITER=200 === +W(n) per iteration: 2894800.00 flops +Q(n) per iteration: 12856 bytes +I(n): 225.17 flops/byte +W(n): 578960000.00 flops +T(n): 47453300.00 cycles +P(n): 12.20 flops/cycle + +=== N_P=500 N_ITER=200 === +W(n) per iteration: 18037000.00 flops +Q(n) per iteration: 32056 bytes +I(n): 562.67 flops/byte +W(n): 3607399936.00 flops +T(n): 275350432.00 cycles +P(n): 13.10 flops/cycle + +=== N_P=1000 N_ITER=200 === +W(n) per iteration: 72074000.00 flops +Q(n) per iteration: 64056 bytes +I(n): 1125.17 flops/byte +W(n): 14414799872.00 flops +T(n): 1059425216.00 cycles +P(n): 13.61 flops/cycle + +=== N_P=2000 N_ITER=200 === +W(n) per iteration: 288148000.00 flops +Q(n) per iteration: 128056 bytes +I(n): 2250.17 flops/byte +W(n): 57629601792.00 flops +T(n): 4161480448.00 cycles +P(n): 13.85 flops/cycle + +=== N_P=5000 N_ITER=200 === +W(n) per iteration: 1800369920.00 flops +Q(n) per iteration: 320056 bytes +I(n): 5625.17 flops/byte +W(n): 360073986048.00 flops +T(n): 25909958656.00 cycles +P(n): 13.90 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 102891044864.00 cycles +P(n): 5.65 flops/cycle + diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2/x86/1.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2/x86/1.log index 42e40a3..8b8601d 100644 --- a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2/x86/1.log +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2/x86/1.log @@ -1,58 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2 -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 3256 bytes I(n): 56.42 flops/byte W(n): 36740000.00 flops -T(n): 3477458.00 cycles -P(n): 10.57 flops/cycle +T(n): 4116743.00 cycles +P(n): 8.92 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 6456 bytes I(n): 112.67 flops/byte W(n): 145480000.00 flops -T(n): 11784472.00 cycles -P(n): 12.35 flops/cycle +T(n): 14193060.00 cycles +P(n): 10.25 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 12856 bytes I(n): 225.17 flops/byte W(n): 578960000.00 flops -T(n): 38291872.00 cycles -P(n): 15.12 flops/cycle +T(n): 46275016.00 cycles +P(n): 12.51 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 32056 bytes I(n): 562.67 flops/byte W(n): 3607399936.00 flops -T(n): 202935328.00 cycles -P(n): 17.78 flops/cycle +T(n): 250446432.00 cycles +P(n): 14.40 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 64056 bytes I(n): 1125.17 flops/byte W(n): 14414799872.00 flops -T(n): 792025088.00 cycles -P(n): 18.20 flops/cycle +T(n): 977844992.00 cycles +P(n): 14.74 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 128056 bytes I(n): 2250.17 flops/byte W(n): 57629601792.00 flops -T(n): 3083133952.00 cycles -P(n): 18.69 flops/cycle +T(n): 3811610624.00 cycles +P(n): 15.12 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800369920.00 flops Q(n) per iteration: 320056 bytes I(n): 5625.17 flops/byte W(n): 360073986048.00 flops -T(n): 19033051136.00 cycles -P(n): 18.92 flops/cycle +T(n): 23616888832.00 cycles +P(n): 15.25 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 94000291840.00 cycles +P(n): 6.18 flops/cycle diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2/x86/2.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2/x86/2.log index 52d6012..2a209b9 100644 --- a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2/x86/2.log +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2/x86/2.log @@ -1,66 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2 -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 3256 bytes I(n): 56.42 flops/byte W(n): 36740000.00 flops -T(n): 3489274.50 cycles -P(n): 10.53 flops/cycle +T(n): 4130377.00 cycles +P(n): 8.90 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 6456 bytes I(n): 112.67 flops/byte W(n): 145480000.00 flops -T(n): 11797675.00 cycles -P(n): 12.33 flops/cycle +T(n): 14179700.00 cycles +P(n): 10.26 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 12856 bytes I(n): 225.17 flops/byte W(n): 578960000.00 flops -T(n): 38045456.00 cycles -P(n): 15.22 flops/cycle +T(n): 46318220.00 cycles +P(n): 12.50 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 32056 bytes I(n): 562.67 flops/byte W(n): 3607399936.00 flops -T(n): 203912944.00 cycles -P(n): 17.69 flops/cycle +T(n): 250998336.00 cycles +P(n): 14.37 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 64056 bytes I(n): 1125.17 flops/byte W(n): 14414799872.00 flops -T(n): 794322688.00 cycles -P(n): 18.15 flops/cycle +T(n): 982180672.00 cycles +P(n): 14.68 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 128056 bytes I(n): 2250.17 flops/byte W(n): 57629601792.00 flops -T(n): 3086995712.00 cycles -P(n): 18.67 flops/cycle +T(n): 3805426944.00 cycles +P(n): 15.14 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800369920.00 flops Q(n) per iteration: 320056 bytes I(n): 5625.17 flops/byte W(n): 360073986048.00 flops -T(n): 19067494400.00 cycles -P(n): 18.88 flops/cycle +T(n): 23592302592.00 cycles +P(n): 15.26 flops/cycle === N_P=10000 N_ITER=200 === W(n) per iteration: 2905772800.00 flops Q(n) per iteration: 640056 bytes I(n): 4539.87 flops/byte W(n): 581154570240.00 flops -T(n): 75557011456.00 cycles -P(n): 7.69 flops/cycle +T(n): 93937680384.00 cycles +P(n): 6.19 flops/cycle diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2/x86/3.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2/x86/3.log new file mode 100644 index 0000000..7f8cb13 --- /dev/null +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2/x86/3.log @@ -0,0 +1,66 @@ +rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +=== N_P=50 N_ITER=200 === +W(n) per iteration: 183700.00 flops +Q(n) per iteration: 3256 bytes +I(n): 56.42 flops/byte +W(n): 36740000.00 flops +T(n): 4107580.00 cycles +P(n): 8.94 flops/cycle + +=== N_P=100 N_ITER=200 === +W(n) per iteration: 727400.00 flops +Q(n) per iteration: 6456 bytes +I(n): 112.67 flops/byte +W(n): 145480000.00 flops +T(n): 14142018.00 cycles +P(n): 10.29 flops/cycle + +=== N_P=200 N_ITER=200 === +W(n) per iteration: 2894800.00 flops +Q(n) per iteration: 12856 bytes +I(n): 225.17 flops/byte +W(n): 578960000.00 flops +T(n): 46132236.00 cycles +P(n): 12.55 flops/cycle + +=== N_P=500 N_ITER=200 === +W(n) per iteration: 18037000.00 flops +Q(n) per iteration: 32056 bytes +I(n): 562.67 flops/byte +W(n): 3607399936.00 flops +T(n): 248790048.00 cycles +P(n): 14.50 flops/cycle + +=== N_P=1000 N_ITER=200 === +W(n) per iteration: 72074000.00 flops +Q(n) per iteration: 64056 bytes +I(n): 1125.17 flops/byte +W(n): 14414799872.00 flops +T(n): 974417088.00 cycles +P(n): 14.79 flops/cycle + +=== N_P=2000 N_ITER=200 === +W(n) per iteration: 288148000.00 flops +Q(n) per iteration: 128056 bytes +I(n): 2250.17 flops/byte +W(n): 57629601792.00 flops +T(n): 3791391744.00 cycles +P(n): 15.20 flops/cycle + +=== N_P=5000 N_ITER=200 === +W(n) per iteration: 1800369920.00 flops +Q(n) per iteration: 320056 bytes +I(n): 5625.17 flops/byte +W(n): 360073986048.00 flops +T(n): 23488210944.00 cycles +P(n): 15.33 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 93195214848.00 cycles +P(n): 6.24 flops/cycle + diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp/x86/1.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp/x86/1.log index 6cdd3a9..3ea961d 100644 --- a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp/x86/1.log +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp/x86/1.log @@ -1,58 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 3256 bytes I(n): 56.42 flops/byte W(n): 36740000.00 flops -T(n): 3500766.25 cycles -P(n): 10.49 flops/cycle +T(n): 4119329.50 cycles +P(n): 8.92 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 6456 bytes I(n): 112.67 flops/byte W(n): 145480000.00 flops -T(n): 11807499.00 cycles -P(n): 12.32 flops/cycle +T(n): 14140615.00 cycles +P(n): 10.29 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 12856 bytes I(n): 225.17 flops/byte W(n): 578960000.00 flops -T(n): 38032600.00 cycles -P(n): 15.22 flops/cycle +T(n): 46104904.00 cycles +P(n): 12.56 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 32056 bytes I(n): 562.67 flops/byte W(n): 3607399936.00 flops -T(n): 204147360.00 cycles -P(n): 17.67 flops/cycle +T(n): 248777184.00 cycles +P(n): 14.50 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 64056 bytes I(n): 1125.17 flops/byte W(n): 14414799872.00 flops -T(n): 791926400.00 cycles -P(n): 18.20 flops/cycle +T(n): 972575296.00 cycles +P(n): 14.82 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 128056 bytes I(n): 2250.17 flops/byte W(n): 57629601792.00 flops -T(n): 3074645504.00 cycles -P(n): 18.74 flops/cycle +T(n): 3793779712.00 cycles +P(n): 15.19 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800369920.00 flops Q(n) per iteration: 320056 bytes I(n): 5625.17 flops/byte W(n): 360073986048.00 flops -T(n): 19024320512.00 cycles -P(n): 18.93 flops/cycle +T(n): 23662673920.00 cycles +P(n): 15.22 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 93648879616.00 cycles +P(n): 6.21 flops/cycle diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp/x86/2.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp/x86/2.log index 73f3cc8..29375a1 100644 --- a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp/x86/2.log +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp/x86/2.log @@ -1,66 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 3256 bytes I(n): 56.42 flops/byte W(n): 36740000.00 flops -T(n): 3498589.50 cycles -P(n): 10.50 flops/cycle +T(n): 4131873.00 cycles +P(n): 8.89 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 6456 bytes I(n): 112.67 flops/byte W(n): 145480000.00 flops -T(n): 11758110.00 cycles -P(n): 12.37 flops/cycle +T(n): 14207365.00 cycles +P(n): 10.24 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 12856 bytes I(n): 225.17 flops/byte W(n): 578960000.00 flops -T(n): 37864020.00 cycles -P(n): 15.29 flops/cycle +T(n): 46157304.00 cycles +P(n): 12.54 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 32056 bytes I(n): 562.67 flops/byte W(n): 3607399936.00 flops -T(n): 202672640.00 cycles -P(n): 17.80 flops/cycle +T(n): 249512304.00 cycles +P(n): 14.46 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 64056 bytes I(n): 1125.17 flops/byte W(n): 14414799872.00 flops -T(n): 790035264.00 cycles -P(n): 18.25 flops/cycle +T(n): 974145152.00 cycles +P(n): 14.80 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 128056 bytes I(n): 2250.17 flops/byte W(n): 57629601792.00 flops -T(n): 3070306304.00 cycles -P(n): 18.77 flops/cycle +T(n): 3796545280.00 cycles +P(n): 15.18 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800369920.00 flops Q(n) per iteration: 320056 bytes I(n): 5625.17 flops/byte W(n): 360073986048.00 flops -T(n): 18978818048.00 cycles -P(n): 18.97 flops/cycle +T(n): 23539767296.00 cycles +P(n): 15.30 flops/cycle === N_P=10000 N_ITER=200 === W(n) per iteration: 2905772800.00 flops Q(n) per iteration: 640056 bytes I(n): 4539.87 flops/byte W(n): 581154570240.00 flops -T(n): 75496284160.00 cycles -P(n): 7.70 flops/cycle +T(n): 93385080832.00 cycles +P(n): 6.22 flops/cycle diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp/x86/3.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp/x86/3.log new file mode 100644 index 0000000..d853e35 --- /dev/null +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp/x86/3.log @@ -0,0 +1,66 @@ +rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +=== N_P=50 N_ITER=200 === +W(n) per iteration: 183700.00 flops +Q(n) per iteration: 3256 bytes +I(n): 56.42 flops/byte +W(n): 36740000.00 flops +T(n): 4133901.25 cycles +P(n): 8.89 flops/cycle + +=== N_P=100 N_ITER=200 === +W(n) per iteration: 727400.00 flops +Q(n) per iteration: 6456 bytes +I(n): 112.67 flops/byte +W(n): 145480000.00 flops +T(n): 14286805.00 cycles +P(n): 10.18 flops/cycle + +=== N_P=200 N_ITER=200 === +W(n) per iteration: 2894800.00 flops +Q(n) per iteration: 12856 bytes +I(n): 225.17 flops/byte +W(n): 578960000.00 flops +T(n): 46514768.00 cycles +P(n): 12.45 flops/cycle + +=== N_P=500 N_ITER=200 === +W(n) per iteration: 18037000.00 flops +Q(n) per iteration: 32056 bytes +I(n): 562.67 flops/byte +W(n): 3607399936.00 flops +T(n): 250415104.00 cycles +P(n): 14.41 flops/cycle + +=== N_P=1000 N_ITER=200 === +W(n) per iteration: 72074000.00 flops +Q(n) per iteration: 64056 bytes +I(n): 1125.17 flops/byte +W(n): 14414799872.00 flops +T(n): 979476864.00 cycles +P(n): 14.72 flops/cycle + +=== N_P=2000 N_ITER=200 === +W(n) per iteration: 288148000.00 flops +Q(n) per iteration: 128056 bytes +I(n): 2250.17 flops/byte +W(n): 57629601792.00 flops +T(n): 3790536448.00 cycles +P(n): 15.20 flops/cycle + +=== N_P=5000 N_ITER=200 === +W(n) per iteration: 1800369920.00 flops +Q(n) per iteration: 320056 bytes +I(n): 5625.17 flops/byte +W(n): 360073986048.00 flops +T(n): 23435288576.00 cycles +P(n): 15.36 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 93591674880.00 cycles +P(n): 6.21 flops/cycle + diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt/x86/1.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt/x86/1.log index a950e19..4022b05 100644 --- a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt/x86/1.log +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt/x86/1.log @@ -1,58 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 3256 bytes I(n): 56.42 flops/byte W(n): 36740000.00 flops -T(n): 3466542.50 cycles -P(n): 10.60 flops/cycle +T(n): 4119765.00 cycles +P(n): 8.92 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 6456 bytes I(n): 112.67 flops/byte W(n): 145480000.00 flops -T(n): 11758505.00 cycles -P(n): 12.37 flops/cycle +T(n): 14158772.00 cycles +P(n): 10.27 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 12856 bytes I(n): 225.17 flops/byte W(n): 578960000.00 flops -T(n): 38354536.00 cycles -P(n): 15.09 flops/cycle +T(n): 46276376.00 cycles +P(n): 12.51 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 32056 bytes I(n): 562.67 flops/byte W(n): 3607399936.00 flops -T(n): 203609408.00 cycles -P(n): 17.72 flops/cycle +T(n): 249878624.00 cycles +P(n): 14.44 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 64056 bytes I(n): 1125.17 flops/byte W(n): 14414799872.00 flops -T(n): 792448704.00 cycles -P(n): 18.19 flops/cycle +T(n): 982863872.00 cycles +P(n): 14.67 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 128056 bytes I(n): 2250.17 flops/byte W(n): 57629601792.00 flops -T(n): 3076762624.00 cycles -P(n): 18.73 flops/cycle +T(n): 3826156544.00 cycles +P(n): 15.06 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800369920.00 flops Q(n) per iteration: 320056 bytes I(n): 5625.17 flops/byte W(n): 360073986048.00 flops -T(n): 19086870528.00 cycles -P(n): 18.87 flops/cycle +T(n): 23693496320.00 cycles +P(n): 15.20 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 94222524416.00 cycles +P(n): 6.17 flops/cycle diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt/x86/2.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt/x86/2.log index 967df04..4c1d8cf 100644 --- a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt/x86/2.log +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt/x86/2.log @@ -1,66 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 3256 bytes I(n): 56.42 flops/byte W(n): 36740000.00 flops -T(n): 3470556.25 cycles -P(n): 10.59 flops/cycle +T(n): 4102695.50 cycles +P(n): 8.96 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 6456 bytes I(n): 112.67 flops/byte W(n): 145480000.00 flops -T(n): 11748129.00 cycles -P(n): 12.38 flops/cycle +T(n): 14151872.00 cycles +P(n): 10.28 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 12856 bytes I(n): 225.17 flops/byte W(n): 578960000.00 flops -T(n): 37961964.00 cycles -P(n): 15.25 flops/cycle +T(n): 46248272.00 cycles +P(n): 12.52 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 32056 bytes I(n): 562.67 flops/byte W(n): 3607399936.00 flops -T(n): 203245888.00 cycles -P(n): 17.75 flops/cycle +T(n): 249935680.00 cycles +P(n): 14.43 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 64056 bytes I(n): 1125.17 flops/byte W(n): 14414799872.00 flops -T(n): 792723072.00 cycles -P(n): 18.18 flops/cycle +T(n): 977354240.00 cycles +P(n): 14.75 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 128056 bytes I(n): 2250.17 flops/byte W(n): 57629601792.00 flops -T(n): 3083602944.00 cycles -P(n): 18.69 flops/cycle +T(n): 3821584896.00 cycles +P(n): 15.08 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800369920.00 flops Q(n) per iteration: 320056 bytes I(n): 5625.17 flops/byte W(n): 360073986048.00 flops -T(n): 19105830912.00 cycles -P(n): 18.85 flops/cycle +T(n): 23594674176.00 cycles +P(n): 15.26 flops/cycle === N_P=10000 N_ITER=200 === W(n) per iteration: 2905772800.00 flops Q(n) per iteration: 640056 bytes I(n): 4539.87 flops/byte W(n): 581154570240.00 flops -T(n): 75556601856.00 cycles -P(n): 7.69 flops/cycle +T(n): 94093844480.00 cycles +P(n): 6.18 flops/cycle diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt/x86/3.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt/x86/3.log new file mode 100644 index 0000000..a80e32c --- /dev/null +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt/x86/3.log @@ -0,0 +1,66 @@ +rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +=== N_P=50 N_ITER=200 === +W(n) per iteration: 183700.00 flops +Q(n) per iteration: 3256 bytes +I(n): 56.42 flops/byte +W(n): 36740000.00 flops +T(n): 4124268.00 cycles +P(n): 8.91 flops/cycle + +=== N_P=100 N_ITER=200 === +W(n) per iteration: 727400.00 flops +Q(n) per iteration: 6456 bytes +I(n): 112.67 flops/byte +W(n): 145480000.00 flops +T(n): 14218675.00 cycles +P(n): 10.23 flops/cycle + +=== N_P=200 N_ITER=200 === +W(n) per iteration: 2894800.00 flops +Q(n) per iteration: 12856 bytes +I(n): 225.17 flops/byte +W(n): 578960000.00 flops +T(n): 46843476.00 cycles +P(n): 12.36 flops/cycle + +=== N_P=500 N_ITER=200 === +W(n) per iteration: 18037000.00 flops +Q(n) per iteration: 32056 bytes +I(n): 562.67 flops/byte +W(n): 3607399936.00 flops +T(n): 250210640.00 cycles +P(n): 14.42 flops/cycle + +=== N_P=1000 N_ITER=200 === +W(n) per iteration: 72074000.00 flops +Q(n) per iteration: 64056 bytes +I(n): 1125.17 flops/byte +W(n): 14414799872.00 flops +T(n): 982352128.00 cycles +P(n): 14.67 flops/cycle + +=== N_P=2000 N_ITER=200 === +W(n) per iteration: 288148000.00 flops +Q(n) per iteration: 128056 bytes +I(n): 2250.17 flops/byte +W(n): 57629601792.00 flops +T(n): 3823222016.00 cycles +P(n): 15.07 flops/cycle + +=== N_P=5000 N_ITER=200 === +W(n) per iteration: 1800369920.00 flops +Q(n) per iteration: 320056 bytes +I(n): 5625.17 flops/byte +W(n): 360073986048.00 flops +T(n): 23695175680.00 cycles +P(n): 15.20 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 94304829440.00 cycles +P(n): 6.16 flops/cycle + diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt/x86/1.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt/x86/1.log index cd711d9..fd8f66f 100644 --- a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt/x86/1.log +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt/x86/1.log @@ -1,58 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 3256 bytes I(n): 56.42 flops/byte W(n): 36740000.00 flops -T(n): 2966264.00 cycles -P(n): 12.39 flops/cycle +T(n): 3472917.50 cycles +P(n): 10.58 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 6456 bytes I(n): 112.67 flops/byte W(n): 145480000.00 flops -T(n): 9680198.00 cycles -P(n): 15.03 flops/cycle +T(n): 11763622.00 cycles +P(n): 12.37 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 12856 bytes I(n): 225.17 flops/byte W(n): 578960000.00 flops -T(n): 30652810.00 cycles -P(n): 18.89 flops/cycle +T(n): 38070640.00 cycles +P(n): 15.21 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 32056 bytes I(n): 562.67 flops/byte W(n): 3607399936.00 flops -T(n): 160992976.00 cycles -P(n): 22.41 flops/cycle +T(n): 204154320.00 cycles +P(n): 17.67 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 64056 bytes I(n): 1125.17 flops/byte W(n): 14414799872.00 flops -T(n): 629138816.00 cycles -P(n): 22.91 flops/cycle +T(n): 798999808.00 cycles +P(n): 18.04 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 128056 bytes I(n): 2250.17 flops/byte W(n): 57629601792.00 flops -T(n): 2423142656.00 cycles -P(n): 23.78 flops/cycle +T(n): 3114275584.00 cycles +P(n): 18.50 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800369920.00 flops Q(n) per iteration: 320056 bytes I(n): 5625.17 flops/byte W(n): 360073986048.00 flops -T(n): 15022035968.00 cycles -P(n): 23.97 flops/cycle +T(n): 19146825728.00 cycles +P(n): 18.81 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 76207964160.00 cycles +P(n): 7.63 flops/cycle diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt/x86/2.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt/x86/2.log index 179470e..0a1f7d4 100644 --- a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt/x86/2.log +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt/x86/2.log @@ -1,66 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 3256 bytes I(n): 56.42 flops/byte W(n): 36740000.00 flops -T(n): 2942563.50 cycles -P(n): 12.49 flops/cycle +T(n): 3503500.00 cycles +P(n): 10.49 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 6456 bytes I(n): 112.67 flops/byte W(n): 145480000.00 flops -T(n): 9665785.00 cycles -P(n): 15.05 flops/cycle +T(n): 11802675.00 cycles +P(n): 12.33 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 12856 bytes I(n): 225.17 flops/byte W(n): 578960000.00 flops -T(n): 30626330.00 cycles -P(n): 18.90 flops/cycle +T(n): 37947776.00 cycles +P(n): 15.26 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 32056 bytes I(n): 562.67 flops/byte W(n): 3607399936.00 flops -T(n): 161586752.00 cycles -P(n): 22.32 flops/cycle +T(n): 203323776.00 cycles +P(n): 17.74 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 64056 bytes I(n): 1125.17 flops/byte W(n): 14414799872.00 flops -T(n): 626457472.00 cycles -P(n): 23.01 flops/cycle +T(n): 821986944.00 cycles +P(n): 17.54 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 128056 bytes I(n): 2250.17 flops/byte W(n): 57629601792.00 flops -T(n): 2423129344.00 cycles -P(n): 23.78 flops/cycle +T(n): 3103710720.00 cycles +P(n): 18.57 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800369920.00 flops Q(n) per iteration: 320056 bytes I(n): 5625.17 flops/byte W(n): 360073986048.00 flops -T(n): 14910323712.00 cycles -P(n): 24.15 flops/cycle +T(n): 19254915072.00 cycles +P(n): 18.70 flops/cycle === N_P=10000 N_ITER=200 === W(n) per iteration: 2905772800.00 flops Q(n) per iteration: 640056 bytes I(n): 4539.87 flops/byte W(n): 581154570240.00 flops -T(n): 59213176832.00 cycles -P(n): 9.81 flops/cycle +T(n): 76036898816.00 cycles +P(n): 7.64 flops/cycle diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt/x86/3.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt/x86/3.log new file mode 100644 index 0000000..8fb271d --- /dev/null +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt/x86/3.log @@ -0,0 +1,66 @@ +rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +=== N_P=50 N_ITER=200 === +W(n) per iteration: 183700.00 flops +Q(n) per iteration: 3256 bytes +I(n): 56.42 flops/byte +W(n): 36740000.00 flops +T(n): 3474629.50 cycles +P(n): 10.57 flops/cycle + +=== N_P=100 N_ITER=200 === +W(n) per iteration: 727400.00 flops +Q(n) per iteration: 6456 bytes +I(n): 112.67 flops/byte +W(n): 145480000.00 flops +T(n): 11869545.00 cycles +P(n): 12.26 flops/cycle + +=== N_P=200 N_ITER=200 === +W(n) per iteration: 2894800.00 flops +Q(n) per iteration: 12856 bytes +I(n): 225.17 flops/byte +W(n): 578960000.00 flops +T(n): 38112416.00 cycles +P(n): 15.19 flops/cycle + +=== N_P=500 N_ITER=200 === +W(n) per iteration: 18037000.00 flops +Q(n) per iteration: 32056 bytes +I(n): 562.67 flops/byte +W(n): 3607399936.00 flops +T(n): 203449264.00 cycles +P(n): 17.73 flops/cycle + +=== N_P=1000 N_ITER=200 === +W(n) per iteration: 72074000.00 flops +Q(n) per iteration: 64056 bytes +I(n): 1125.17 flops/byte +W(n): 14414799872.00 flops +T(n): 816738752.00 cycles +P(n): 17.65 flops/cycle + +=== N_P=2000 N_ITER=200 === +W(n) per iteration: 288148000.00 flops +Q(n) per iteration: 128056 bytes +I(n): 2250.17 flops/byte +W(n): 57629601792.00 flops +T(n): 3081998592.00 cycles +P(n): 18.70 flops/cycle + +=== N_P=5000 N_ITER=200 === +W(n) per iteration: 1800369920.00 flops +Q(n) per iteration: 320056 bytes +I(n): 5625.17 flops/byte +W(n): 360073986048.00 flops +T(n): 19241965568.00 cycles +P(n): 18.71 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 76032835584.00 cycles +P(n): 7.64 flops/cycle + diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved/x86/1.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved/x86/1.log new file mode 100644 index 0000000..ed597a5 --- /dev/null +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved/x86/1.log @@ -0,0 +1,66 @@ +rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_expfix_improved.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_expfix_improved -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +=== N_P=50 N_ITER=200 === +W(n) per iteration: 183700.00 flops +Q(n) per iteration: 3256 bytes +I(n): 56.42 flops/byte +W(n): 36740000.00 flops +T(n): 3443131.25 cycles +P(n): 10.67 flops/cycle + +=== N_P=100 N_ITER=200 === +W(n) per iteration: 727400.00 flops +Q(n) per iteration: 6456 bytes +I(n): 112.67 flops/byte +W(n): 145480000.00 flops +T(n): 11289992.00 cycles +P(n): 12.89 flops/cycle + +=== N_P=200 N_ITER=200 === +W(n) per iteration: 2894800.00 flops +Q(n) per iteration: 12856 bytes +I(n): 225.17 flops/byte +W(n): 578960000.00 flops +T(n): 36293512.00 cycles +P(n): 15.95 flops/cycle + +=== N_P=500 N_ITER=200 === +W(n) per iteration: 18037000.00 flops +Q(n) per iteration: 32056 bytes +I(n): 562.67 flops/byte +W(n): 3607399936.00 flops +T(n): 193259072.00 cycles +P(n): 18.67 flops/cycle + +=== N_P=1000 N_ITER=200 === +W(n) per iteration: 72074000.00 flops +Q(n) per iteration: 64056 bytes +I(n): 1125.17 flops/byte +W(n): 14414799872.00 flops +T(n): 752713344.00 cycles +P(n): 19.15 flops/cycle + +=== N_P=2000 N_ITER=200 === +W(n) per iteration: 288148000.00 flops +Q(n) per iteration: 128056 bytes +I(n): 2250.17 flops/byte +W(n): 57629601792.00 flops +T(n): 2940765440.00 cycles +P(n): 19.60 flops/cycle + +=== N_P=5000 N_ITER=200 === +W(n) per iteration: 1800369920.00 flops +Q(n) per iteration: 320056 bytes +I(n): 5625.17 flops/byte +W(n): 360073986048.00 flops +T(n): 18122862592.00 cycles +P(n): 19.87 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 71869390848.00 cycles +P(n): 8.09 flops/cycle + diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved/x86/2.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved/x86/2.log new file mode 100644 index 0000000..08bfc3e --- /dev/null +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved/x86/2.log @@ -0,0 +1,64 @@ +=== N_P=50 N_ITER=200 === +W(n) per iteration: 183700.00 flops +Q(n) per iteration: 3256 bytes +I(n): 56.42 flops/byte +W(n): 36740000.00 flops +T(n): 3387230.00 cycles +P(n): 10.85 flops/cycle + +=== N_P=100 N_ITER=200 === +W(n) per iteration: 727400.00 flops +Q(n) per iteration: 6456 bytes +I(n): 112.67 flops/byte +W(n): 145480000.00 flops +T(n): 11326786.00 cycles +P(n): 12.84 flops/cycle + +=== N_P=200 N_ITER=200 === +W(n) per iteration: 2894800.00 flops +Q(n) per iteration: 12856 bytes +I(n): 225.17 flops/byte +W(n): 578960000.00 flops +T(n): 36351516.00 cycles +P(n): 15.93 flops/cycle + +=== N_P=500 N_ITER=200 === +W(n) per iteration: 18037000.00 flops +Q(n) per iteration: 32056 bytes +I(n): 562.67 flops/byte +W(n): 3607399936.00 flops +T(n): 194490336.00 cycles +P(n): 18.55 flops/cycle + +=== N_P=1000 N_ITER=200 === +W(n) per iteration: 72074000.00 flops +Q(n) per iteration: 64056 bytes +I(n): 1125.17 flops/byte +W(n): 14414799872.00 flops +T(n): 753201792.00 cycles +P(n): 19.14 flops/cycle + +=== N_P=2000 N_ITER=200 === +W(n) per iteration: 288148000.00 flops +Q(n) per iteration: 128056 bytes +I(n): 2250.17 flops/byte +W(n): 57629601792.00 flops +T(n): 2954236416.00 cycles +P(n): 19.51 flops/cycle + +=== N_P=5000 N_ITER=200 === +W(n) per iteration: 1800369920.00 flops +Q(n) per iteration: 320056 bytes +I(n): 5625.17 flops/byte +W(n): 360073986048.00 flops +T(n): 18356828160.00 cycles +P(n): 19.62 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 73678970880.00 cycles +P(n): 7.89 flops/cycle + diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved/x86/3.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved/x86/3.log new file mode 100644 index 0000000..70f3e89 --- /dev/null +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved/x86/3.log @@ -0,0 +1,64 @@ +=== N_P=50 N_ITER=200 === +W(n) per iteration: 183700.00 flops +Q(n) per iteration: 3256 bytes +I(n): 56.42 flops/byte +W(n): 36740000.00 flops +T(n): 3445767.00 cycles +P(n): 10.66 flops/cycle + +=== N_P=100 N_ITER=200 === +W(n) per iteration: 727400.00 flops +Q(n) per iteration: 6456 bytes +I(n): 112.67 flops/byte +W(n): 145480000.00 flops +T(n): 11501729.00 cycles +P(n): 12.65 flops/cycle + +=== N_P=200 N_ITER=200 === +W(n) per iteration: 2894800.00 flops +Q(n) per iteration: 12856 bytes +I(n): 225.17 flops/byte +W(n): 578960000.00 flops +T(n): 36756200.00 cycles +P(n): 15.75 flops/cycle + +=== N_P=500 N_ITER=200 === +W(n) per iteration: 18037000.00 flops +Q(n) per iteration: 32056 bytes +I(n): 562.67 flops/byte +W(n): 3607399936.00 flops +T(n): 198376320.00 cycles +P(n): 18.18 flops/cycle + +=== N_P=1000 N_ITER=200 === +W(n) per iteration: 72074000.00 flops +Q(n) per iteration: 64056 bytes +I(n): 1125.17 flops/byte +W(n): 14414799872.00 flops +T(n): 765950336.00 cycles +P(n): 18.82 flops/cycle + +=== N_P=2000 N_ITER=200 === +W(n) per iteration: 288148000.00 flops +Q(n) per iteration: 128056 bytes +I(n): 2250.17 flops/byte +W(n): 57629601792.00 flops +T(n): 2987576576.00 cycles +P(n): 19.29 flops/cycle + +=== N_P=5000 N_ITER=200 === +W(n) per iteration: 1800369920.00 flops +Q(n) per iteration: 320056 bytes +I(n): 5625.17 flops/byte +W(n): 360073986048.00 flops +T(n): 18625347584.00 cycles +P(n): 19.33 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 73340780544.00 cycles +P(n): 7.92 flops/cycle + diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved_moreilp/x86/1.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved_moreilp/x86/1.log new file mode 100644 index 0000000..5b20e8e --- /dev/null +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved_moreilp/x86/1.log @@ -0,0 +1,66 @@ +rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_expfix_improved_moreilp.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_expfix_improved_moreilp -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +=== N_P=50 N_ITER=200 === +W(n) per iteration: 183700.00 flops +Q(n) per iteration: 3256 bytes +I(n): 56.42 flops/byte +W(n): 36740000.00 flops +T(n): 2430659.75 cycles +P(n): 15.12 flops/cycle + +=== N_P=100 N_ITER=200 === +W(n) per iteration: 727400.00 flops +Q(n) per iteration: 6456 bytes +I(n): 112.67 flops/byte +W(n): 145480000.00 flops +T(n): 8285106.00 cycles +P(n): 17.56 flops/cycle + +=== N_P=200 N_ITER=200 === +W(n) per iteration: 2894800.00 flops +Q(n) per iteration: 12856 bytes +I(n): 225.17 flops/byte +W(n): 578960000.00 flops +T(n): 30615050.00 cycles +P(n): 18.91 flops/cycle + +=== N_P=500 N_ITER=200 === +W(n) per iteration: 18037000.00 flops +Q(n) per iteration: 32056 bytes +I(n): 562.67 flops/byte +W(n): 3607399936.00 flops +T(n): 186199040.00 cycles +P(n): 19.37 flops/cycle + +=== N_P=1000 N_ITER=200 === +W(n) per iteration: 72074000.00 flops +Q(n) per iteration: 64056 bytes +I(n): 1125.17 flops/byte +W(n): 14414799872.00 flops +T(n): 728076288.00 cycles +P(n): 19.80 flops/cycle + +=== N_P=2000 N_ITER=200 === +W(n) per iteration: 288148000.00 flops +Q(n) per iteration: 128056 bytes +I(n): 2250.17 flops/byte +W(n): 57629601792.00 flops +T(n): 2895743232.00 cycles +P(n): 19.90 flops/cycle + +=== N_P=5000 N_ITER=200 === +W(n) per iteration: 1800369920.00 flops +Q(n) per iteration: 320056 bytes +I(n): 5625.17 flops/byte +W(n): 360073986048.00 flops +T(n): 18180956160.00 cycles +P(n): 19.81 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 72372396032.00 cycles +P(n): 8.03 flops/cycle + diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved_moreilp/x86/2.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved_moreilp/x86/2.log new file mode 100644 index 0000000..66eac2b --- /dev/null +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved_moreilp/x86/2.log @@ -0,0 +1,64 @@ +=== N_P=50 N_ITER=200 === +W(n) per iteration: 183700.00 flops +Q(n) per iteration: 3256 bytes +I(n): 56.42 flops/byte +W(n): 36740000.00 flops +T(n): 2443465.25 cycles +P(n): 15.04 flops/cycle + +=== N_P=100 N_ITER=200 === +W(n) per iteration: 727400.00 flops +Q(n) per iteration: 6456 bytes +I(n): 112.67 flops/byte +W(n): 145480000.00 flops +T(n): 8370210.00 cycles +P(n): 17.38 flops/cycle + +=== N_P=200 N_ITER=200 === +W(n) per iteration: 2894800.00 flops +Q(n) per iteration: 12856 bytes +I(n): 225.17 flops/byte +W(n): 578960000.00 flops +T(n): 30839560.00 cycles +P(n): 18.77 flops/cycle + +=== N_P=500 N_ITER=200 === +W(n) per iteration: 18037000.00 flops +Q(n) per iteration: 32056 bytes +I(n): 562.67 flops/byte +W(n): 3607399936.00 flops +T(n): 185338336.00 cycles +P(n): 19.46 flops/cycle + +=== N_P=1000 N_ITER=200 === +W(n) per iteration: 72074000.00 flops +Q(n) per iteration: 64056 bytes +I(n): 1125.17 flops/byte +W(n): 14414799872.00 flops +T(n): 737704256.00 cycles +P(n): 19.54 flops/cycle + +=== N_P=2000 N_ITER=200 === +W(n) per iteration: 288148000.00 flops +Q(n) per iteration: 128056 bytes +I(n): 2250.17 flops/byte +W(n): 57629601792.00 flops +T(n): 2915981056.00 cycles +P(n): 19.76 flops/cycle + +=== N_P=5000 N_ITER=200 === +W(n) per iteration: 1800369920.00 flops +Q(n) per iteration: 320056 bytes +I(n): 5625.17 flops/byte +W(n): 360073986048.00 flops +T(n): 18362775552.00 cycles +P(n): 19.61 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 73707225088.00 cycles +P(n): 7.88 flops/cycle + diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved_moreilp/x86/3.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved_moreilp/x86/3.log new file mode 100644 index 0000000..a9c7550 --- /dev/null +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved_moreilp/x86/3.log @@ -0,0 +1,64 @@ +=== N_P=50 N_ITER=200 === +W(n) per iteration: 183700.00 flops +Q(n) per iteration: 3256 bytes +I(n): 56.42 flops/byte +W(n): 36740000.00 flops +T(n): 2445340.00 cycles +P(n): 15.02 flops/cycle + +=== N_P=100 N_ITER=200 === +W(n) per iteration: 727400.00 flops +Q(n) per iteration: 6456 bytes +I(n): 112.67 flops/byte +W(n): 145480000.00 flops +T(n): 8350645.00 cycles +P(n): 17.42 flops/cycle + +=== N_P=200 N_ITER=200 === +W(n) per iteration: 2894800.00 flops +Q(n) per iteration: 12856 bytes +I(n): 225.17 flops/byte +W(n): 578960000.00 flops +T(n): 30609110.00 cycles +P(n): 18.91 flops/cycle + +=== N_P=500 N_ITER=200 === +W(n) per iteration: 18037000.00 flops +Q(n) per iteration: 32056 bytes +I(n): 562.67 flops/byte +W(n): 3607399936.00 flops +T(n): 186796768.00 cycles +P(n): 19.31 flops/cycle + +=== N_P=1000 N_ITER=200 === +W(n) per iteration: 72074000.00 flops +Q(n) per iteration: 64056 bytes +I(n): 1125.17 flops/byte +W(n): 14414799872.00 flops +T(n): 733212800.00 cycles +P(n): 19.66 flops/cycle + +=== N_P=2000 N_ITER=200 === +W(n) per iteration: 288148000.00 flops +Q(n) per iteration: 128056 bytes +I(n): 2250.17 flops/byte +W(n): 57629601792.00 flops +T(n): 2960800768.00 cycles +P(n): 19.46 flops/cycle + +=== N_P=5000 N_ITER=200 === +W(n) per iteration: 1800369920.00 flops +Q(n) per iteration: 320056 bytes +I(n): 5625.17 flops/byte +W(n): 360073986048.00 flops +T(n): 18505687040.00 cycles +P(n): 19.46 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 73613836288.00 cycles +P(n): 7.89 flops/cycle + diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4/x86/1.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4/x86/1.log index 6501532..9eac607 100644 --- a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4/x86/1.log +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4/x86/1.log @@ -1,58 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4 -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 3256 bytes I(n): 56.42 flops/byte W(n): 36740000.00 flops -T(n): 3587017.50 cycles -P(n): 10.24 flops/cycle +T(n): 3897775.00 cycles +P(n): 9.43 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 6456 bytes I(n): 112.67 flops/byte W(n): 145480000.00 flops -T(n): 12215910.00 cycles -P(n): 11.91 flops/cycle +T(n): 13522278.00 cycles +P(n): 10.76 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 12856 bytes I(n): 225.17 flops/byte W(n): 578960000.00 flops -T(n): 44944608.00 cycles -P(n): 12.88 flops/cycle +T(n): 50063060.00 cycles +P(n): 11.56 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 32056 bytes I(n): 562.67 flops/byte W(n): 3607399936.00 flops -T(n): 214169936.00 cycles -P(n): 16.84 flops/cycle +T(n): 240297888.00 cycles +P(n): 15.01 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 64056 bytes I(n): 1125.17 flops/byte W(n): 14414799872.00 flops -T(n): 828421248.00 cycles -P(n): 17.40 flops/cycle +T(n): 942706688.00 cycles +P(n): 15.29 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 128056 bytes I(n): 2250.17 flops/byte W(n): 57629601792.00 flops -T(n): 3268490496.00 cycles -P(n): 17.63 flops/cycle +T(n): 3722795008.00 cycles +P(n): 15.48 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800369920.00 flops Q(n) per iteration: 320056 bytes I(n): 5625.17 flops/byte W(n): 360073986048.00 flops -T(n): 20012742656.00 cycles -P(n): 17.99 flops/cycle +T(n): 22749288448.00 cycles +P(n): 15.83 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 90110476288.00 cycles +P(n): 6.45 flops/cycle diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4/x86/2.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4/x86/2.log index 03e3e9e..e61cf75 100644 --- a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4/x86/2.log +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4/x86/2.log @@ -1,66 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4 -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 3256 bytes I(n): 56.42 flops/byte W(n): 36740000.00 flops -T(n): 3567542.00 cycles -P(n): 10.30 flops/cycle +T(n): 3907767.50 cycles +P(n): 9.40 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 6456 bytes I(n): 112.67 flops/byte W(n): 145480000.00 flops -T(n): 12180789.00 cycles -P(n): 11.94 flops/cycle +T(n): 13510660.00 cycles +P(n): 10.77 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 12856 bytes I(n): 225.17 flops/byte W(n): 578960000.00 flops -T(n): 44522004.00 cycles -P(n): 13.00 flops/cycle +T(n): 50107380.00 cycles +P(n): 11.55 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 32056 bytes I(n): 562.67 flops/byte W(n): 3607399936.00 flops -T(n): 212099104.00 cycles -P(n): 17.01 flops/cycle +T(n): 239951200.00 cycles +P(n): 15.03 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 64056 bytes I(n): 1125.17 flops/byte W(n): 14414799872.00 flops -T(n): 830612480.00 cycles -P(n): 17.35 flops/cycle +T(n): 940302272.00 cycles +P(n): 15.33 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 128056 bytes I(n): 2250.17 flops/byte W(n): 57629601792.00 flops -T(n): 3272956672.00 cycles -P(n): 17.61 flops/cycle +T(n): 3722942720.00 cycles +P(n): 15.48 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800369920.00 flops Q(n) per iteration: 320056 bytes I(n): 5625.17 flops/byte W(n): 360073986048.00 flops -T(n): 20105635840.00 cycles -P(n): 17.91 flops/cycle +T(n): 22711234560.00 cycles +P(n): 15.85 flops/cycle === N_P=10000 N_ITER=200 === W(n) per iteration: 2905772800.00 flops Q(n) per iteration: 640056 bytes I(n): 4539.87 flops/byte W(n): 581154570240.00 flops -T(n): 79669575680.00 cycles -P(n): 7.29 flops/cycle +T(n): 90064855040.00 cycles +P(n): 6.45 flops/cycle diff --git a/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4/x86/3.log b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4/x86/3.log new file mode 100644 index 0000000..98b4ec6 --- /dev/null +++ b/measurements/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4/x86/3.log @@ -0,0 +1,66 @@ +rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o +/usr/bin/g++ main-float.cpp ./variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4_expfix.cpp -o main_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +=== N_P=50 N_ITER=200 === +W(n) per iteration: 183700.00 flops +Q(n) per iteration: 3256 bytes +I(n): 56.42 flops/byte +W(n): 36740000.00 flops +T(n): 3864792.00 cycles +P(n): 9.51 flops/cycle + +=== N_P=100 N_ITER=200 === +W(n) per iteration: 727400.00 flops +Q(n) per iteration: 6456 bytes +I(n): 112.67 flops/byte +W(n): 145480000.00 flops +T(n): 13472545.00 cycles +P(n): 10.80 flops/cycle + +=== N_P=200 N_ITER=200 === +W(n) per iteration: 2894800.00 flops +Q(n) per iteration: 12856 bytes +I(n): 225.17 flops/byte +W(n): 578960000.00 flops +T(n): 49757488.00 cycles +P(n): 11.64 flops/cycle + +=== N_P=500 N_ITER=200 === +W(n) per iteration: 18037000.00 flops +Q(n) per iteration: 32056 bytes +I(n): 562.67 flops/byte +W(n): 3607399936.00 flops +T(n): 238792880.00 cycles +P(n): 15.11 flops/cycle + +=== N_P=1000 N_ITER=200 === +W(n) per iteration: 72074000.00 flops +Q(n) per iteration: 64056 bytes +I(n): 1125.17 flops/byte +W(n): 14414799872.00 flops +T(n): 953924224.00 cycles +P(n): 15.11 flops/cycle + +=== N_P=2000 N_ITER=200 === +W(n) per iteration: 288148000.00 flops +Q(n) per iteration: 128056 bytes +I(n): 2250.17 flops/byte +W(n): 57629601792.00 flops +T(n): 3701525248.00 cycles +P(n): 15.57 flops/cycle + +=== N_P=5000 N_ITER=200 === +W(n) per iteration: 1800369920.00 flops +Q(n) per iteration: 320056 bytes +I(n): 5625.17 flops/byte +W(n): 360073986048.00 flops +T(n): 22775025664.00 cycles +P(n): 15.81 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772800.00 flops +Q(n) per iteration: 640056 bytes +I(n): 4539.87 flops/byte +W(n): 581154570240.00 flops +T(n): 90258751488.00 cycles +P(n): 6.44 flops/cycle + diff --git a/measurements/variant_float_inlining_SoA_NEON_polyexp_moreavx_ilp_2_rsqrt_morersqrt/arm/1.log b/measurements/variant_float_inlining_SoA_NEON_polyexp_moreavx_ilp_2_rsqrt_morersqrt/arm/1.log new file mode 100644 index 0000000..8f7a2a2 --- /dev/null +++ b/measurements/variant_float_inlining_SoA_NEON_polyexp_moreavx_ilp_2_rsqrt_morersqrt/arm/1.log @@ -0,0 +1,58 @@ +rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o +sudo /usr/bin/g++ main-float.cpp ./variants/variant_float_inlining.cpp -o main_float_inlining -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +=== N_P=50 N_ITER=200 === +W(n) per iteration: 183700.00 flops +Q(n) per iteration: 3256 bytes +I(n): 56.42 flops/byte +W(n): 36740000.00 flops +T(n): 10826171.00 cycles +P(n): 3.39 flops/cycle + +=== N_P=100 N_ITER=200 === +W(n) per iteration: 727400.00 flops +Q(n) per iteration: 6456 bytes +I(n): 112.67 flops/byte +W(n): 145480000.00 flops +T(n): 48929320.00 cycles +P(n): 2.97 flops/cycle + +=== N_P=200 N_ITER=200 === +W(n) per iteration: 2894800.00 flops +Q(n) per iteration: 12856 bytes +I(n): 225.17 flops/byte +W(n): 578960000.00 flops +T(n): 190686384.00 cycles +P(n): 3.04 flops/cycle + +=== N_P=500 N_ITER=200 === +W(n) per iteration: 18037000.00 flops +Q(n) per iteration: 32056 bytes +I(n): 562.67 flops/byte +W(n): 3607399936.00 flops +T(n): 1427274624.00 cycles +P(n): 2.53 flops/cycle + +=== N_P=1000 N_ITER=200 === +W(n) per iteration: 72074000.00 flops +Q(n) per iteration: 64056 bytes +I(n): 1125.17 flops/byte +W(n): 14414799872.00 flops +T(n): 6172825600.00 cycles +P(n): 2.34 flops/cycle + +=== N_P=2000 N_ITER=200 === +W(n) per iteration: 288148000.00 flops +Q(n) per iteration: 128056 bytes +I(n): 2250.17 flops/byte +W(n): 57629601792.00 flops +T(n): 27468242944.00 cycles +P(n): 2.10 flops/cycle + +=== N_P=5000 N_ITER=200 === +W(n) per iteration: 1800369920.00 flops +Q(n) per iteration: 320056 bytes +I(n): 5625.17 flops/byte +W(n): 360073986048.00 flops +T(n): 192917569536.00 cycles +P(n): 1.87 flops/cycle + diff --git a/measurements/variant_inlining_7_SoA_AVX2_polyexp/x86/1.log b/measurements/variant_inlining_7_SoA_AVX2_polyexp/x86/1.log index 8a21c6c..7ff1112 100644 --- a/measurements/variant_inlining_7_SoA_AVX2_polyexp/x86/1.log +++ b/measurements/variant_inlining_7_SoA_AVX2_polyexp/x86/1.log @@ -1,58 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main.cpp ./variants/variant_inlining_7_SoA_AVX2_polyexp.cpp -o main_inlining_7_SoA_AVX2_polyexp -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main.cpp ./variants/variant_inlining_7_SoA_AVX2_polyexp_expfix.cpp -o main_inlining_7_SoA_AVX2_polyexp_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 6512 bytes I(n): 28.21 flops/byte W(n): 36740000.00 flops -T(n): 9225415.00 cycles -P(n): 3.98 flops/cycle +T(n): 11371033.75 cycles +P(n): 3.23 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 12912 bytes I(n): 56.34 flops/byte W(n): 145480000.00 flops -T(n): 32320875.00 cycles -P(n): 4.50 flops/cycle +T(n): 39890030.00 cycles +P(n): 3.65 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 25712 bytes I(n): 112.59 flops/byte W(n): 578960000.00 flops -T(n): 122392560.00 cycles -P(n): 4.73 flops/cycle +T(n): 153171560.00 cycles +P(n): 3.78 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 64112 bytes I(n): 281.34 flops/byte W(n): 3607400000.00 flops -T(n): 727457980.00 cycles -P(n): 4.96 flops/cycle +T(n): 926036960.00 cycles +P(n): 3.90 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 128112 bytes I(n): 562.59 flops/byte W(n): 14414800000.00 flops -T(n): 2871839460.00 cycles -P(n): 5.02 flops/cycle +T(n): 3676943300.00 cycles +P(n): 3.92 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 256112 bytes I(n): 1125.09 flops/byte W(n): 57629600000.00 flops -T(n): 11342093520.00 cycles -P(n): 5.08 flops/cycle +T(n): 14545721140.00 cycles +P(n): 3.96 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800370000.00 flops Q(n) per iteration: 640112 bytes I(n): 2812.59 flops/byte W(n): 360074000000.00 flops -T(n): 70407692300.00 cycles -P(n): 5.11 flops/cycle +T(n): 90702048200.00 cycles +P(n): 3.97 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772704.00 flops +Q(n) per iteration: 1280112 bytes +I(n): 2269.94 flops/byte +W(n): 581154540800.00 flops +T(n): 362081083160.00 cycles +P(n): 1.61 flops/cycle diff --git a/measurements/variant_inlining_7_SoA_AVX2_polyexp/x86/2.log b/measurements/variant_inlining_7_SoA_AVX2_polyexp/x86/2.log index 033bc17..f46ef75 100644 --- a/measurements/variant_inlining_7_SoA_AVX2_polyexp/x86/2.log +++ b/measurements/variant_inlining_7_SoA_AVX2_polyexp/x86/2.log @@ -1,66 +1,64 @@ -rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main.cpp ./variants/variant_inlining_7_SoA_AVX2_polyexp.cpp -o main_inlining_7_SoA_AVX2_polyexp -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 6512 bytes I(n): 28.21 flops/byte W(n): 36740000.00 flops -T(n): 9074662.50 cycles -P(n): 4.05 flops/cycle +T(n): 11368170.00 cycles +P(n): 3.23 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 12912 bytes I(n): 56.34 flops/byte W(n): 145480000.00 flops -T(n): 31994315.00 cycles -P(n): 4.55 flops/cycle +T(n): 39909820.00 cycles +P(n): 3.65 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 25712 bytes I(n): 112.59 flops/byte W(n): 578960000.00 flops -T(n): 120234740.00 cycles -P(n): 4.82 flops/cycle +T(n): 152279380.00 cycles +P(n): 3.80 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 64112 bytes I(n): 281.34 flops/byte W(n): 3607400000.00 flops -T(n): 719504200.00 cycles -P(n): 5.01 flops/cycle +T(n): 925130680.00 cycles +P(n): 3.90 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 128112 bytes I(n): 562.59 flops/byte W(n): 14414800000.00 flops -T(n): 2844257700.00 cycles -P(n): 5.07 flops/cycle +T(n): 3668254420.00 cycles +P(n): 3.93 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 256112 bytes I(n): 1125.09 flops/byte W(n): 57629600000.00 flops -T(n): 11300324680.00 cycles -P(n): 5.10 flops/cycle +T(n): 14660040260.00 cycles +P(n): 3.93 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800370000.00 flops Q(n) per iteration: 640112 bytes I(n): 2812.59 flops/byte W(n): 360074000000.00 flops -T(n): 70554568640.00 cycles -P(n): 5.10 flops/cycle +T(n): 93340296780.00 cycles +P(n): 3.86 flops/cycle === N_P=10000 N_ITER=200 === W(n) per iteration: 2905772704.00 flops Q(n) per iteration: 1280112 bytes I(n): 2269.94 flops/byte W(n): 581154540800.00 flops -T(n): 281416807980.00 cycles -P(n): 2.07 flops/cycle +T(n): 362367747120.00 cycles +P(n): 1.60 flops/cycle diff --git a/measurements/variant_inlining_7_SoA_AVX2_polyexp/x86/3.log b/measurements/variant_inlining_7_SoA_AVX2_polyexp/x86/3.log new file mode 100644 index 0000000..25880a8 --- /dev/null +++ b/measurements/variant_inlining_7_SoA_AVX2_polyexp/x86/3.log @@ -0,0 +1,64 @@ +=== N_P=50 N_ITER=200 === +W(n) per iteration: 183700.00 flops +Q(n) per iteration: 6512 bytes +I(n): 28.21 flops/byte +W(n): 36740000.00 flops +T(n): 11342471.25 cycles +P(n): 3.24 flops/cycle + +=== N_P=100 N_ITER=200 === +W(n) per iteration: 727400.00 flops +Q(n) per iteration: 12912 bytes +I(n): 56.34 flops/byte +W(n): 145480000.00 flops +T(n): 40124180.00 cycles +P(n): 3.63 flops/cycle + +=== N_P=200 N_ITER=200 === +W(n) per iteration: 2894800.00 flops +Q(n) per iteration: 25712 bytes +I(n): 112.59 flops/byte +W(n): 578960000.00 flops +T(n): 151911440.00 cycles +P(n): 3.81 flops/cycle + +=== N_P=500 N_ITER=200 === +W(n) per iteration: 18037000.00 flops +Q(n) per iteration: 64112 bytes +I(n): 281.34 flops/byte +W(n): 3607400000.00 flops +T(n): 923357200.00 cycles +P(n): 3.91 flops/cycle + +=== N_P=1000 N_ITER=200 === +W(n) per iteration: 72074000.00 flops +Q(n) per iteration: 128112 bytes +I(n): 562.59 flops/byte +W(n): 14414800000.00 flops +T(n): 3687447740.00 cycles +P(n): 3.91 flops/cycle + +=== N_P=2000 N_ITER=200 === +W(n) per iteration: 288148000.00 flops +Q(n) per iteration: 256112 bytes +I(n): 1125.09 flops/byte +W(n): 57629600000.00 flops +T(n): 14732693600.00 cycles +P(n): 3.91 flops/cycle + +=== N_P=5000 N_ITER=200 === +W(n) per iteration: 1800370000.00 flops +Q(n) per iteration: 640112 bytes +I(n): 2812.59 flops/byte +W(n): 360074000000.00 flops +T(n): 90864696480.00 cycles +P(n): 3.96 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772704.00 flops +Q(n) per iteration: 1280112 bytes +I(n): 2269.94 flops/byte +W(n): 581154540800.00 flops +T(n): 361983172200.00 cycles +P(n): 1.61 flops/cycle + diff --git a/measurements/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt/x86/1.log b/measurements/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt/x86/1.log index b6f19de..b741ee1 100644 --- a/measurements/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt/x86/1.log +++ b/measurements/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt/x86/1.log @@ -1,58 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main.cpp ./variants/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt.cpp -o main_inlining_8_SoA_AVX512_polyexp_fastinvsqrt -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main.cpp ./variants/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_expfix.cpp -o main_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 6512 bytes I(n): 28.21 flops/byte W(n): 36740000.00 flops -T(n): 7287068.75 cycles -P(n): 5.04 flops/cycle +T(n): 8339301.25 cycles +P(n): 4.41 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 12912 bytes I(n): 56.34 flops/byte W(n): 145480000.00 flops -T(n): 24479917.50 cycles -P(n): 5.94 flops/cycle +T(n): 28662660.00 cycles +P(n): 5.08 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 25712 bytes I(n): 112.59 flops/byte W(n): 578960000.00 flops -T(n): 88304220.00 cycles -P(n): 6.56 flops/cycle +T(n): 104402900.00 cycles +P(n): 5.55 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 64112 bytes I(n): 281.34 flops/byte W(n): 3607400000.00 flops -T(n): 532537300.00 cycles -P(n): 6.77 flops/cycle +T(n): 636519040.00 cycles +P(n): 5.67 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 128112 bytes I(n): 562.59 flops/byte W(n): 14414800000.00 flops -T(n): 2074603460.00 cycles -P(n): 6.95 flops/cycle +T(n): 2499027620.00 cycles +P(n): 5.77 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 256112 bytes I(n): 1125.09 flops/byte W(n): 57629600000.00 flops -T(n): 8222911780.00 cycles -P(n): 7.01 flops/cycle +T(n): 9941452140.00 cycles +P(n): 5.80 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800370000.00 flops Q(n) per iteration: 640112 bytes I(n): 2812.59 flops/byte W(n): 360074000000.00 flops -T(n): 51149290420.00 cycles -P(n): 7.04 flops/cycle +T(n): 61650558000.00 cycles +P(n): 5.84 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772704.00 flops +Q(n) per iteration: 1280112 bytes +I(n): 2269.94 flops/byte +W(n): 581154540800.00 flops +T(n): 246792591620.00 cycles +P(n): 2.35 flops/cycle diff --git a/measurements/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt/x86/2.log b/measurements/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt/x86/2.log index 1de959b..5762311 100644 --- a/measurements/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt/x86/2.log +++ b/measurements/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt/x86/2.log @@ -1,66 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main.cpp ./variants/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt.cpp -o main_inlining_8_SoA_AVX512_polyexp_fastinvsqrt -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main.cpp ./variants/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_expfix.cpp -o main_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 6512 bytes I(n): 28.21 flops/byte W(n): 36740000.00 flops -T(n): 7237100.00 cycles -P(n): 5.08 flops/cycle +T(n): 8445907.50 cycles +P(n): 4.35 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 12912 bytes I(n): 56.34 flops/byte W(n): 145480000.00 flops -T(n): 24227557.50 cycles -P(n): 6.00 flops/cycle +T(n): 28691310.00 cycles +P(n): 5.07 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 25712 bytes I(n): 112.59 flops/byte W(n): 578960000.00 flops -T(n): 87321790.00 cycles -P(n): 6.63 flops/cycle +T(n): 104933160.00 cycles +P(n): 5.52 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 64112 bytes I(n): 281.34 flops/byte W(n): 3607400000.00 flops -T(n): 529210780.00 cycles -P(n): 6.82 flops/cycle +T(n): 639568720.00 cycles +P(n): 5.64 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 128112 bytes I(n): 562.59 flops/byte W(n): 14414800000.00 flops -T(n): 2064752120.00 cycles -P(n): 6.98 flops/cycle +T(n): 2515964020.00 cycles +P(n): 5.73 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 256112 bytes I(n): 1125.09 flops/byte W(n): 57629600000.00 flops -T(n): 8154495340.00 cycles -P(n): 7.07 flops/cycle +T(n): 9996713720.00 cycles +P(n): 5.76 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800370000.00 flops Q(n) per iteration: 640112 bytes I(n): 2812.59 flops/byte W(n): 360074000000.00 flops -T(n): 50962729840.00 cycles -P(n): 7.07 flops/cycle +T(n): 62098746740.00 cycles +P(n): 5.80 flops/cycle === N_P=10000 N_ITER=200 === W(n) per iteration: 2905772704.00 flops Q(n) per iteration: 1280112 bytes I(n): 2269.94 flops/byte W(n): 581154540800.00 flops -T(n): 203476930280.00 cycles -P(n): 2.86 flops/cycle +T(n): 247013435860.00 cycles +P(n): 2.35 flops/cycle diff --git a/measurements/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt/x86/3.log b/measurements/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt/x86/3.log new file mode 100644 index 0000000..f95f05f --- /dev/null +++ b/measurements/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt/x86/3.log @@ -0,0 +1,66 @@ +rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o +/usr/bin/g++ main.cpp ./variants/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_expfix.cpp -o main_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +=== N_P=50 N_ITER=200 === +W(n) per iteration: 183700.00 flops +Q(n) per iteration: 6512 bytes +I(n): 28.21 flops/byte +W(n): 36740000.00 flops +T(n): 8335317.50 cycles +P(n): 4.41 flops/cycle + +=== N_P=100 N_ITER=200 === +W(n) per iteration: 727400.00 flops +Q(n) per iteration: 12912 bytes +I(n): 56.34 flops/byte +W(n): 145480000.00 flops +T(n): 28557990.00 cycles +P(n): 5.09 flops/cycle + +=== N_P=200 N_ITER=200 === +W(n) per iteration: 2894800.00 flops +Q(n) per iteration: 25712 bytes +I(n): 112.59 flops/byte +W(n): 578960000.00 flops +T(n): 104404360.00 cycles +P(n): 5.55 flops/cycle + +=== N_P=500 N_ITER=200 === +W(n) per iteration: 18037000.00 flops +Q(n) per iteration: 64112 bytes +I(n): 281.34 flops/byte +W(n): 3607400000.00 flops +T(n): 635858120.00 cycles +P(n): 5.67 flops/cycle + +=== N_P=1000 N_ITER=200 === +W(n) per iteration: 72074000.00 flops +Q(n) per iteration: 128112 bytes +I(n): 562.59 flops/byte +W(n): 14414800000.00 flops +T(n): 2509183840.00 cycles +P(n): 5.74 flops/cycle + +=== N_P=2000 N_ITER=200 === +W(n) per iteration: 288148000.00 flops +Q(n) per iteration: 256112 bytes +I(n): 1125.09 flops/byte +W(n): 57629600000.00 flops +T(n): 9956726160.00 cycles +P(n): 5.79 flops/cycle + +=== N_P=5000 N_ITER=200 === +W(n) per iteration: 1800370000.00 flops +Q(n) per iteration: 640112 bytes +I(n): 2812.59 flops/byte +W(n): 360074000000.00 flops +T(n): 61839346220.00 cycles +P(n): 5.82 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772704.00 flops +Q(n) per iteration: 1280112 bytes +I(n): 2269.94 flops/byte +W(n): 581154540800.00 flops +T(n): 246699025260.00 cycles +P(n): 2.36 flops/cycle + diff --git a/measurements/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr/x86/1.log b/measurements/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr/x86/1.log index d114728..18b6f5f 100644 --- a/measurements/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr/x86/1.log +++ b/measurements/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr/x86/1.log @@ -1,58 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main.cpp ./variants/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr.cpp -o main_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main.cpp ./variants/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr_expfix.cpp -o main_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 6512 bytes I(n): 28.21 flops/byte W(n): 36740000.00 flops -T(n): 7143010.00 cycles -P(n): 5.14 flops/cycle +T(n): 8308587.50 cycles +P(n): 4.42 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 12912 bytes I(n): 56.34 flops/byte W(n): 145480000.00 flops -T(n): 24630712.50 cycles -P(n): 5.91 flops/cycle +T(n): 28404470.00 cycles +P(n): 5.12 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 25712 bytes I(n): 112.59 flops/byte W(n): 578960000.00 flops -T(n): 88030350.00 cycles -P(n): 6.58 flops/cycle +T(n): 103978120.00 cycles +P(n): 5.57 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 64112 bytes I(n): 281.34 flops/byte W(n): 3607400000.00 flops -T(n): 538550140.00 cycles -P(n): 6.70 flops/cycle +T(n): 633362280.00 cycles +P(n): 5.70 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 128112 bytes I(n): 562.59 flops/byte W(n): 14414800000.00 flops -T(n): 2077772880.00 cycles -P(n): 6.94 flops/cycle +T(n): 2494262100.00 cycles +P(n): 5.78 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 256112 bytes I(n): 1125.09 flops/byte W(n): 57629600000.00 flops -T(n): 8277950160.00 cycles -P(n): 6.96 flops/cycle +T(n): 9899453320.00 cycles +P(n): 5.82 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800370000.00 flops Q(n) per iteration: 640112 bytes I(n): 2812.59 flops/byte W(n): 360074000000.00 flops -T(n): 51513976020.00 cycles -P(n): 6.99 flops/cycle +T(n): 61865956520.00 cycles +P(n): 5.82 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772704.00 flops +Q(n) per iteration: 1280112 bytes +I(n): 2269.94 flops/byte +W(n): 581154540800.00 flops +T(n): 246306063920.00 cycles +P(n): 2.36 flops/cycle diff --git a/measurements/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr/x86/2.log b/measurements/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr/x86/2.log index c0dc82b..1653c69 100644 --- a/measurements/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr/x86/2.log +++ b/measurements/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr/x86/2.log @@ -1,66 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main.cpp ./variants/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr.cpp -o main_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main.cpp ./variants/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr_expfix.cpp -o main_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 6512 bytes I(n): 28.21 flops/byte W(n): 36740000.00 flops -T(n): 7224345.00 cycles -P(n): 5.09 flops/cycle +T(n): 8344811.25 cycles +P(n): 4.40 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 12912 bytes I(n): 56.34 flops/byte W(n): 145480000.00 flops -T(n): 24323830.00 cycles -P(n): 5.98 flops/cycle +T(n): 28520365.00 cycles +P(n): 5.10 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 25712 bytes I(n): 112.59 flops/byte W(n): 578960000.00 flops -T(n): 87541580.00 cycles -P(n): 6.61 flops/cycle +T(n): 104404120.00 cycles +P(n): 5.55 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 64112 bytes I(n): 281.34 flops/byte W(n): 3607400000.00 flops -T(n): 540497680.00 cycles -P(n): 6.67 flops/cycle +T(n): 636400560.00 cycles +P(n): 5.67 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 128112 bytes I(n): 562.59 flops/byte W(n): 14414800000.00 flops -T(n): 2069077440.00 cycles -P(n): 6.97 flops/cycle +T(n): 2501258800.00 cycles +P(n): 5.76 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 256112 bytes I(n): 1125.09 flops/byte W(n): 57629600000.00 flops -T(n): 8259242740.00 cycles -P(n): 6.98 flops/cycle +T(n): 9901533780.00 cycles +P(n): 5.82 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800370000.00 flops Q(n) per iteration: 640112 bytes I(n): 2812.59 flops/byte W(n): 360074000000.00 flops -T(n): 51381444880.00 cycles -P(n): 7.01 flops/cycle +T(n): 61815669960.00 cycles +P(n): 5.82 flops/cycle === N_P=10000 N_ITER=200 === W(n) per iteration: 2905772704.00 flops Q(n) per iteration: 1280112 bytes I(n): 2269.94 flops/byte W(n): 581154540800.00 flops -T(n): 205008714840.00 cycles -P(n): 2.83 flops/cycle +T(n): 247091597180.00 cycles +P(n): 2.35 flops/cycle diff --git a/measurements/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr/x86/3.log b/measurements/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr/x86/3.log new file mode 100644 index 0000000..a60b0dc --- /dev/null +++ b/measurements/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr/x86/3.log @@ -0,0 +1,66 @@ +rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o +/usr/bin/g++ main.cpp ./variants/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr_expfix.cpp -o main_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +=== N_P=50 N_ITER=200 === +W(n) per iteration: 183700.00 flops +Q(n) per iteration: 6512 bytes +I(n): 28.21 flops/byte +W(n): 36740000.00 flops +T(n): 8321530.00 cycles +P(n): 4.42 flops/cycle + +=== N_P=100 N_ITER=200 === +W(n) per iteration: 727400.00 flops +Q(n) per iteration: 12912 bytes +I(n): 56.34 flops/byte +W(n): 145480000.00 flops +T(n): 28458355.00 cycles +P(n): 5.11 flops/cycle + +=== N_P=200 N_ITER=200 === +W(n) per iteration: 2894800.00 flops +Q(n) per iteration: 25712 bytes +I(n): 112.59 flops/byte +W(n): 578960000.00 flops +T(n): 104209360.00 cycles +P(n): 5.56 flops/cycle + +=== N_P=500 N_ITER=200 === +W(n) per iteration: 18037000.00 flops +Q(n) per iteration: 64112 bytes +I(n): 281.34 flops/byte +W(n): 3607400000.00 flops +T(n): 634333640.00 cycles +P(n): 5.69 flops/cycle + +=== N_P=1000 N_ITER=200 === +W(n) per iteration: 72074000.00 flops +Q(n) per iteration: 128112 bytes +I(n): 562.59 flops/byte +W(n): 14414800000.00 flops +T(n): 2496796020.00 cycles +P(n): 5.77 flops/cycle + +=== N_P=2000 N_ITER=200 === +W(n) per iteration: 288148000.00 flops +Q(n) per iteration: 256112 bytes +I(n): 1125.09 flops/byte +W(n): 57629600000.00 flops +T(n): 9914787460.00 cycles +P(n): 5.81 flops/cycle + +=== N_P=5000 N_ITER=200 === +W(n) per iteration: 1800370000.00 flops +Q(n) per iteration: 640112 bytes +I(n): 2812.59 flops/byte +W(n): 360074000000.00 flops +T(n): 61721090840.00 cycles +P(n): 5.83 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772704.00 flops +Q(n) per iteration: 1280112 bytes +I(n): 2269.94 flops/byte +W(n): 581154540800.00 flops +T(n): 246519066200.00 cycles +P(n): 2.36 flops/cycle + diff --git a/measurements/variant_inlining_8_SoA_AVX512_polyexp_moreavx/x86/1.log b/measurements/variant_inlining_8_SoA_AVX512_polyexp_moreavx/x86/1.log index e886877..c33cf4f 100644 --- a/measurements/variant_inlining_8_SoA_AVX512_polyexp_moreavx/x86/1.log +++ b/measurements/variant_inlining_8_SoA_AVX512_polyexp_moreavx/x86/1.log @@ -1,58 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main.cpp ./variants/variant_inlining_8_SoA_AVX512_polyexp_moreavx.cpp -o main_inlining_8_SoA_AVX512_polyexp_moreavx -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main.cpp ./variants/variant_inlining_8_SoA_AVX512_polyexp_moreavx_expfix.cpp -o main_inlining_8_SoA_AVX512_polyexp_moreavx_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 6512 bytes I(n): 28.21 flops/byte W(n): 36740000.00 flops -T(n): 6876013.75 cycles -P(n): 5.34 flops/cycle +T(n): 7985528.75 cycles +P(n): 4.60 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 12912 bytes I(n): 56.34 flops/byte W(n): 145480000.00 flops -T(n): 23521667.50 cycles -P(n): 6.18 flops/cycle +T(n): 27703355.00 cycles +P(n): 5.25 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 25712 bytes I(n): 112.59 flops/byte W(n): 578960000.00 flops -T(n): 85927760.00 cycles -P(n): 6.74 flops/cycle +T(n): 102292560.00 cycles +P(n): 5.66 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 64112 bytes I(n): 281.34 flops/byte W(n): 3607400000.00 flops -T(n): 524078060.00 cycles -P(n): 6.88 flops/cycle +T(n): 629804220.00 cycles +P(n): 5.73 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 128112 bytes I(n): 562.59 flops/byte W(n): 14414800000.00 flops -T(n): 2052525500.00 cycles -P(n): 7.02 flops/cycle +T(n): 2472263180.00 cycles +P(n): 5.83 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 256112 bytes I(n): 1125.09 flops/byte W(n): 57629600000.00 flops -T(n): 8210618700.00 cycles -P(n): 7.02 flops/cycle +T(n): 9851588140.00 cycles +P(n): 5.85 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800370000.00 flops Q(n) per iteration: 640112 bytes I(n): 2812.59 flops/byte W(n): 360074000000.00 flops -T(n): 50972389900.00 cycles -P(n): 7.06 flops/cycle +T(n): 61479499820.00 cycles +P(n): 5.86 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772704.00 flops +Q(n) per iteration: 1280112 bytes +I(n): 2269.94 flops/byte +W(n): 581154540800.00 flops +T(n): 245617006060.00 cycles +P(n): 2.37 flops/cycle diff --git a/measurements/variant_inlining_8_SoA_AVX512_polyexp_moreavx/x86/2.log b/measurements/variant_inlining_8_SoA_AVX512_polyexp_moreavx/x86/2.log index 27bc43b..5ee8171 100644 --- a/measurements/variant_inlining_8_SoA_AVX512_polyexp_moreavx/x86/2.log +++ b/measurements/variant_inlining_8_SoA_AVX512_polyexp_moreavx/x86/2.log @@ -1,66 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main.cpp ./variants/variant_inlining_8_SoA_AVX512_polyexp_moreavx.cpp -o main_inlining_8_SoA_AVX512_polyexp_moreavx -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main.cpp ./variants/variant_inlining_8_SoA_AVX512_polyexp_moreavx_expfix.cpp -o main_inlining_8_SoA_AVX512_polyexp_moreavx_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 6512 bytes I(n): 28.21 flops/byte W(n): 36740000.00 flops -T(n): 6880311.25 cycles -P(n): 5.34 flops/cycle +T(n): 8028216.25 cycles +P(n): 4.58 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 12912 bytes I(n): 56.34 flops/byte W(n): 145480000.00 flops -T(n): 23463525.00 cycles -P(n): 6.20 flops/cycle +T(n): 27833730.00 cycles +P(n): 5.23 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 25712 bytes I(n): 112.59 flops/byte W(n): 578960000.00 flops -T(n): 85995280.00 cycles -P(n): 6.73 flops/cycle +T(n): 102829680.00 cycles +P(n): 5.63 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 64112 bytes I(n): 281.34 flops/byte W(n): 3607400000.00 flops -T(n): 521810900.00 cycles -P(n): 6.91 flops/cycle +T(n): 629698060.00 cycles +P(n): 5.73 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 128112 bytes I(n): 562.59 flops/byte W(n): 14414800000.00 flops -T(n): 2070674920.00 cycles -P(n): 6.96 flops/cycle +T(n): 2469782600.00 cycles +P(n): 5.84 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 256112 bytes I(n): 1125.09 flops/byte W(n): 57629600000.00 flops -T(n): 8150338100.00 cycles -P(n): 7.07 flops/cycle +T(n): 9826240720.00 cycles +P(n): 5.86 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800370000.00 flops Q(n) per iteration: 640112 bytes I(n): 2812.59 flops/byte W(n): 360074000000.00 flops -T(n): 50841614020.00 cycles -P(n): 7.08 flops/cycle +T(n): 61490138600.00 cycles +P(n): 5.86 flops/cycle === N_P=10000 N_ITER=200 === W(n) per iteration: 2905772704.00 flops Q(n) per iteration: 1280112 bytes I(n): 2269.94 flops/byte W(n): 581154540800.00 flops -T(n): 202898659340.00 cycles -P(n): 2.86 flops/cycle +T(n): 245848977420.00 cycles +P(n): 2.36 flops/cycle diff --git a/measurements/variant_inlining_8_SoA_AVX512_polyexp_moreavx/x86/3.log b/measurements/variant_inlining_8_SoA_AVX512_polyexp_moreavx/x86/3.log new file mode 100644 index 0000000..27a1fc5 --- /dev/null +++ b/measurements/variant_inlining_8_SoA_AVX512_polyexp_moreavx/x86/3.log @@ -0,0 +1,66 @@ +rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o +/usr/bin/g++ main.cpp ./variants/variant_inlining_8_SoA_AVX512_polyexp_moreavx_expfix.cpp -o main_inlining_8_SoA_AVX512_polyexp_moreavx_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +=== N_P=50 N_ITER=200 === +W(n) per iteration: 183700.00 flops +Q(n) per iteration: 6512 bytes +I(n): 28.21 flops/byte +W(n): 36740000.00 flops +T(n): 7992830.00 cycles +P(n): 4.60 flops/cycle + +=== N_P=100 N_ITER=200 === +W(n) per iteration: 727400.00 flops +Q(n) per iteration: 12912 bytes +I(n): 56.34 flops/byte +W(n): 145480000.00 flops +T(n): 27693680.00 cycles +P(n): 5.25 flops/cycle + +=== N_P=200 N_ITER=200 === +W(n) per iteration: 2894800.00 flops +Q(n) per iteration: 25712 bytes +I(n): 112.59 flops/byte +W(n): 578960000.00 flops +T(n): 102340840.00 cycles +P(n): 5.66 flops/cycle + +=== N_P=500 N_ITER=200 === +W(n) per iteration: 18037000.00 flops +Q(n) per iteration: 64112 bytes +I(n): 281.34 flops/byte +W(n): 3607400000.00 flops +T(n): 638328340.00 cycles +P(n): 5.65 flops/cycle + +=== N_P=1000 N_ITER=200 === +W(n) per iteration: 72074000.00 flops +Q(n) per iteration: 128112 bytes +I(n): 562.59 flops/byte +W(n): 14414800000.00 flops +T(n): 2468865800.00 cycles +P(n): 5.84 flops/cycle + +=== N_P=2000 N_ITER=200 === +W(n) per iteration: 288148000.00 flops +Q(n) per iteration: 256112 bytes +I(n): 1125.09 flops/byte +W(n): 57629600000.00 flops +T(n): 9838254540.00 cycles +P(n): 5.86 flops/cycle + +=== N_P=5000 N_ITER=200 === +W(n) per iteration: 1800370000.00 flops +Q(n) per iteration: 640112 bytes +I(n): 2812.59 flops/byte +W(n): 360074000000.00 flops +T(n): 61344519940.00 cycles +P(n): 5.87 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772704.00 flops +Q(n) per iteration: 1280112 bytes +I(n): 2269.94 flops/byte +W(n): 581154540800.00 flops +T(n): 245174501540.00 cycles +P(n): 2.37 flops/cycle + diff --git a/measurements/variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2/x86/1.log b/measurements/variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2/x86/1.log index 24e4936..7a9a201 100644 --- a/measurements/variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2/x86/1.log +++ b/measurements/variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2/x86/1.log @@ -1,58 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main.cpp ./variants/variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2.cpp -o main_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2 -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main.cpp ./variants/variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2_expfix.cpp -o main_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 6512 bytes I(n): 28.21 flops/byte W(n): 36740000.00 flops -T(n): 7796687.50 cycles -P(n): 4.71 flops/cycle +T(n): 8506121.25 cycles +P(n): 4.32 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 12912 bytes I(n): 56.34 flops/byte W(n): 145480000.00 flops -T(n): 25453505.00 cycles -P(n): 5.72 flops/cycle +T(n): 27681145.00 cycles +P(n): 5.26 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 25712 bytes I(n): 112.59 flops/byte W(n): 578960000.00 flops -T(n): 90370870.00 cycles -P(n): 6.41 flops/cycle +T(n): 98048030.00 cycles +P(n): 5.90 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 64112 bytes I(n): 281.34 flops/byte W(n): 3607400000.00 flops -T(n): 538274500.00 cycles -P(n): 6.70 flops/cycle +T(n): 594320700.00 cycles +P(n): 6.07 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 128112 bytes I(n): 562.59 flops/byte W(n): 14414800000.00 flops -T(n): 2095953220.00 cycles -P(n): 6.88 flops/cycle +T(n): 2270890500.00 cycles +P(n): 6.35 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 256112 bytes I(n): 1125.09 flops/byte W(n): 57629600000.00 flops -T(n): 8248614920.00 cycles -P(n): 6.99 flops/cycle +T(n): 8985906260.00 cycles +P(n): 6.41 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800370000.00 flops Q(n) per iteration: 640112 bytes I(n): 2812.59 flops/byte W(n): 360074000000.00 flops -T(n): 51762509580.00 cycles -P(n): 6.96 flops/cycle +T(n): 56358587540.00 cycles +P(n): 6.39 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772704.00 flops +Q(n) per iteration: 1280112 bytes +I(n): 2269.94 flops/byte +W(n): 581154540800.00 flops +T(n): 224065475420.00 cycles +P(n): 2.59 flops/cycle diff --git a/measurements/variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2/x86/2.log b/measurements/variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2/x86/2.log index 658682f..e6443dc 100644 --- a/measurements/variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2/x86/2.log +++ b/measurements/variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2/x86/2.log @@ -1,66 +1,66 @@ rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o -/usr/bin/g++ main.cpp ./variants/variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2.cpp -o main_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2 -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +/usr/bin/g++ main.cpp ./variants/variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2_expfix.cpp -o main_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 === N_P=50 N_ITER=200 === W(n) per iteration: 183700.00 flops Q(n) per iteration: 6512 bytes I(n): 28.21 flops/byte W(n): 36740000.00 flops -T(n): 7778888.75 cycles -P(n): 4.72 flops/cycle +T(n): 8512763.75 cycles +P(n): 4.32 flops/cycle === N_P=100 N_ITER=200 === W(n) per iteration: 727400.00 flops Q(n) per iteration: 12912 bytes I(n): 56.34 flops/byte W(n): 145480000.00 flops -T(n): 25303990.00 cycles -P(n): 5.75 flops/cycle +T(n): 27679115.00 cycles +P(n): 5.26 flops/cycle === N_P=200 N_ITER=200 === W(n) per iteration: 2894800.00 flops Q(n) per iteration: 25712 bytes I(n): 112.59 flops/byte W(n): 578960000.00 flops -T(n): 89661540.00 cycles -P(n): 6.46 flops/cycle +T(n): 98109310.00 cycles +P(n): 5.90 flops/cycle === N_P=500 N_ITER=200 === W(n) per iteration: 18037000.00 flops Q(n) per iteration: 64112 bytes I(n): 281.34 flops/byte W(n): 3607400000.00 flops -T(n): 534011120.00 cycles -P(n): 6.76 flops/cycle +T(n): 583896260.00 cycles +P(n): 6.18 flops/cycle === N_P=1000 N_ITER=200 === W(n) per iteration: 72074000.00 flops Q(n) per iteration: 128112 bytes I(n): 562.59 flops/byte W(n): 14414800000.00 flops -T(n): 2077751560.00 cycles -P(n): 6.94 flops/cycle +T(n): 2292138700.00 cycles +P(n): 6.29 flops/cycle === N_P=2000 N_ITER=200 === W(n) per iteration: 288148000.00 flops Q(n) per iteration: 256112 bytes I(n): 1125.09 flops/byte W(n): 57629600000.00 flops -T(n): 8233407040.00 cycles -P(n): 7.00 flops/cycle +T(n): 9006037600.00 cycles +P(n): 6.40 flops/cycle === N_P=5000 N_ITER=200 === W(n) per iteration: 1800370000.00 flops Q(n) per iteration: 640112 bytes I(n): 2812.59 flops/byte W(n): 360074000000.00 flops -T(n): 51189403060.00 cycles -P(n): 7.03 flops/cycle +T(n): 56211721500.00 cycles +P(n): 6.41 flops/cycle === N_P=10000 N_ITER=200 === W(n) per iteration: 2905772704.00 flops Q(n) per iteration: 1280112 bytes I(n): 2269.94 flops/byte W(n): 581154540800.00 flops -T(n): 204461065180.00 cycles -P(n): 2.84 flops/cycle +T(n): 223879818840.00 cycles +P(n): 2.60 flops/cycle diff --git a/measurements/variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2/x86/3.log b/measurements/variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2/x86/3.log new file mode 100644 index 0000000..c702109 --- /dev/null +++ b/measurements/variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2/x86/3.log @@ -0,0 +1,66 @@ +rm -f main_* run_tests *.o *.s variants/*.s variants/*.o headers/*.s headers/*.o +/usr/bin/g++ main.cpp ./variants/variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2_expfix.cpp -o main_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2_expfix -O3 -march=native -std=c++23 -Wall -Wextra -flto -DFLOPCOUNT=0 -DRANDOM_SEED=0 -DROOFLINE=0 -DBENCHMARK=1 +=== N_P=50 N_ITER=200 === +W(n) per iteration: 183700.00 flops +Q(n) per iteration: 6512 bytes +I(n): 28.21 flops/byte +W(n): 36740000.00 flops +T(n): 8550285.00 cycles +P(n): 4.30 flops/cycle + +=== N_P=100 N_ITER=200 === +W(n) per iteration: 727400.00 flops +Q(n) per iteration: 12912 bytes +I(n): 56.34 flops/byte +W(n): 145480000.00 flops +T(n): 27834905.00 cycles +P(n): 5.23 flops/cycle + +=== N_P=200 N_ITER=200 === +W(n) per iteration: 2894800.00 flops +Q(n) per iteration: 25712 bytes +I(n): 112.59 flops/byte +W(n): 578960000.00 flops +T(n): 98660270.00 cycles +P(n): 5.87 flops/cycle + +=== N_P=500 N_ITER=200 === +W(n) per iteration: 18037000.00 flops +Q(n) per iteration: 64112 bytes +I(n): 281.34 flops/byte +W(n): 3607400000.00 flops +T(n): 587210580.00 cycles +P(n): 6.14 flops/cycle + +=== N_P=1000 N_ITER=200 === +W(n) per iteration: 72074000.00 flops +Q(n) per iteration: 128112 bytes +I(n): 562.59 flops/byte +W(n): 14414800000.00 flops +T(n): 2280133880.00 cycles +P(n): 6.32 flops/cycle + +=== N_P=2000 N_ITER=200 === +W(n) per iteration: 288148000.00 flops +Q(n) per iteration: 256112 bytes +I(n): 1125.09 flops/byte +W(n): 57629600000.00 flops +T(n): 8974668040.00 cycles +P(n): 6.42 flops/cycle + +=== N_P=5000 N_ITER=200 === +W(n) per iteration: 1800370000.00 flops +Q(n) per iteration: 640112 bytes +I(n): 2812.59 flops/byte +W(n): 360074000000.00 flops +T(n): 56052905260.00 cycles +P(n): 6.42 flops/cycle + +=== N_P=10000 N_ITER=200 === +W(n) per iteration: 2905772704.00 flops +Q(n) per iteration: 1280112 bytes +I(n): 2269.94 flops/byte +W(n): 581154540800.00 flops +T(n): 224433219680.00 cycles +P(n): 2.59 flops/cycle + diff --git a/variants/variant_branchless_flopcount.cpp b/variants/variant_branchless_flopcount.cpp deleted file mode 100644 index d903659..0000000 --- a/variants/variant_branchless_flopcount.cpp +++ /dev/null @@ -1,426 +0,0 @@ -// This file is merged from the forces.cpp and social_forces_baseline.cpp -// The goal is that we from now on only have one file as our baseline -// This should make it more easy in the future to implement optimizations -// Our naming convention from now on is: variant_.cpp (Please make sure to keep that consistent, otherwise our Makefile wont work anymore) - -// # Changes: FLOPCOUNT -// # Predecessor: variant_branchless.cpp - -// n_iter * [n_p ** 2 * (15 A + 24 M + 1 D + 4 S + 1 E) + n_p * (- 4 A - 4 M + 1 D - 1 S - 1 E) + n_obstacles * n_p * (13 A + 19 M + 1 D + 2 S + 1 E)] - - - -#include "../headers/board.hpp" -#include "../headers/constants.hpp" -#include "../headers/forces.hpp" -#include "../headers/pedestrian.hpp" -#include "../headers/social_force.hpp" -#include "../headers/vector2d.hpp" - -#include -#include -#include -#include -#include // keep — forces code uses unqualified sqrt/exp -#include -#include -#include - -#define SEED 42 -#define BOARD_WIDTH 10.0 -#define BOARD_LENGTH 50.0 -#define WALL_EPS 1e-3 -#define BOARD_WIDTH_MINUS_WALL_EPS 9.999 - -#ifndef RANDOM_SEED -#define RANDOM_SEED 0 -#endif - -#ifndef BENCHMARK -#define BENCHMARK 0 -#endif - -using namespace std; - -// forces.cpp - -// Flop count: 3 ADDs, 6 MULTs, 1 SQRT -double w(Vector2d e, Vector2d f) { - - // 1 ADD + 2 MULT - double dot = e.dot(f); - // 1 ADD + 2 MULT + 1 SQRT - double f_norm = f.norm(); - // 1 MULT - double cond = (double)(dot >= f_norm * cos_phi); // Should be 1 if in the field of view, else 0 - // 1 ADD + 1 MULT - return c_neg_times_dt + cond * (dt_neg - c_neg_times_dt); -} - -// Flop count: 2 ADDs, 4 MULTs -Vector2d acceleration_term_dt(const Pedestrian &alpha) { - - // # 2 MULTs - Vector2d desired_velocity = alpha.e * alpha.desired_v0; - - Vector2d actual_velocity = alpha.curr_vel; - - // # 2 ADDs, 2 MULTs - Vector2d f_alpha_0_dt = (desired_velocity - actual_velocity) * dt_times_tau_alpha_inv; - - return f_alpha_0_dt; -} - -// Flop count: 13 ADDs, 24 MULTs, 1 DIV, 4 SQRTs, 1 EXP -Vector2d pedestrian_repulsion_dt(const Pedestrian &alpha, const Pedestrian &beta) { - - // # 2 ADDs - // $\vec{r}_{\alpha\beta}$ - Vector2d r_ab = alpha.curr_pos - beta.curr_pos; - - // # 1 ADD, 2 MULTs, 1 SQRT - // $\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert$ - double r_ab_norm = r_ab.norm(); - r_ab_norm = r_ab_norm > EPS ? r_ab_norm : EPS; // Avoid division by zero - - // $v_\beta \Delta t \vec{e}_\beta$ - Vector2d s_b_e = beta.s_b_e; - - // # 2 ADDs - // $\vec{r}_{\alpha\beta} - \vec{v}_{\beta}\varDelta_{t}\vec{e}_{\beta}$ - Vector2d r_ab2 = r_ab - s_b_e; - - // # 1 ADD, 2 MULTs, 1 SQRT - // $\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert$ - double r_ab2_norm = r_ab2.norm(); - r_ab2_norm = r_ab2_norm > EPS ? r_ab2_norm : EPS; // Avoid division by zero - - // # 1 ADD - // $\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert$ - double r_ab_norm_sum = r_ab_norm + r_ab2_norm; - - // # 1 ADD, 1 MULTs, 1 SQRT - // - // $2b = \sqrt{(\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert)^2 - (v_\beta \Delta t)^2}$ - // - double two_b_sq = r_ab_norm_sum * r_ab_norm_sum - beta.s_b_sq; - two_b_sq = two_b_sq > EPS_SQ ? two_b_sq : EPS_SQ; // Avoid sqrt of negative and avoid division by zero - double two_b = sqrt(two_b_sq); - - // # 5 MULTs, 1 DIV, 1 EXP - // - // $\frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert\,\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}$ - // - double scalar_mult_common = (r_ab_norm_sum / (two_b * r_ab_norm * r_ab2_norm)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b * NEG_TWO_SIGMA_INV)); - - // # 1 MULT - // - // $\frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert}$ - // - double scalar_mult_r_ab = scalar_mult_common * r_ab2_norm; - - // # 1 MULT - // - // $\frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}$ - // - double scalar_mult_r_ab2 = scalar_mult_common * r_ab_norm; - - // # 2 ADDs, 4 MULTs - // - // $\vec{-f}_{\alpha \beta}(\vec{r}_{\alpha \beta}) = \frac{-V^0_{\alpha \beta}}{2\sigma}e^{-b / \sigma} 2\grad_{\vec{r}_{\alpha \beta}}b $ - // - // - // $= \frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert}\,\vec{r}_{\alpha \beta} + \frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} - - // v_\beta \Delta t \vec{e}_\beta \Arrowvert}\,(\vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta)$ - // - // - // - // $2\grad_{\vec{r}_{\alpha \beta}}b = \frac{(\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert)(\frac{\vec{r}_{\alpha \beta}}{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert} + \frac{\vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta}{\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert})}{2b}$ - // - // - // $= \frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert}\,\vec{r}_{\alpha \beta} + \frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}\,(\vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta)$ - // - // - Vector2d f_alpha_beta_neg = r_ab * scalar_mult_r_ab + r_ab2 * scalar_mult_r_ab2; - - // # 3 ADDs, 8 MULTs, 1 SQRT - // - // $\vec{F}_{\alpha\beta}(\vec{e}_{\alpha}, \vec{r}_{\alpha \beta}).dt = w(\vec{e}_{\alpha}, -\vec{f}_{\alpha\beta}(\vec{r}_{\alpha \beta})).\vec{f}_{\alpha\beta}(\vec{r}_{\alpha \beta}).dt$ - // - Vector2d f_alpha_beta_dt = f_alpha_beta_neg * w(alpha.e, f_alpha_beta_neg); - - return f_alpha_beta_dt; -} - -// Flop count: 11 ADDs, 19 MULTs, 1 DIVs, 2 SQRTs, 1 EXP -Vector2d obstacle_repulsion_dt(const Pedestrian &alpha, const Obstacle &B) { - - // # 7 ADDs, 5 MULTs - // $\vec{r}_{\alpha B}$ - Vector2d r_aB = alpha.curr_pos - B.find_nearest_obstacle_point(alpha.curr_pos); - - // # 1 ADD, 2 MULTs, 1 SQRT - // $\Arrowvert \vec{r}_{\alpha B} \Arrowvert$ - double r_aB_norm = r_aB.norm(); - r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; // Avoid division by zero - - // # 2 MULTs, 1 DIV, 1 EXP - // - // $\frac{-U^0_{\alpha B}}{R} e^{- \Arrowvert \vec{r}_{\alpha B} \Arrowvert / R}$ - // - double scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; - - // # 2 MULTs - // - // $-\vec{F}_{\alpha B}(\vec{r}_{\alpha B}) = \frac{-U^0_{\alpha B}}{R} e^{- \Arrowvert \vec{r}_{\alpha B} \Arrowvert / R} \frac{\vec{r}_{\alpha B}}{\Arrowvert \vec{r}_{\alpha B} \Arrowvert}$ - // - Vector2d f_alpha_B_neg = r_aB * scalar_mult; - - // # 3 ADDs, 8 MULTs, 1 SQRT - // - // $\vec{F}_{\alpha B}(\vec{e}_{\alpha}, \vec{r}_{\alpha B}).dt = w(\vec{e}_{\alpha}, -\vec{F}_{\alpha B}(\vec{r}_{\alpha B})).\vec{F}_{\alpha B}(\vec{r}_{\alpha B}).dt$ - // - Vector2d f_alpha_B_dt = f_alpha_B_neg * w(alpha.e, f_alpha_B_neg); - - return f_alpha_B_dt; -} - -// social_force_baseline.cpp - -Pedestrian *init_pedestrians(int n_p) { -#if RANDOM_SEED - random_device rd; // Platform-provided random seed source. - mt19937 gen(rd()); // Non-reproducible initialization. -#else - mt19937 gen(SEED); // Reproducible initialization. -#endif - - normal_distribution velocity_gen(v0_mean, v0_std_dev); - uniform_real_distribution y_gen(0.3, BOARD_WIDTH - 0.3); - uniform_real_distribution x_gen_left(2.0, BOARD_LENGTH / 2.0); - uniform_real_distribution x_gen_right(BOARD_LENGTH / 2.0, BOARD_LENGTH - 2.0); - - Pedestrian *P = new Pedestrian[n_p]; - - int n_p_half = n_p / 2; - - // Group of pedestrians walking from left to right. - for (int i = 0; i < n_p_half; i++) { - double x = x_gen_left(gen); - double y = y_gen(gen); - - Vector2d start_pos = Vector2d(x, y); - Vector2d destination = Vector2d(BOARD_LENGTH + 30.0, y); - - Vector2d init_e = destination - start_pos; - double init_e_norm = init_e.norm(); - Vector2d init_e_unit = init_e / init_e_norm; - - // Reject near-zero desired speeds to avoid pedestrians that barely move, - // and reject negative speeds because they would reverse the intended - // walking direction. - double desired_v0; - do { - desired_v0 = velocity_gen(gen); - } while (desired_v0 <= 0.1); - - double v_max = 1.3 * desired_v0; - - P[i] = Pedestrian(WHITE, Vector2d(), start_pos, init_e_unit, v_max, desired_v0, destination); - } - - // Group of pedestrians walking from right to left. - for (int i = n_p_half; i < n_p; i++) { - double x = x_gen_right(gen); - double y = y_gen(gen); - - Vector2d start_pos = Vector2d(x, y); - Vector2d destination = Vector2d(-30.0, y); - - Vector2d init_e = destination - start_pos; - double init_e_norm = init_e.norm(); - Vector2d init_e_unit = init_e / init_e_norm; - - // Reject near-zero desired speeds to avoid pedestrians that barely move, - // and reject negative speeds because they would reverse the intended - // walking direction. - double desired_v0; - do { - desired_v0 = velocity_gen(gen); - } while (desired_v0 <= 0.1); - - double v_max = 1.3 * desired_v0; - - P[i] = Pedestrian(BLACK, Vector2d(), start_pos, init_e_unit, v_max, desired_v0, destination); - } - - return P; -} - -Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } - -int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { - -#if BENCHMARK - // Avoid compiler unused parameter warning - (void)dump_path; -#endif - -#if !BENCHMARK - const int dump_interval = 1; - - // Each sample stores: time step, pedestrian id, x, y, e.x, e.y, color. - vector> samples; - - if (dump_path) { - samples.reserve(static_cast(n_iter / dump_interval + 1) * n_p); - - // Store the initial state before the first simulation step. - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - samples.emplace_back(0, i, p.curr_pos.x, p.curr_pos.y, p.e.x, p.e.y, p.color); - } - } -#endif - - // n_iter * [ {n_p * {[(n_p - 1) * (13 ADDs, 24 MULTs, 1 DIV, 4 SQRTs, 1 EXP + 2 ADDs)] + [2 ADD + 4 MULT + (n_obstacles * (11 ADDs, 19 MULTs, 1 DIV, 2 SQRTs, 1 EXP) + n_obstacles * 2 ADDs) + 2 ADD ]}} + {(7 ADDs, 16 MULTs, 2 DIVs, 3 SQRTs) * n_p} ] - // n_iter * [ {n_p * {[(n_p - 1) * (13 A + 24 M + 1 D + 4 S + 1 E + 2 A)] + [2 A + 4 M + (n_obstacles * (11 A + 19 M + 1 D + 2 S + 1 E) + n_obstacles * 2 A) + 2 A ]}} + {n_p * (7 A + 16 M + 2 D + 3 S)} ] - // n_iter * [n_p ** 2 * (15 A + 24 M + 1 D + 4 S + 1 E) + n_p * (- 11 A - 20 M - 1 D - 4 S - 1 E) + n_obstacles * n_p * (13 A + 19 M + 1 D + 2 S + 1 E) + n_p * (7 A + 16 M + 2 D + 3 S)] - // n_iter * [n_p ** 2 * (15 A + 24 M + 1 D + 4 S + 1 E) + n_p * (- 11 A - 20 M - 1 D - 4 S - 1 E) + n_p * (7 A + 16 M + 2 D + 3 S) + n_obstacles * n_p * (13 A + 19 M + 1 D + 2 S + 1 E)] - // n_iter * [n_p ** 2 * (15 A + 24 M + 1 D + 4 S + 1 E) + n_p * (- 4 A - 4 M + 1 D - 1 S - 1 E) + n_obstacles * n_p * (13 A + 19 M + 1 D + 2 S + 1 E)] - - - for (int t = 0; t < n_iter; t++) { - // Pass 1: Compute all forces from the current state. - // n_p * {[(n_p - 1) * (13 ADDs, 24 MULTs, 1 DIV, 4 SQRTs, 1 EXP + 2 ADDs)] + [(2 ADD + 4 MULT + (n_obstacles * (11 ADDs, 19 MULTs, 1 DIV, 2 SQRTs, 1 EXP) + n_obstacles * 2 ADDs) + 2 ADD) ]} - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - - // # 2 ADDs, 4 MULTs - // - // $\vec{F}_\alpha(\vec{v}_\alpha, v^0_\alpha \vec{e}_\alpha) = \frac{1}{\tau_\alpha}(v^0_\alpha \vec{e}_\alpha - \vec{v}_\alpha)$ - // - Vector2d f_alpha_dt = acceleration_term_dt(p); - - // # (N-1) * (13 ADDs, 24 MULTs, 1 DIV, 4 SQRTs, 1 EXP) - // + (N-1) * 2 ADDs - // - // $\sum_{\beta} \vec{F}_{\alpha\beta}(\vec{e}_{\alpha},\vec{r}_{\alpha} - \vec{r}_{\beta})$ - // - // for (int j = 0; j < n_p; j++) { - // if (i == j) - // continue; - // - // f_alpha_dt += pedestrian_repulsion_dt(p, pedestrians[j]); - //} - for (int j = 0; j < i; j++) { - f_alpha_dt += pedestrian_repulsion_dt(p, pedestrians[j]); - } - for (int j = i + 1; j < n_p; j++) { - f_alpha_dt += pedestrian_repulsion_dt(p, pedestrians[j]); - } - // # board.n_obstacles * (11 ADDs, 19 MULTs, 1 DIV, 2 SQRTs, 1 EXP) - // + board.n_obstacles * 2 ADDs - // - // $\sum_{B} \vec{F}_{\alpha B}(\vec{e}_{\alpha}, \vec{r}_{\alpha} - \vec{r}_{B})$ - // - for (int k = 0; k < board.n_obstacles; k++) { - f_alpha_dt += obstacle_repulsion_dt(p, board.obstacles[k]); - } - - // # 2 ADDs - // - // - // $\frac{d\vec{w}_\alpha}{dt} = \vec{F}_{\alpha}(t)$ - // - p.w += f_alpha_dt; - } - - // Pass 2: Update pedestrian states after all forces have been computed. - // # (7 ADDs, 16 MULTs, 2 DIVs, 3 SQRTs) * n_p - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - - // # 1 ADD, 2 MULTs, 1 SQRT - double w_norm = p.w.norm(); - - double w_norm2 = w_norm > EPS ? w_norm : EPS; // Avoid division by zero. - - // # 1 DIV - double correction_factor = std::min(1.0, p.v_max / w_norm2); - - // # 2 MULTs - p.curr_vel = p.w * correction_factor; - - // # 2 ADDs, 2 MULTs - // - // $\vec{r}_i^{t+1} = \vec{r}_i^t + \vec{v}_i^t dt$ - // - p.curr_pos = p.curr_pos + p.curr_vel * dt; - - // When a pedestrian reaches the end of the corridor, teleport them back - // to the opposite entrance while keeping the same y-coordinate. This - // maintains a constant pedestrian flow and makes lane formation easier to - // observe. - if (p.color == WHITE && p.curr_pos.x > (BOARD_LENGTH - 1.5)) { - p.curr_pos.x = 1.0; - p.destination.y = p.curr_pos.y; - p.w = Vector2d(p.desired_v0, 0.0); - p.curr_vel = p.w; - } - if (p.color == BLACK && p.curr_pos.x < 1.5) { - p.curr_pos.x = BOARD_LENGTH - 1.0; - p.destination.y = p.curr_pos.y; - p.w = Vector2d(-p.desired_v0, 0.0); - p.curr_vel = p.w; - } - - // Keep pedestrians inside the board boundaries. - p.curr_pos.y = clamp(p.curr_pos.y, WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - - // # 2 ADDs - Vector2d e = p.destination - p.curr_pos; - - // # 1 ADD, 2 MULTs, 1 DIV, 1 SQRT - double e_norm = e.norm(); - double e_norm2 = std::fmax(e_norm, EPS); // Avoid division by zero. - double e_norm_inv = 1.0 / e_norm2; - - // # 2 MULTs - p.e = e * e_norm_inv; - - // # 1 ADD, 2 MULTs - double velocity_norm_sq = p.curr_vel.dot(p.curr_vel); - - // # 1 SQRT - double velocity_norm = std::sqrt(velocity_norm_sq); - - // # 1 MULT - p.s_b_sq = velocity_norm_sq * delta_t_sq; - - // # 3 MULTs - p.s_b_e = p.e * (velocity_norm * delta_t); - -#if !BENCHMARK - // Store the current pedestrian state for visualization. - if (dump_path && (t % dump_interval == 0)) { - samples.emplace_back(t + 1, i, p.curr_pos.x, p.curr_pos.y, p.e.x, p.e.y, p.color); - } -#endif - } - } - -#if !BENCHMARK - // Export recorded simulation states to CSV. - if (dump_path) { - ofstream out(dump_path); - out << "time,id,x,y,p.e.x,p.e.y,color\n"; - - for (auto &[t, id, x, y, e_x, e_y, c] : samples) { - out << t << ',' << id << ',' << x << ',' << y << ',' << e_x << ',' << e_y << ',' << c << '\n'; - } - } -#endif - - return 0; -} \ No newline at end of file diff --git a/variants/variant_branchless_sqrtfree_flopcount.cpp b/variants/variant_branchless_sqrtfree_flopcount.cpp deleted file mode 100644 index ed3ff6b..0000000 --- a/variants/variant_branchless_sqrtfree_flopcount.cpp +++ /dev/null @@ -1,428 +0,0 @@ -// This file is merged from the forces.cpp and social_forces_baseline.cpp -// The goal is that we from now on only have one file as our baseline -// This should make it more easy in the future to implement optimizations -// Our naming convention from now on is: variant_.cpp (Please make sure to keep that consistent, otherwise our Makefile wont work anymore) - -// # Changes: FLOPCOUNT -// # Predecessor: variant_branchless_sqrtfree.cpp -// n_iter * [n_p ** 2 * (15 A + 25 M + 1 D + 3 S + 1 E) + n_p * (- 4 A - 5 M + 1 D - 1 E) + n_obstacles * n_p * (13 A + 20 M + 1 D + 1 S + 1 E)] - - -#include "../headers/board.hpp" -#include "../headers/constants.hpp" -#include "../headers/forces.hpp" -#include "../headers/pedestrian.hpp" -#include "../headers/social_force.hpp" -#include "../headers/vector2d.hpp" - -#include -#include -#include -#include -#include // keep — forces code uses unqualified sqrt/exp -#include -#include -#include - -#define SEED 42 -#define BOARD_WIDTH 10.0 -#define BOARD_LENGTH 50.0 -#define WALL_EPS 1e-3 -#define BOARD_WIDTH_MINUS_WALL_EPS 9.999 - -#ifndef RANDOM_SEED -#define RANDOM_SEED 0 -#endif - -#ifndef BENCHMARK -#define BENCHMARK 0 -#endif - -using namespace std; - -// forces.cpp - -// Flop count: 3 ADDs, 7 MULTs (no SQRT, no branch) -// Branchless + sqrt-free: cos_phi < 0 so f.norm()*cos_phi <= 0. -// - If dot >= 0: condition is trivially true. -// - If dot < 0: both sides non-positive; square them safely: -// dot^2 <= f.dot(f) * cos_phi^2. -// Bitwise | (not ||) keeps both sides evaluated and avoids a branch. - -// 3 ADD + 7 MULT -double w(Vector2d e, Vector2d f) { - - double dot = e.x * f.x + e.y * f.y; - double f_dot_f = f.x * f.x + f.y * f.y; - double cond = (dot >= 0.0) | (dot * dot <= f_dot_f * cos_phi_sq); - return c_neg_times_dt + cond * (dt_neg - c_neg_times_dt); -} - -// Flop count: 2 ADDs, 4 MULTs -Vector2d acceleration_term_dt(const Pedestrian &alpha) { - - // # 2 MULTs - Vector2d desired_velocity = alpha.e * alpha.desired_v0; - - Vector2d actual_velocity = alpha.curr_vel; - - // # 2 ADDs, 2 MULTs - Vector2d f_alpha_0_dt = (desired_velocity - actual_velocity) * dt_times_tau_alpha_inv; - - return f_alpha_0_dt; -} - -// Flop count: 13 ADDs, 25 MULTs, 1 DIV, 3 SQRTs, 1 EXP -Vector2d pedestrian_repulsion_dt(const Pedestrian &alpha, const Pedestrian &beta) { - - // # 2 ADDs - // $\vec{r}_{\alpha\beta}$ - Vector2d r_ab = alpha.curr_pos - beta.curr_pos; - - // # 1 ADD, 2 MULTs, 1 SQRT - // $\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert$ - double r_ab_norm = r_ab.norm(); - r_ab_norm = r_ab_norm > EPS ? r_ab_norm : EPS; // Avoid division by zero - - // $v_\beta \Delta t \vec{e}_\beta$ - Vector2d s_b_e = beta.s_b_e; - - // # 2 ADDs - // $\vec{r}_{\alpha\beta} - \vec{v}_{\beta}\varDelta_{t}\vec{e}_{\beta}$ - Vector2d r_ab2 = r_ab - s_b_e; - - // # 1 ADD, 2 MULTs, 1 SQRT - // $\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert$ - double r_ab2_norm = r_ab2.norm(); - r_ab2_norm = r_ab2_norm > EPS ? r_ab2_norm : EPS; // Avoid division by zero - - // # 1 ADD - // $\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert$ - double r_ab_norm_sum = r_ab_norm + r_ab2_norm; - - // # 1 ADD, 1 MULTs, 1 SQRT - // - // $2b = \sqrt{(\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert)^2 - (v_\beta \Delta t)^2}$ - // - double two_b_sq = r_ab_norm_sum * r_ab_norm_sum - beta.s_b_sq; - two_b_sq = two_b_sq > EPS_SQ ? two_b_sq : EPS_SQ; // Avoid sqrt of negative and avoid division by zero - double two_b = sqrt(two_b_sq); - - // # 5 MULTs, 1 DIV, 1 EXP - // - // $\frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert\,\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}$ - // - double scalar_mult_common = (r_ab_norm_sum / (two_b * r_ab_norm * r_ab2_norm)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b * NEG_TWO_SIGMA_INV)); - - // # 1 MULT - // - // $\frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert}$ - // - double scalar_mult_r_ab = scalar_mult_common * r_ab2_norm; - - // # 1 MULT - // - // $\frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}$ - // - double scalar_mult_r_ab2 = scalar_mult_common * r_ab_norm; - - // # 2 ADDs, 4 MULTs - // - // $\vec{-f}_{\alpha \beta}(\vec{r}_{\alpha \beta}) = \frac{-V^0_{\alpha \beta}}{2\sigma}e^{-b / \sigma} 2\grad_{\vec{r}_{\alpha \beta}}b $ - // - // - // $= \frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert}\,\vec{r}_{\alpha \beta} + \frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} - - // v_\beta \Delta t \vec{e}_\beta \Arrowvert}\,(\vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta)$ - // - // - // - // $2\grad_{\vec{r}_{\alpha \beta}}b = \frac{(\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert)(\frac{\vec{r}_{\alpha \beta}}{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert} + \frac{\vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta}{\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert})}{2b}$ - // - // - // $= \frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert}\,\vec{r}_{\alpha \beta} + \frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}\,(\vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta)$ - // - // - Vector2d f_alpha_beta_neg = r_ab * scalar_mult_r_ab + r_ab2 * scalar_mult_r_ab2; - - // # 3 ADDs, 9 MULTs - // - // $\vec{F}_{\alpha\beta}(\vec{e}_{\alpha}, \vec{r}_{\alpha \beta}).dt = w(\vec{e}_{\alpha}, -\vec{f}_{\alpha\beta}(\vec{r}_{\alpha \beta})).\vec{f}_{\alpha\beta}(\vec{r}_{\alpha \beta}).dt$ - // - Vector2d f_alpha_beta_dt = f_alpha_beta_neg * w(alpha.e, f_alpha_beta_neg); - - return f_alpha_beta_dt; -} - -// Flop count: 11 ADDs, 20 MULTs, 1 DIVs, 1 SQRT, 1 EXP -Vector2d obstacle_repulsion_dt(const Pedestrian &alpha, const Obstacle &B) { - - // # 7 ADDs, 5 MULTs - // $\vec{r}_{\alpha B}$ - Vector2d r_aB = alpha.curr_pos - B.find_nearest_obstacle_point(alpha.curr_pos); - - // # 1 ADD, 2 MULTs, 1 SQRT - // $\Arrowvert \vec{r}_{\alpha B} \Arrowvert$ - double r_aB_norm = r_aB.norm(); - r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; // Avoid division by zero - - // # 2 MULTs, 1 DIV, 1 EXP - // - // $\frac{-U^0_{\alpha B}}{R} e^{- \Arrowvert \vec{r}_{\alpha B} \Arrowvert / R}$ - // - double scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; - - // # 2 MULTs - // - // $-\vec{F}_{\alpha B}(\vec{r}_{\alpha B}) = \frac{-U^0_{\alpha B}}{R} e^{- \Arrowvert \vec{r}_{\alpha B} \Arrowvert / R} \frac{\vec{r}_{\alpha B}}{\Arrowvert \vec{r}_{\alpha B} \Arrowvert}$ - // - Vector2d f_alpha_B_neg = r_aB * scalar_mult; - - // # 3 ADDs, 9 MULTs - // - // $\vec{F}_{\alpha B}(\vec{e}_{\alpha}, \vec{r}_{\alpha B}).dt = w(\vec{e}_{\alpha}, -\vec{F}_{\alpha B}(\vec{r}_{\alpha B})).\vec{F}_{\alpha B}(\vec{r}_{\alpha B}).dt$ - // - Vector2d f_alpha_B_dt = f_alpha_B_neg * w(alpha.e, f_alpha_B_neg); - - return f_alpha_B_dt; -} - -// social_force_baseline.cpp - -Pedestrian *init_pedestrians(int n_p) { -#if RANDOM_SEED - random_device rd; // Platform-provided random seed source. - mt19937 gen(rd()); // Non-reproducible initialization. -#else - mt19937 gen(SEED); // Reproducible initialization. -#endif - - normal_distribution velocity_gen(v0_mean, v0_std_dev); - uniform_real_distribution y_gen(0.3, BOARD_WIDTH - 0.3); - uniform_real_distribution x_gen_left(2.0, BOARD_LENGTH / 2.0); - uniform_real_distribution x_gen_right(BOARD_LENGTH / 2.0, BOARD_LENGTH - 2.0); - - Pedestrian *P = new Pedestrian[n_p]; - - int n_p_half = n_p / 2; - - // Group of pedestrians walking from left to right. - for (int i = 0; i < n_p_half; i++) { - double x = x_gen_left(gen); - double y = y_gen(gen); - - Vector2d start_pos = Vector2d(x, y); - Vector2d destination = Vector2d(BOARD_LENGTH + 30.0, y); - - Vector2d init_e = destination - start_pos; - double init_e_norm = init_e.norm(); - Vector2d init_e_unit = init_e / init_e_norm; - - // Reject near-zero desired speeds to avoid pedestrians that barely move, - // and reject negative speeds because they would reverse the intended - // walking direction. - double desired_v0; - do { - desired_v0 = velocity_gen(gen); - } while (desired_v0 <= 0.1); - - double v_max = 1.3 * desired_v0; - - P[i] = Pedestrian(WHITE, Vector2d(), start_pos, init_e_unit, v_max, desired_v0, destination); - } - - // Group of pedestrians walking from right to left. - for (int i = n_p_half; i < n_p; i++) { - double x = x_gen_right(gen); - double y = y_gen(gen); - - Vector2d start_pos = Vector2d(x, y); - Vector2d destination = Vector2d(-30.0, y); - - Vector2d init_e = destination - start_pos; - double init_e_norm = init_e.norm(); - Vector2d init_e_unit = init_e / init_e_norm; - - // Reject near-zero desired speeds to avoid pedestrians that barely move, - // and reject negative speeds because they would reverse the intended - // walking direction. - double desired_v0; - do { - desired_v0 = velocity_gen(gen); - } while (desired_v0 <= 0.1); - - double v_max = 1.3 * desired_v0; - - P[i] = Pedestrian(BLACK, Vector2d(), start_pos, init_e_unit, v_max, desired_v0, destination); - } - - return P; -} - -Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } - -int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { - -#if BENCHMARK - // Avoid compiler unused parameter warning - (void)dump_path; -#endif - -#if !BENCHMARK - const int dump_interval = 1; - - // Each sample stores: time step, pedestrian id, x, y, e.x, e.y, color. - vector> samples; - - if (dump_path) { - samples.reserve(static_cast(n_iter / dump_interval + 1) * n_p); - - // Store the initial state before the first simulation step. - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - samples.emplace_back(0, i, p.curr_pos.x, p.curr_pos.y, p.e.x, p.e.y, p.color); - } - } -#endif - - // n_iter * [{n_p * [(n_p - 1) * (13 ADDs, 25 MULTs, 1 DIV, 3 SQRTs, 1 EXP) + (n_p-1) * (2 ADDs) + n_obstacles * (11 ADDs, 20 MULTs, 1 DIV, 1 SQRTs, 1 EXP) + n_obstacles * (2 ADDs) + 4 ADDs + 4 MULTs]} + {(7 ADDs, 16 MULTs, 2 DIVs, 3 SQRTs) * n_p}] - // n_iter * [{n_p * [(n_p - 1) * (13 A + 25 M + 1 D + 3 S + 1 E) + (n_p - 1) * (2 A) + n_obstacles * (11 A + 20 M + 1 D + 1 S + 1 E) + n_obstacles * (2 A) + 4 A + 4 M]} + {(7 A + 16 M + 2 D + 3 S) * n_p}] - // n_iter * [{n_p * [n_p * (13 A + 25 M + 1 D + 3 S + 1 E) - 1 * (13 A + 25 M + 1 D + 3 S + 1 E) + n_p * (2 A) - 1 * (2 A) + n_obstacles * (11 A + 20 M + 1 D + 1 S + 1 E) + n_obstacles * (2 A) + 4 A + 4 M]} + {n_p * (7 A + 16 M + 2 D + 3 S)}] - // n_iter * [{n_p * [n_p * (15 A + 25 M + 1 D + 3 S + 1 E) - 1 * (15 A + 25 M + 1 D + 3 S + 1 E - 4 A - 4 M) + n_obstacles * (13 A + 20 M + 1 D + 1 S + 1 E)]} + {n_p * (7 A + 16 M + 2 D + 3 S)}] - // n_iter * [n_p ** 2 * (15 A + 25 M + 1 D + 3 S + 1 E) - n_p * (11 A + 21 M + 1 D + 3 S + 1 E) + n_obstacles * n_p * (13 A + 20 M + 1 D + 1 S + 1 E) + n_p * (7 A + 16 M + 2 D + 3 S)] - // n_iter * [n_p ** 2 * (15 A + 25 M + 1 D + 3 S + 1 E) + n_p * (- 11 A - 21 M - 1 D - 3 S - 1 E) + n_p * (7 A + 16 M + 2 D + 3 S) + n_obstacles * n_p * (13 A + 20 M + 1 D + 1 S + 1 E)] - // n_iter * [n_p ** 2 * (15 A + 25 M + 1 D + 3 S + 1 E) + n_p * (- 4 A - 5 M + 1 D - 1 E) + n_obstacles * n_p * (13 A + 20 M + 1 D + 1 S + 1 E)] - for (int t = 0; t < n_iter; t++) { - // Pass 1: Compute all forces from the current state. - - // n_p * [(n_p - 1) * (13 ADDs, 24 MULTs, 1 DIV, 3 SQRTs, 1 EXP) + (n_p-1) * (2 ADDs) + n_obstacles * (11 ADDs, 19 MULTs, 1 DIV, 1 SQRT, 1 EXP) + n_obstacles * (2 ADDs) + 4 ADDs + 4 MULTs] - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - - // # 2 ADDs, 4 MULTs - // - // $\vec{F}_\alpha(\vec{v}_\alpha, v^0_\alpha \vec{e}_\alpha) = \frac{1}{\tau_\alpha}(v^0_\alpha \vec{e}_\alpha - \vec{v}_\alpha)$ - // - Vector2d f_alpha_dt = acceleration_term_dt(p); - - // # (N-1) * (13 ADDs, 25 MULTs, 1 DIV, 3 SQRT, 1 EXP) - // + (N-1) * 2 ADDs - // - // $\sum_{\beta} \vec{F}_{\alpha\beta}(\vec{e}_{\alpha},\vec{r}_{\alpha} - \vec{r}_{\beta})$ - // - // for (int j = 0; j < n_p; j++) { - // if (i == j) - // continue; - // - // f_alpha_dt += pedestrian_repulsion_dt(p, pedestrians[j]); - //} - for (int j = 0; j < i; j++) { - f_alpha_dt += pedestrian_repulsion_dt(p, pedestrians[j]); - } - for (int j = i + 1; j < n_p; j++) { - f_alpha_dt += pedestrian_repulsion_dt(p, pedestrians[j]); - } - // # board.n_obstacles * (11 ADDs, 20 MULTs, 1 DIV, 1 SQRT, 1 EXP) - // + board.n_obstacles * 2 ADDs - // - // $\sum_{B} \vec{F}_{\alpha B}(\vec{e}_{\alpha}, \vec{r}_{\alpha} - \vec{r}_{B})$ - // - for (int k = 0; k < board.n_obstacles; k++) { - f_alpha_dt += obstacle_repulsion_dt(p, board.obstacles[k]); - } - - // # 2 ADDs - // - // - // $\frac{d\vec{w}_\alpha}{dt} = \vec{F}_{\alpha}(t)$ - // - p.w += f_alpha_dt; - } - - // Pass 2: Update pedestrian states after all forces have been computed. - // # (7 ADDs, 16 MULTs, 2 DIVs, 3 SQRTs) * n_p - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - - // # 1 ADD, 2 MULTs, 1 SQRT - double w_norm = p.w.norm(); - - double w_norm2 = w_norm > EPS ? w_norm : EPS; // Avoid division by zero. - - // # 1 DIV - double correction_factor = std::min(1.0, p.v_max / w_norm2); - - // # 2 MULTs - p.curr_vel = p.w * correction_factor; - - // # 2 ADDs, 2 MULTs - // - // $\vec{r}_i^{t+1} = \vec{r}_i^t + \vec{v}_i^t dt$ - // - p.curr_pos = p.curr_pos + p.curr_vel * dt; - - // When a pedestrian reaches the end of the corridor, teleport them back - // to the opposite entrance while keeping the same y-coordinate. This - // maintains a constant pedestrian flow and makes lane formation easier to - // observe. - if (p.color == WHITE && p.curr_pos.x > (BOARD_LENGTH - 1.5)) { - p.curr_pos.x = 1.0; - p.destination.y = p.curr_pos.y; - p.w = Vector2d(p.desired_v0, 0.0); - p.curr_vel = p.w; - } - if (p.color == BLACK && p.curr_pos.x < 1.5) { - p.curr_pos.x = BOARD_LENGTH - 1.0; - p.destination.y = p.curr_pos.y; - p.w = Vector2d(-p.desired_v0, 0.0); - p.curr_vel = p.w; - } - - // Keep pedestrians inside the board boundaries. - p.curr_pos.y = clamp(p.curr_pos.y, WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - - // # 2 ADDs - Vector2d e = p.destination - p.curr_pos; - - // # 1 ADD, 2 MULTs, 1 DIV, 1 SQRT - double e_norm = e.norm(); - double e_norm2 = std::fmax(e_norm, EPS); // Avoid division by zero. - double e_norm_inv = 1.0 / e_norm2; - - // # 2 MULTs - p.e = e * e_norm_inv; - - // # 1 ADD, 2 MULTs - double velocity_norm_sq = p.curr_vel.dot(p.curr_vel); - - // # 1 SQRT - double velocity_norm = std::sqrt(velocity_norm_sq); - - // # 1 MULT - p.s_b_sq = velocity_norm_sq * delta_t_sq; - - // # 3 MULTs - p.s_b_e = p.e * (velocity_norm * delta_t); - -#if !BENCHMARK - // Store the current pedestrian state for visualization. - if (dump_path && (t % dump_interval == 0)) { - samples.emplace_back(t + 1, i, p.curr_pos.x, p.curr_pos.y, p.e.x, p.e.y, p.color); - } -#endif - } - } - -#if !BENCHMARK - // Export recorded simulation states to CSV. - if (dump_path) { - ofstream out(dump_path); - out << "time,id,x,y,p.e.x,p.e.y,color\n"; - - for (auto &[t, id, x, y, e_x, e_y, c] : samples) { - out << t << ',' << id << ',' << x << ',' << y << ',' << e_x << ',' << e_y << ',' << c << '\n'; - } - } -#endif - - return 0; -} \ No newline at end of file diff --git a/variants/variant_cutoff_callsite_flopcount.cpp b/variants/variant_cutoff_callsite_flopcount.cpp deleted file mode 100644 index 969f59c..0000000 --- a/variants/variant_cutoff_callsite_flopcount.cpp +++ /dev/null @@ -1,436 +0,0 @@ -// This file is copied from the baseline and modified -// Our goal is to only calculate pedestrian-pedestrian forces for pedestrian which are near -// Our tolerance is 1cm and our cutoff is a 5m radius. -// Since we have some tolerance and we put pedestrians back at the end of the hallway once they are on one end. We only test/verify on a smaller subsample. -// Otherwise we had huge gaps (because of those jumps back) -// In this version we do the cutoff before we call the pedestrian forces function - -// # Changes: FLOPCOUNT -// # Predecessor: variant_cutoff_callsite.cpp - -// // n_iter * [ n_p ** 2 * (14 A + 23 M + 1 D + 4 S + 1 E) + n_p * (- 3 A - 3 M + 1 D - 1 S - 1 E) + n_obstacles * n_p * (12 A + 18 M + 1 D + 2 S + 1 E) ] - - -#include "../headers/board.hpp" -#include "../headers/constants.hpp" -#include "../headers/pedestrian.hpp" -#include "../headers/vector2d.hpp" - -#include -#include -#include -#include -#include // keep — forces code uses unqualified sqrt/exp -#include -#include -#include - -#define SEED 42 -#define BOARD_WIDTH 10.0 -#define BOARD_LENGTH 50.0 -#define WALL_EPS 1e-3 -#define BOARD_WIDTH_MINUS_WALL_EPS 9.999 - -#ifndef RANDOM_SEED -#define RANDOM_SEED 0 -#endif - -#ifndef BENCHMARK -#define BENCHMARK 0 -#endif - -using namespace std; - -// forces.cpp - -// Flop count: 2 ADDs, 5 MULTs, 1 SQRT -double w(Vector2d e, Vector2d f) { - if (e.dot(f) >= f.norm() * cos_phi) - return dt_neg; - else - return c_neg_times_dt; -} - -// Flop count: 2 ADDs, 4 MULTs -Vector2d acceleration_term_dt(const Pedestrian &alpha) { - - // # 2 MULTs - Vector2d desired_velocity = alpha.e * alpha.desired_v0; - - Vector2d actual_velocity = alpha.curr_vel; - - // # 2 ADDs, 2 MULTs - Vector2d f_alpha_0_dt = (desired_velocity - actual_velocity) * dt_times_tau_alpha_inv; - - return f_alpha_0_dt; -} - -// Flop count: 12 ADDs, 23 MULTs, 1 DIV, 4 SQRTs, 1 EXP -Vector2d pedestrian_repulsion_dt(const Pedestrian &alpha, const Pedestrian &beta) { - - // # 2 ADDs - // $\vec{r}_{\alpha\beta}$ - Vector2d r_ab = alpha.curr_pos - beta.curr_pos; - - // # 1 ADD, 2 MULTs, 1 SQRT - // $\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert$ - double r_ab_norm = r_ab.norm(); - // Now we wanna check if it is a close pedestrian or wheter it is far away and can be ignored - // double r_ab_sq = r_ab.x * r_ab.x + r_ab.y * r_ab.y; // squared distance - // if (r_ab_sq > CUTOFF_SQ) - // return Vector2d(0.0, 0.0); // cheap reject - // double r_ab_norm = sqrt(r_ab_sq); // reuse r_ab_sq, no recompute - - r_ab_norm = r_ab_norm > EPS ? r_ab_norm : EPS; // Avoid division by zero - - // $v_\beta \Delta t \vec{e}_\beta$ - Vector2d s_b_e = beta.s_b_e; - - // # 2 ADDs - // $\vec{r}_{\alpha\beta} - \vec{v}_{\beta}\varDelta_{t}\vec{e}_{\beta}$ - Vector2d r_ab2 = r_ab - s_b_e; - - // # 1 ADD, 2 MULTs, 1 SQRT - // $\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert$ - double r_ab2_norm = r_ab2.norm(); - r_ab2_norm = r_ab2_norm > EPS ? r_ab2_norm : EPS; // Avoid division by zero - - // # 1 ADD - // $\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert$ - double r_ab_norm_sum = r_ab_norm + r_ab2_norm; - - // # 1 ADD, 1 MULTs, 1 SQRT - // - // $2b = \sqrt{(\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert)^2 - (v_\beta \Delta t)^2}$ - // - double two_b_sq = r_ab_norm_sum * r_ab_norm_sum - beta.s_b_sq; - two_b_sq = two_b_sq > EPS_SQ ? two_b_sq : EPS_SQ; // Avoid sqrt of negative and avoid division by zero - double two_b = sqrt(two_b_sq); - - // # 5 MULTs, 1 DIV, 1 EXP - // - // $\frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert\,\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}$ - // - double scalar_mult_common = (r_ab_norm_sum / (two_b * r_ab_norm * r_ab2_norm)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b * NEG_TWO_SIGMA_INV)); - - // # 1 MULT - // - // $\frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert}$ - // - double scalar_mult_r_ab = scalar_mult_common * r_ab2_norm; - - // # 1 MULT - // - // $\frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}$ - // - double scalar_mult_r_ab2 = scalar_mult_common * r_ab_norm; - - // # 2 ADDs, 4 MULTs - // - // $\vec{-f}_{\alpha \beta}(\vec{r}_{\alpha \beta}) = \frac{-V^0_{\alpha \beta}}{2\sigma}e^{-b / \sigma} 2\grad_{\vec{r}_{\alpha \beta}}b $ - // - // - // $= \frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert}\,\vec{r}_{\alpha \beta} + \frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} - - // v_\beta \Delta t \vec{e}_\beta \Arrowvert}\,(\vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta)$ - // - // - // - // $2\grad_{\vec{r}_{\alpha \beta}}b = \frac{(\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert)(\frac{\vec{r}_{\alpha \beta}}{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert} + \frac{\vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta}{\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert})}{2b}$ - // - // - // $= \frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert}\,\vec{r}_{\alpha \beta} + \frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}\,(\vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta)$ - // - // - Vector2d f_alpha_beta_neg = r_ab * scalar_mult_r_ab + r_ab2 * scalar_mult_r_ab2; - - // # 2 ADDs, 7 MULTs, 1 SQRT - // - // $\vec{F}_{\alpha\beta}(\vec{e}_{\alpha}, \vec{r}_{\alpha \beta}).dt = w(\vec{e}_{\alpha}, -\vec{f}_{\alpha\beta}(\vec{r}_{\alpha \beta})).\vec{f}_{\alpha\beta}(\vec{r}_{\alpha \beta}).dt$ - // - Vector2d f_alpha_beta_dt = f_alpha_beta_neg * w(alpha.e, f_alpha_beta_neg); - - return f_alpha_beta_dt; -} - -// Flop count: 10 ADDs, 18 MULTs, 1 DIVs, 2 SQRTs, 1 EXP -Vector2d obstacle_repulsion_dt(const Pedestrian &alpha, const Obstacle &B) { - - // # 7 ADDs, 5 MULTs - // $\vec{r}_{\alpha B}$ - Vector2d r_aB = alpha.curr_pos - B.find_nearest_obstacle_point(alpha.curr_pos); - - // # 1 ADD, 2 MULTs, 1 SQRT - // $\Arrowvert \vec{r}_{\alpha B} \Arrowvert$ - double r_aB_norm = r_aB.norm(); - r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; // Avoid division by zero - - // # 2 MULTs, 1 DIV, 1 EXP - // - // $\frac{-U^0_{\alpha B}}{R} e^{- \Arrowvert \vec{r}_{\alpha B} \Arrowvert / R}$ - // - double scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; - - // # 2 MULTs - // - // $-\vec{F}_{\alpha B}(\vec{r}_{\alpha B}) = \frac{-U^0_{\alpha B}}{R} e^{- \Arrowvert \vec{r}_{\alpha B} \Arrowvert / R} \frac{\vec{r}_{\alpha B}}{\Arrowvert \vec{r}_{\alpha B} \Arrowvert}$ - // - Vector2d f_alpha_B_neg = r_aB * scalar_mult; - - // # 2 ADDs, 7 MULTs, 1 SQRT - // - // $\vec{F}_{\alpha B}(\vec{e}_{\alpha}, \vec{r}_{\alpha B}).dt = w(\vec{e}_{\alpha}, -\vec{F}_{\alpha B}(\vec{r}_{\alpha B})).\vec{F}_{\alpha B}(\vec{r}_{\alpha B}).dt$ - // - Vector2d f_alpha_B_dt = f_alpha_B_neg * w(alpha.e, f_alpha_B_neg); - - return f_alpha_B_dt; -} - -// social_force_baseline.cpp - -Pedestrian *init_pedestrians(int n_p) { -#if RANDOM_SEED - random_device rd; // Platform-provided random seed source. - mt19937 gen(rd()); // Non-reproducible initialization. -#else - mt19937 gen(SEED); // Reproducible initialization. -#endif - - normal_distribution velocity_gen(v0_mean, v0_std_dev); - uniform_real_distribution y_gen(0.3, BOARD_WIDTH - 0.3); - uniform_real_distribution x_gen_left(2.0, BOARD_LENGTH / 2.0); - uniform_real_distribution x_gen_right(BOARD_LENGTH / 2.0, BOARD_LENGTH - 2.0); - - Pedestrian *P = new Pedestrian[n_p]; - - int n_p_half = n_p / 2; - - // Group of pedestrians walking from left to right. - for (int i = 0; i < n_p_half; i++) { - double x = x_gen_left(gen); - double y = y_gen(gen); - - Vector2d start_pos = Vector2d(x, y); - Vector2d destination = Vector2d(BOARD_LENGTH + 30.0, y); - - Vector2d init_e = destination - start_pos; - double init_e_norm = init_e.norm(); - Vector2d init_e_unit = init_e / init_e_norm; - - // Reject near-zero desired speeds to avoid pedestrians that barely move, - // and reject negative speeds because they would reverse the intended - // walking direction. - double desired_v0; - do { - desired_v0 = velocity_gen(gen); - } while (desired_v0 <= 0.1); - - double v_max = 1.3 * desired_v0; - - P[i] = Pedestrian(WHITE, Vector2d(), start_pos, init_e_unit, v_max, desired_v0, destination); - } - - // Group of pedestrians walking from right to left. - for (int i = n_p_half; i < n_p; i++) { - double x = x_gen_right(gen); - double y = y_gen(gen); - - Vector2d start_pos = Vector2d(x, y); - Vector2d destination = Vector2d(-30.0, y); - - Vector2d init_e = destination - start_pos; - double init_e_norm = init_e.norm(); - Vector2d init_e_unit = init_e / init_e_norm; - - // Reject near-zero desired speeds to avoid pedestrians that barely move, - // and reject negative speeds because they would reverse the intended - // walking direction. - double desired_v0; - do { - desired_v0 = velocity_gen(gen); - } while (desired_v0 <= 0.1); - - double v_max = 1.3 * desired_v0; - - P[i] = Pedestrian(BLACK, Vector2d(), start_pos, init_e_unit, v_max, desired_v0, destination); - } - - return P; -} - -Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } - -int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { - -#if BENCHMARK - // Avoid compiler unused parameter warning - (void)dump_path; -#endif - -#if !BENCHMARK - const int dump_interval = 1; - - // Each sample stores: time step, pedestrian id, x, y, e.x, e.y, color. - vector> samples; - - if (dump_path) { - samples.reserve(static_cast(n_iter / dump_interval + 1) * n_p); - - // Store the initial state before the first simulation step. - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - samples.emplace_back(0, i, p.curr_pos.x, p.curr_pos.y, p.e.x, p.e.y, p.color); - } - } -#endif - - // n_iter * [ { n_p * (n_p - 1) * (12 ADDs, 23 MULTs, 1 DIV, 4 SQRTs, 1 EXP + 2 ADDs) + n_p * (4 ADD + 4 MULT + board.n_obstacles * (10 ADDs, 18 MULTs, 1 DIV, 2 SQRTs, 1 EXP + 2 ADD) ) } + {(7 ADDs, 16 MULTs, 2 DIVs, 3 SQRTs) * n_p} ] - - // n_iter * [ { n_p * (n_p - 1) * (12 A + 23 M + 1 D + 4 S + 1 E + 2 A) + n_p * (4 A + 4 M + n_obstacles * (10 A + 18 M + 1 D + 2 S + 1 E + 2 A) ) } + {n_p * (7 A + 16 M + 2 D + 3 S)} ] - - // n_iter * [ { n_p ** 2 * (12 A + 23 M + 1 D + 4 S + 1 E + 2 A) - n_p * (12 A + 23 M + 1 D + 4 S + 1 E + 2 A) + n_p * (4 A + 4 M) + n_obstacles * n_p * (10 A + 18 M + 1 D + 2 S + 1 E + 2 A) } + {n_p * (7 A + 16 M + 2 D + 3 S)} ] - - - // n_iter * [ n_p ** 2 * (12 A + 23 M + 1 D + 4 S + 1 E + 2 A) + n_p * (- 8 A - 19 M - 1 D - 4 S - 1 E - 2 A) + n_obstacles * n_p * (10 A + 18 M + 1 D + 2 S + 1 E + 2 A) + n_p * (7 A + 16 M + 2 D + 3 S) ] - - - // n_iter * [ n_p ** 2 * (14 A + 23 M + 1 D + 4 S + 1 E) + n_p * (- 3 A - 3 M + 1 D - 1 S - 1 E) + n_obstacles * n_p * (12 A + 18 M + 1 D + 2 S + 1 E) ] - -// NOTE: this flop count charges every ped-ped pair the full cost. The cutoff -// (L80-81) early-rejects pairs farther than 5m, so the real ped-ped work is only -// a fraction of this (roughly 40-50% on a 10x50 hallway, depending on the layout). -// We keep it at 100% here as the upper-bound / fixed-W baseline, the exact fraction -// can be folded into the n_p**2 term later if we want the actual executed flops. - - for (int t = 0; t < n_iter; t++) { - // Pass 1: Compute all forces from the current state. - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - - // # 2 ADDs, 4 MULTs - // - // $\vec{F}_\alpha(\vec{v}_\alpha, v^0_\alpha \vec{e}_\alpha) = \frac{1}{\tau_\alpha}(v^0_\alpha \vec{e}_\alpha - \vec{v}_\alpha)$ - // - Vector2d f_alpha_dt = acceleration_term_dt(p); - - // # (N-1) * (12 ADDs, 23 MULTs, 1 DIV, 4 SQRTs, 1 EXP) - // + (N-1) * 2 ADDs - // - // $\sum_{\beta} \vec{F}_{\alpha\beta}(\vec{e}_{\alpha},\vec{r}_{\alpha} - \vec{r}_{\beta})$ - // - for (int j = 0; j < n_p; j++) { - if (i == j) - continue; - - // Cutoff check at the call site (so we dont have an additional call) - Vector2d r_ab_pre = p.curr_pos - pedestrians[j].curr_pos; - if (r_ab_pre.x * r_ab_pre.x + r_ab_pre.y * r_ab_pre.y > CUTOFF_SQ) - continue; - - f_alpha_dt += pedestrian_repulsion_dt(p, pedestrians[j]); - } - - // # board.n_obstacles * (10 ADDs, 18 MULTs, 1 DIV, 2 SQRTs, 1 EXP) - // + board.n_obstacles * 2 ADDs - // - // $\sum_{B} \vec{F}_{\alpha B}(\vec{e}_{\alpha}, \vec{r}_{\alpha} - \vec{r}_{B})$ - // - for (int k = 0; k < board.n_obstacles; k++) { - f_alpha_dt += obstacle_repulsion_dt(p, board.obstacles[k]); - } - - // # 2 ADDs - // - // - // $\frac{d\vec{w}_\alpha}{dt} = \vec{F}_{\alpha}(t)$ - // - p.w += f_alpha_dt; - } - - // Pass 2: Update pedestrian states after all forces have been computed. - // # (7 ADDs, 16 MULTs, 2 DIVs, 3 SQRTs) * n_p - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - - // # 1 ADD, 2 MULTs, 1 SQRT - double w_norm = p.w.norm(); - - double w_norm2 = w_norm > EPS ? w_norm : EPS; // Avoid division by zero. - - // # 1 DIV - double correction_factor = std::min(1.0, p.v_max / w_norm2); - - // # 2 MULTs - p.curr_vel = p.w * correction_factor; - - // # 2 ADDs, 2 MULTs - // - // $\vec{r}_i^{t+1} = \vec{r}_i^t + \vec{v}_i^t dt$ - // - p.curr_pos = p.curr_pos + p.curr_vel * dt; - - // When a pedestrian reaches the end of the corridor, teleport them back - // to the opposite entrance while keeping the same y-coordinate. This - // maintains a constant pedestrian flow and makes lane formation easier to - // observe. - if (p.color == WHITE && p.curr_pos.x > (BOARD_LENGTH - 1.5)) { - p.curr_pos.x = 1.0; - p.destination.y = p.curr_pos.y; - p.w = Vector2d(p.desired_v0, 0.0); - p.curr_vel = p.w; - } - if (p.color == BLACK && p.curr_pos.x < 1.5) { - p.curr_pos.x = BOARD_LENGTH - 1.0; - p.destination.y = p.curr_pos.y; - p.w = Vector2d(-p.desired_v0, 0.0); - p.curr_vel = p.w; - } - - // Keep pedestrians inside the board boundaries. - p.curr_pos.y = clamp(p.curr_pos.y, WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - - // # 2 ADDs - Vector2d e = p.destination - p.curr_pos; - - // # 1 ADD, 2 MULTs, 1 DIV, 1 SQRT - double e_norm = e.norm(); - double e_norm2 = e_norm > EPS ? e_norm : EPS; // Avoid division by zero. - double e_norm_inv = 1.0 / e_norm2; - - // # 2 MULTs - p.e = e * e_norm_inv; - - // # 1 ADD, 2 MULTs - double velocity_norm_sq = p.curr_vel.dot(p.curr_vel); - - // # 1 SQRT - double velocity_norm = std::sqrt(velocity_norm_sq); - - // # 1 MULT - p.s_b_sq = velocity_norm_sq * delta_t_sq; - - // # 3 MULTs - p.s_b_e = p.e * (velocity_norm * delta_t); - -#if !BENCHMARK - // Store the current pedestrian state for visualization. - if (dump_path && (t % dump_interval == 0)) { - samples.emplace_back(t + 1, i, p.curr_pos.x, p.curr_pos.y, p.e.x, p.e.y, p.color); - } -#endif - } - } - -#if !BENCHMARK - // Export recorded simulation states to CSV. - if (dump_path) { - ofstream out(dump_path); - out << "time,id,x,y,p.e.x,p.e.y,color\n"; - - for (auto &[t, id, x, y, e_x, e_y, c] : samples) { - out << t << ',' << id << ',' << x << ',' << y << ',' << e_x << ',' << e_y << ',' << c << '\n'; - } - } -#endif - - return 0; -} \ No newline at end of file diff --git a/variants/variant_cutoff_flopcount.cpp b/variants/variant_cutoff_flopcount.cpp deleted file mode 100644 index bffd1a9..0000000 --- a/variants/variant_cutoff_flopcount.cpp +++ /dev/null @@ -1,434 +0,0 @@ -// This file is copied from the baseline and modified -// Our goal is to only calculate pedestrian-pedestrian forces for pedestrian which are near -// Our tolerance is 1cm and our cutoff is a 5m radius. -// Since we have some tolerance and we put pedestrians back at the end of the hallway once they are on one end. We only test/verify on a smaller subsample. -// Otherwise we had huge gaps (because of those jumps back) - -// # Changes: FLOPCOUNT -// # Predecessor: variant_cutoff.cpp - - -// n_iter * [ n_p ** 2 * (14 A + 23 M + 1 D + 4 S + 1 E) + n_p * (- 3 A - 3 M + 1 D - 1 S - 1 E) + n_obstacles * n_p * (12 A + 18 M + 1 D + 2 S + 1 E) ] - - -#include "../headers/board.hpp" -#include "../headers/constants.hpp" -#include "../headers/pedestrian.hpp" -#include "../headers/vector2d.hpp" - -#include -#include -#include -#include -#include // keep — forces code uses unqualified sqrt/exp -#include -#include -#include - -#define SEED 42 -#define BOARD_WIDTH 10.0 -#define BOARD_LENGTH 50.0 -#define WALL_EPS 1e-3 -#define BOARD_WIDTH_MINUS_WALL_EPS 9.999 - -#ifndef RANDOM_SEED -#define RANDOM_SEED 0 -#endif - -#ifndef BENCHMARK -#define BENCHMARK 0 -#endif - -using namespace std; - -// forces.cpp - -// Flop count: 2 ADDs, 5 MULTs, 1 SQRT -double w(Vector2d e, Vector2d f) { - if (e.dot(f) >= f.norm() * cos_phi) - return dt_neg; - else - return c_neg_times_dt; -} - -// Flop count: 2 ADDs, 4 MULTs -Vector2d acceleration_term_dt(const Pedestrian &alpha) { - - // # 2 MULTs - Vector2d desired_velocity = alpha.e * alpha.desired_v0; - - Vector2d actual_velocity = alpha.curr_vel; - - // # 2 ADDs, 2 MULTs - Vector2d f_alpha_0_dt = (desired_velocity - actual_velocity) * dt_times_tau_alpha_inv; - - return f_alpha_0_dt; -} - -// Flop count: 12 ADDs, 23 MULTs, 1 DIV, 4 SQRTs, 1 EXP -Vector2d pedestrian_repulsion_dt(const Pedestrian &alpha, const Pedestrian &beta) { - - // # 2 ADDs - // $\vec{r}_{\alpha\beta}$ - Vector2d r_ab = alpha.curr_pos - beta.curr_pos; - - // # 1 ADD, 2 MULTs, 1 SQRT - // $\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert$ - // double r_ab_norm = r_ab.norm(); - // Now we wanna check if it is a close pedestrian or wheter it is far away and can be ignored - double r_ab_sq = r_ab.x * r_ab.x + r_ab.y * r_ab.y; // squared distance - if (r_ab_sq > CUTOFF_SQ) - return Vector2d(0.0, 0.0); // cheap reject - double r_ab_norm = sqrt(r_ab_sq); // reuse r_ab_sq, no recompute - - r_ab_norm = r_ab_norm > EPS ? r_ab_norm : EPS; // Avoid division by zero - - // $v_\beta \Delta t \vec{e}_\beta$ - Vector2d s_b_e = beta.s_b_e; - - // # 2 ADDs - // $\vec{r}_{\alpha\beta} - \vec{v}_{\beta}\varDelta_{t}\vec{e}_{\beta}$ - Vector2d r_ab2 = r_ab - s_b_e; - - // # 1 ADD, 2 MULTs, 1 SQRT - // $\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert$ - double r_ab2_norm = r_ab2.norm(); - r_ab2_norm = r_ab2_norm > EPS ? r_ab2_norm : EPS; // Avoid division by zero - - // # 1 ADD - // $\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert$ - double r_ab_norm_sum = r_ab_norm + r_ab2_norm; - - // # 1 ADD, 1 MULTs, 1 SQRT - // - // $2b = \sqrt{(\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert)^2 - (v_\beta \Delta t)^2}$ - // - double two_b_sq = r_ab_norm_sum * r_ab_norm_sum - beta.s_b_sq; - two_b_sq = two_b_sq > EPS_SQ ? two_b_sq : EPS_SQ; // Avoid sqrt of negative and avoid division by zero - double two_b = sqrt(two_b_sq); - - // # 5 MULTs, 1 DIV, 1 EXP - // - // $\frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert\,\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}$ - // - double scalar_mult_common = (r_ab_norm_sum / (two_b * r_ab_norm * r_ab2_norm)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b * NEG_TWO_SIGMA_INV)); - - // # 1 MULT - // - // $\frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert}$ - // - double scalar_mult_r_ab = scalar_mult_common * r_ab2_norm; - - // # 1 MULT - // - // $\frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}$ - // - double scalar_mult_r_ab2 = scalar_mult_common * r_ab_norm; - - // # 2 ADDs, 4 MULTs - // - // $\vec{-f}_{\alpha \beta}(\vec{r}_{\alpha \beta}) = \frac{-V^0_{\alpha \beta}}{2\sigma}e^{-b / \sigma} 2\grad_{\vec{r}_{\alpha \beta}}b $ - // - // - // $= \frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert}\,\vec{r}_{\alpha \beta} + \frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} - - // v_\beta \Delta t \vec{e}_\beta \Arrowvert}\,(\vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta)$ - // - // - // - // $2\grad_{\vec{r}_{\alpha \beta}}b = \frac{(\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert)(\frac{\vec{r}_{\alpha \beta}}{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert} + \frac{\vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta}{\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert})}{2b}$ - // - // - // $= \frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert}\,\vec{r}_{\alpha \beta} + \frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}\,(\vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta)$ - // - // - Vector2d f_alpha_beta_neg = r_ab * scalar_mult_r_ab + r_ab2 * scalar_mult_r_ab2; - - // # 2 ADDs, 7 MULTs, 1 SQRT - // - // $\vec{F}_{\alpha\beta}(\vec{e}_{\alpha}, \vec{r}_{\alpha \beta}).dt = w(\vec{e}_{\alpha}, -\vec{f}_{\alpha\beta}(\vec{r}_{\alpha \beta})).\vec{f}_{\alpha\beta}(\vec{r}_{\alpha \beta}).dt$ - // - Vector2d f_alpha_beta_dt = f_alpha_beta_neg * w(alpha.e, f_alpha_beta_neg); - - return f_alpha_beta_dt; -} - -// Flop count: 10 ADDs, 18 MULTs, 1 DIVs, 2 SQRTs, 1 EXP -Vector2d obstacle_repulsion_dt(const Pedestrian &alpha, const Obstacle &B) { - - // # 7 ADDs, 5 MULTs - // $\vec{r}_{\alpha B}$ - Vector2d r_aB = alpha.curr_pos - B.find_nearest_obstacle_point(alpha.curr_pos); - - // # 1 ADD, 2 MULTs, 1 SQRT - // $\Arrowvert \vec{r}_{\alpha B} \Arrowvert$ - double r_aB_norm = r_aB.norm(); - r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; // Avoid division by zero - - // # 2 MULTs, 1 DIV, 1 EXP - // - // $\frac{-U^0_{\alpha B}}{R} e^{- \Arrowvert \vec{r}_{\alpha B} \Arrowvert / R}$ - // - double scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; - - // # 2 MULTs - // - // $-\vec{F}_{\alpha B}(\vec{r}_{\alpha B}) = \frac{-U^0_{\alpha B}}{R} e^{- \Arrowvert \vec{r}_{\alpha B} \Arrowvert / R} \frac{\vec{r}_{\alpha B}}{\Arrowvert \vec{r}_{\alpha B} \Arrowvert}$ - // - Vector2d f_alpha_B_neg = r_aB * scalar_mult; - - // # 2 ADDs, 7 MULTs, 1 SQRT - // - // $\vec{F}_{\alpha B}(\vec{e}_{\alpha}, \vec{r}_{\alpha B}).dt = w(\vec{e}_{\alpha}, -\vec{F}_{\alpha B}(\vec{r}_{\alpha B})).\vec{F}_{\alpha B}(\vec{r}_{\alpha B}).dt$ - // - Vector2d f_alpha_B_dt = f_alpha_B_neg * w(alpha.e, f_alpha_B_neg); - - return f_alpha_B_dt; -} - -// social_force_baseline.cpp - -Pedestrian *init_pedestrians(int n_p) { -#if RANDOM_SEED - random_device rd; // Platform-provided random seed source. - mt19937 gen(rd()); // Non-reproducible initialization. -#else - mt19937 gen(SEED); // Reproducible initialization. -#endif - - normal_distribution velocity_gen(v0_mean, v0_std_dev); - uniform_real_distribution y_gen(0.3, BOARD_WIDTH - 0.3); - uniform_real_distribution x_gen_left(2.0, BOARD_LENGTH / 2.0); - uniform_real_distribution x_gen_right(BOARD_LENGTH / 2.0, BOARD_LENGTH - 2.0); - - Pedestrian *P = new Pedestrian[n_p]; - - int n_p_half = n_p / 2; - - // Group of pedestrians walking from left to right. - for (int i = 0; i < n_p_half; i++) { - double x = x_gen_left(gen); - double y = y_gen(gen); - - Vector2d start_pos = Vector2d(x, y); - Vector2d destination = Vector2d(BOARD_LENGTH + 30.0, y); - - Vector2d init_e = destination - start_pos; - double init_e_norm = init_e.norm(); - Vector2d init_e_unit = init_e / init_e_norm; - - // Reject near-zero desired speeds to avoid pedestrians that barely move, - // and reject negative speeds because they would reverse the intended - // walking direction. - double desired_v0; - do { - desired_v0 = velocity_gen(gen); - } while (desired_v0 <= 0.1); - - double v_max = 1.3 * desired_v0; - - P[i] = Pedestrian(WHITE, Vector2d(), start_pos, init_e_unit, v_max, desired_v0, destination); - } - - // Group of pedestrians walking from right to left. - for (int i = n_p_half; i < n_p; i++) { - double x = x_gen_right(gen); - double y = y_gen(gen); - - Vector2d start_pos = Vector2d(x, y); - Vector2d destination = Vector2d(-30.0, y); - - Vector2d init_e = destination - start_pos; - double init_e_norm = init_e.norm(); - Vector2d init_e_unit = init_e / init_e_norm; - - // Reject near-zero desired speeds to avoid pedestrians that barely move, - // and reject negative speeds because they would reverse the intended - // walking direction. - double desired_v0; - do { - desired_v0 = velocity_gen(gen); - } while (desired_v0 <= 0.1); - - double v_max = 1.3 * desired_v0; - - P[i] = Pedestrian(BLACK, Vector2d(), start_pos, init_e_unit, v_max, desired_v0, destination); - } - - return P; -} - -Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } - -int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { - -#if BENCHMARK - // Avoid compiler unused parameter warning - (void)dump_path; -#endif - -#if !BENCHMARK - const int dump_interval = 1; - - // Each sample stores: time step, pedestrian id, x, y, e.x, e.y, color. - vector> samples; - - if (dump_path) { - samples.reserve(static_cast(n_iter / dump_interval + 1) * n_p); - - // Store the initial state before the first simulation step. - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - samples.emplace_back(0, i, p.curr_pos.x, p.curr_pos.y, p.e.x, p.e.y, p.color); - } - } -#endif - - // n_iter * [{ n_p * { [(n_p - 1) * (12 ADDs, 23 MULTs, 1 DIV, 4 SQRTs, 1 EXP + 2 ADDs)] + [n_obstacles * (10 ADDs, 18 MULTs, 1 DIV, 2 SQRTs, 1 EXP + 2 ADDs) + 4 ADDs + 4 MULTs] } } + { (7 ADDs, 16 MULTs, 2 DIVs, 3 SQRTs) * n_p }] - - - // n_iter * [{ n_p * { [(n_p - 1) * (12 A + 23 M + 1 D + 4 S + 1 E + 2 A)] + [n_obstacles * (10 A + 18 M + 1 D + 2 S + 1 E + 2 A) + 4 A + 4 M] } } + { n_p * (7 A + 16 M + 2 D + 3 S) }] - - // n_iter * [{ n_p * { n_p * (14 A + 23 M + 1 D + 4 S + 1 E) - 1 * (10 A + 19 M + 1 D + 4 S + 1 E) + n_obstacles * (12 A + 18 M + 1 D + 2 S + 1 E) }} + { n_p * (7 A + 16 M + 2 D + 3 S) }] - - - // n_iter * [ n_p ** 2 * (14 A + 23 M + 1 D + 4 S + 1 E) - n_p * (10 A + 19 M + 1 D + 4 S + 1 E) + n_obstacles * n_p * (12 A + 18 M + 1 D + 2 S + 1 E) + n_p * (7 A + 16 M + 2 D + 3 S) ] - - - // n_iter * [ n_p ** 2 * (14 A + 23 M + 1 D + 4 S + 1 E) + n_p * (- 3 A - 3 M + 1 D - 1 S - 1 E) + n_obstacles * n_p * (12 A + 18 M + 1 D + 2 S + 1 E) ] - -// NOTE: this flop count charges every ped-ped pair the full cost. The cutoff -// (L80-81) early-rejects pairs farther than 5m, so the real ped-ped work is only -// a fraction of this (roughly 40-50% on a 10x50 hallway, depending on the layout). -// We keep it at 100% here as the upper-bound / fixed-W baseline, the exact fraction -// can be folded into the n_p**2 term later if we want the actual executed flops. - - - for (int t = 0; t < n_iter; t++) { - // Pass 1: Compute all forces from the current state. - // n_p * { [(n_p - 1) * (12 ADDs, 23 MULTs, 1 DIV, 4 SQRTs, 1 EXP + 2 ADDs)] + [n_obstacles * (10 ADDs, 18 MULTs, 1 DIV, 2 SQRTs, 1 EXP + 2 ADDs) + 4 ADDs + 4 MULTs] } - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - - // # 2 ADDs, 4 MULTs - // - // $\vec{F}_\alpha(\vec{v}_\alpha, v^0_\alpha \vec{e}_\alpha) = \frac{1}{\tau_\alpha}(v^0_\alpha \vec{e}_\alpha - \vec{v}_\alpha)$ - // - Vector2d f_alpha_dt = acceleration_term_dt(p); - - // # (N-1) * (12 ADDs, 23 MULTs, 1 DIV, 4 SQRTs, 1 EXP) - // + (N-1) * 2 ADDs - // - // $\sum_{\beta} \vec{F}_{\alpha\beta}(\vec{e}_{\alpha},\vec{r}_{\alpha} - \vec{r}_{\beta})$ - // - for (int j = 0; j < n_p; j++) { - if (i == j) - continue; - - f_alpha_dt += pedestrian_repulsion_dt(p, pedestrians[j]); - } - - // # board.n_obstacles * (10 ADDs, 18 MULTs, 1 DIV, 2 SQRTs, 1 EXP) - // + board.n_obstacles * 2 ADDs - // - // $\sum_{B} \vec{F}_{\alpha B}(\vec{e}_{\alpha}, \vec{r}_{\alpha} - \vec{r}_{B})$ - // - for (int k = 0; k < board.n_obstacles; k++) { - f_alpha_dt += obstacle_repulsion_dt(p, board.obstacles[k]); - } - - // # 2 ADDs - // - // - // $\frac{d\vec{w}_\alpha}{dt} = \vec{F}_{\alpha}(t)$ - // - p.w += f_alpha_dt; - } - - // Pass 2: Update pedestrian states after all forces have been computed. - // # (7 ADDs, 16 MULTs, 2 DIVs, 3 SQRTs) * n_p - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - - // # 1 ADD, 2 MULTs, 1 SQRT - double w_norm = p.w.norm(); - - double w_norm2 = w_norm > EPS ? w_norm : EPS; // Avoid division by zero. - - // # 1 DIV - double correction_factor = std::min(1.0, p.v_max / w_norm2); - - // # 2 MULTs - p.curr_vel = p.w * correction_factor; - - // # 2 ADDs, 2 MULTs - // - // $\vec{r}_i^{t+1} = \vec{r}_i^t + \vec{v}_i^t dt$ - // - p.curr_pos = p.curr_pos + p.curr_vel * dt; - - // When a pedestrian reaches the end of the corridor, teleport them back - // to the opposite entrance while keeping the same y-coordinate. This - // maintains a constant pedestrian flow and makes lane formation easier to - // observe. - if (p.color == WHITE && p.curr_pos.x > (BOARD_LENGTH - 1.5)) { - p.curr_pos.x = 1.0; - p.destination.y = p.curr_pos.y; - p.w = Vector2d(p.desired_v0, 0.0); - p.curr_vel = p.w; - } - if (p.color == BLACK && p.curr_pos.x < 1.5) { - p.curr_pos.x = BOARD_LENGTH - 1.0; - p.destination.y = p.curr_pos.y; - p.w = Vector2d(-p.desired_v0, 0.0); - p.curr_vel = p.w; - } - - // Keep pedestrians inside the board boundaries. - p.curr_pos.y = clamp(p.curr_pos.y, WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - - // # 2 ADDs - Vector2d e = p.destination - p.curr_pos; - - // # 1 ADD, 2 MULTs, 1 DIV, 1 SQRT - double e_norm = e.norm(); - double e_norm2 = e_norm > EPS ? e_norm : EPS; // Avoid division by zero. - double e_norm_inv = 1.0 / e_norm2; - - // # 2 MULTs - p.e = e * e_norm_inv; - - // # 1 ADD, 2 MULTs - double velocity_norm_sq = p.curr_vel.dot(p.curr_vel); - - // # 1 SQRT - double velocity_norm = std::sqrt(velocity_norm_sq); - - // # 1 MULT - p.s_b_sq = velocity_norm_sq * delta_t_sq; - - // # 3 MULTs - p.s_b_e = p.e * (velocity_norm * delta_t); - -#if !BENCHMARK - // Store the current pedestrian state for visualization. - if (dump_path && (t % dump_interval == 0)) { - samples.emplace_back(t + 1, i, p.curr_pos.x, p.curr_pos.y, p.e.x, p.e.y, p.color); - } -#endif - } - } - -#if !BENCHMARK - // Export recorded simulation states to CSV. - if (dump_path) { - ofstream out(dump_path); - out << "time,id,x,y,p.e.x,p.e.y,color\n"; - - for (auto &[t, id, x, y, e_x, e_y, c] : samples) { - out << t << ',' << id << ',' << x << ',' << y << ',' << e_x << ',' << e_y << ',' << c << '\n'; - } - } -#endif - - return 0; -} \ No newline at end of file diff --git a/variants/variant_float_inlining_SoA_AVX2_flopcount.cpp b/variants/variant_float_inlining_SoA_AVX2_flopcount.cpp deleted file mode 100644 index bbc98d7..0000000 --- a/variants/variant_float_inlining_SoA_AVX2_flopcount.cpp +++ /dev/null @@ -1,449 +0,0 @@ -// # Changes: AVX2 vectorization of the ped-ped inner loop (8 floats per __m256, exp still scalar) -// # Predecessor: variant_float_inlining_SoA.cpp - -#include "../headers/board_reduced_float.hpp" -#include "../headers/constants_float.hpp" -#include "../headers/pedestrian_reduced_float.hpp" - -#include // avx2 - -#include -#include -#include -#include -#include -#include -#include -#include - -#define SEED 42 -#define BOARD_WIDTH 10.0f -#define BOARD_LENGTH 50.0f -#define WALL_EPS 1e-3f -#define BOARD_WIDTH_MINUS_WALL_EPS 9.999f - -#ifndef RANDOM_SEED -#define RANDOM_SEED 0 -#endif - -#ifndef BENCHMARK -#define BENCHMARK 0 -#endif - -using namespace std; - -// same SoA arrays as the predecessor, but we pad to multiple of 8 so the avx loop is clean -vector pos_x, pos_y; -vector sb_sq; -vector sb_e_x, sb_e_y; -vector e_x, e_y; -vector curr_vel_x, curr_vel_y; -vector w_x, w_y; -vector desired_v0; -vector v_max; -vector destination_x, destination_y; -vector color; - -Pedestrian *init_pedestrians(int n_p) { -#if RANDOM_SEED - random_device rd; - mt19937 gen(rd()); -#else - mt19937 gen(SEED); -#endif - - normal_distribution velocity_gen(v0_mean, v0_std_dev); - uniform_real_distribution y_gen(0.3, BOARD_WIDTH - 0.3); - uniform_real_distribution x_gen_left(2.0, BOARD_LENGTH / 2.0); - uniform_real_distribution x_gen_right(BOARD_LENGTH / 2.0, BOARD_LENGTH - 2.0); - - const int n_p_pad = (n_p + 7) & ~7; // round up to a multiple of 8 for avx float lanes - - pos_x.resize(n_p_pad); - pos_y.resize(n_p_pad); - sb_sq.resize(n_p_pad); - sb_e_x.resize(n_p_pad); - sb_e_y.resize(n_p_pad); - e_x.resize(n_p_pad); - e_y.resize(n_p_pad); - curr_vel_x.resize(n_p_pad); - curr_vel_y.resize(n_p_pad); - w_x.resize(n_p_pad); - w_y.resize(n_p_pad); - desired_v0.resize(n_p_pad); - v_max.resize(n_p_pad); - destination_x.resize(n_p_pad); - destination_y.resize(n_p_pad); - color.resize(n_p_pad); - - int n_p_half = n_p / 2; - - for (int i = 0; i < n_p_half; i++) { - float x = x_gen_left(gen); - float y = y_gen(gen); - - float dest_x = BOARD_LENGTH + 30.0; // renamed to avoid shadowing destination_x[] - float dest_y = y; - - float init_e_x = dest_x - x; - float init_e_y = dest_y - y; - float init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - float init_e_unit_x = init_e_x / init_e_norm; - float init_e_unit_y = init_e_y / init_e_norm; - - float d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1); - - float v_m = 1.3 * d_v0; - - color[i] = 0; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - w_x[i] = 0.0f; - w_y[i] = 0.0f; - curr_vel_x[i] = 0.0f; - curr_vel_y[i] = 0.0f; - sb_sq[i] = 0.0f; - sb_e_x[i] = 0.0f; - sb_e_y[i] = 0.0f; - } - - for (int i = n_p_half; i < n_p; i++) { - float x = x_gen_right(gen); - float y = y_gen(gen); - - float dest_x = -30; - float dest_y = y; - - float init_e_x = dest_x - x; - float init_e_y = dest_y - y; - float init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - float init_e_unit_x = init_e_x / init_e_norm; - float init_e_unit_y = init_e_y / init_e_norm; - - float d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1); - - float v_m = 1.3 * d_v0; - - color[i] = 1; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - w_x[i] = 0.0f; - w_y[i] = 0.0f; - curr_vel_x[i] = 0.0f; - curr_vel_y[i] = 0.0f; - sb_sq[i] = 0.0f; - sb_e_x[i] = 0.0f; - sb_e_y[i] = 0.0f; - } - - // padding lanes: park them far away, zero everything else. - // exp(very negative) is roughly 0 and the active mask zeroes their contribution anyway. - for (int j = n_p; j < n_p_pad; j++) { - pos_x[j] = 1e9f; - pos_y[j] = 1e9f; - sb_sq[j] = 0.0f; - sb_e_x[j] = 0.0f; - sb_e_y[j] = 0.0f; - } - return nullptr; -} - -Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } - -int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { - (void)pedestrians; -#if BENCHMARK - (void)dump_path; -#endif - -#if !BENCHMARK - const int dump_interval = 1; - - vector> samples; - - if (dump_path) { - samples.reserve(static_cast(n_iter / dump_interval + 1) * n_p); - - for (int i = 0; i < n_p; i++) { - samples.emplace_back(0, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } - } -#endif - - const int n_p_pad = (n_p + 7) & ~7; - - // {0,1,2,3,4,5,6,7} so we can build per-iter j indices as (j + lane_off) - alignas(32) const float lane_offset_arr[8] = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f}; - const __m256 lane_off = _mm256_load_ps(lane_offset_arr); - - // constants broadcast to all 8 lanes once - const __m256 v_neg_v0_div_2s = _mm256_set1_ps(NEG_V0_AB_div_TWO_SIGMA); - const __m256 v_neg_2s_inv = _mm256_set1_ps(NEG_TWO_SIGMA_INV); - const __m256 v_cos_phi_sq = _mm256_set1_ps(cos_phi_sq); - const __m256 v_dt_neg = _mm256_set1_ps(dt_neg); - const __m256 v_c_neg_dt = _mm256_set1_ps(c_neg_times_dt); - const __m256 v_zero = _mm256_setzero_ps(); - const __m256 v_one = _mm256_set1_ps(1.0f); - const __m256 v_eps = _mm256_set1_ps(EPS); - const __m256 v_eps_sq = _mm256_set1_ps(EPS_SQ); - const __m256 v_np = _mm256_set1_ps((float)n_p); - - // # flops per iteration (one pass of the outer time loop): - // # ADDs: n_p * 22 + n_p * n_p_pad * 15 + n_p * board.n_obstacles * 10 + n_p * 7 - // # MULTs: n_p * 4 + n_p * n_p_pad * 24 + n_p * board.n_obstacles * 13 + n_p * 16 - // # DIVs: n_p * n_p_pad * 1 + n_p * board.n_obstacles + n_p * 2 - // # SQRTs: n_p * n_p_pad * 3 + n_p * board.n_obstacles + n_p * 3 - // # EXPs: n_p * n_p_pad * 1 + n_p * board.n_obstacles - for (int t = 0; t < n_iter; t++) { - - for (int i = 0; i < n_p; i++) { - - float desired_velocity_x = e_x[i] * desired_v0[i]; // # 1 MULT - float desired_velocity_y = e_y[i] * desired_v0[i]; // # 1 MULT - - float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; // # 1 MULT, 1 ADD - float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; // # 1 MULT, 1 ADD - - // i is fixed for the inner loops, broadcast its fields once - const __m256 pix = _mm256_set1_ps(pos_x[i]); - const __m256 piy = _mm256_set1_ps(pos_y[i]); - const __m256 eix = _mm256_set1_ps(e_x[i]); - const __m256 eiy = _mm256_set1_ps(e_y[i]); - const __m256 v_i = _mm256_set1_ps((float)i); - - __m256 acc_x = _mm256_setzero_ps(); - __m256 acc_y = _mm256_setzero_ps(); - - for (int j = 0; j < n_p_pad; j += 8) { - // 8 lanes at once, lane k maps to pedestrian j+k - __m256 j_idx = _mm256_add_ps(_mm256_set1_ps((float)j), lane_off); // # 8 ADDs - - // active = (j+k != i) AND (j+k < n_p), zero in lanes we wanna skip - __m256 m_neq_i = _mm256_cmp_ps(j_idx, v_i, _CMP_NEQ_OQ); - __m256 m_in_range = _mm256_cmp_ps(j_idx, v_np, _CMP_LT_OQ); - __m256 active = _mm256_and_ps(m_neq_i, m_in_range); - - // j-side loads, SoA is contiguous. loadu because std::vector only guarantees 16B align - __m256 pjx = _mm256_loadu_ps(&pos_x[j]); - __m256 pjy = _mm256_loadu_ps(&pos_y[j]); - __m256 sbe_jx = _mm256_loadu_ps(&sb_e_x[j]); - __m256 sbe_jy = _mm256_loadu_ps(&sb_e_y[j]); - __m256 sb_jsq = _mm256_loadu_ps(&sb_sq[j]); - - // r_ab = pos_i - pos_j ; |r_ab| with the EPS clamp the scalar version does - __m256 r_ab_x = _mm256_sub_ps(pix, pjx); // # 8 ADDs - __m256 r_ab_y = _mm256_sub_ps(piy, pjy); // # 8 ADDs - __m256 r_ab_n2 = _mm256_fmadd_ps(r_ab_x, r_ab_x, _mm256_mul_ps(r_ab_y, r_ab_y)); // # 16 MULTs, 8 ADDs - __m256 r_ab_n = _mm256_sqrt_ps(r_ab_n2); // # 8 SQRTs - r_ab_n = _mm256_max_ps(r_ab_n, v_eps); - - // r_ab2 = r_ab - sb_e_j ; |r_ab2| also clamped - __m256 r_ab2_x = _mm256_sub_ps(r_ab_x, sbe_jx); // # 8 ADDs - __m256 r_ab2_y = _mm256_sub_ps(r_ab_y, sbe_jy); // # 8 ADDs - __m256 r_ab2_n2 = _mm256_fmadd_ps(r_ab2_x, r_ab2_x, _mm256_mul_ps(r_ab2_y, r_ab2_y)); // # 16 MULTs, 8 ADDs - __m256 r_ab2_n = _mm256_sqrt_ps(r_ab2_n2); // # 8 SQRTs - r_ab2_n = _mm256_max_ps(r_ab2_n, v_eps); - - // 2b = sqrt((|r_ab| + |r_ab2|)^2 - sb_sq_j) ; clamp the inside with EPS_SQ - __m256 r_sum = _mm256_add_ps(r_ab_n, r_ab2_n); // # 8 ADDs - __m256 two_b_sq = _mm256_fmsub_ps(r_sum, r_sum, sb_jsq); // # 8 MULTs, 8 ADDs - two_b_sq = _mm256_max_ps(two_b_sq, v_eps_sq); - __m256 two_b = _mm256_sqrt_ps(two_b_sq); // # 8 SQRTs - - // exp scalar fallback. manually unrolled, otherwise gcc keeps it as a loop with - // one expf call and serialises all 8 (the double avx2 with 4 iters does get unrolled, the 8 here doesn't). - __m256 e_arg = _mm256_mul_ps(two_b, v_neg_2s_inv); // # 8 MULTs - alignas(32) float tmp_arg[8], tmp_val[8]; - _mm256_store_ps(tmp_arg, e_arg); - tmp_val[0] = expf(tmp_arg[0]); - tmp_val[1] = expf(tmp_arg[1]); - tmp_val[2] = expf(tmp_arg[2]); - tmp_val[3] = expf(tmp_arg[3]); - tmp_val[4] = expf(tmp_arg[4]); - tmp_val[5] = expf(tmp_arg[5]); - tmp_val[6] = expf(tmp_arg[6]); - tmp_val[7] = expf(tmp_arg[7]); // # 8 EXPs (1 per lane, scalar) - __m256 e_val = _mm256_load_ps(tmp_val); - - // smc = (r_sum * NEG_V0_AB_div_TWO_SIGMA * e_val) / (two_b * r_ab_n * r_ab2_n) - // i==j and padding lanes collapse the denom, so we swap in 1.0 there to keep smc finite. - // the AND with active below zeroes those lanes anyway. - __m256 numer = _mm256_mul_ps(_mm256_mul_ps(r_sum, v_neg_v0_div_2s), e_val); // # 16 MULTs - __m256 denom = _mm256_mul_ps(_mm256_mul_ps(two_b, r_ab_n), r_ab2_n); // # 16 MULTs - __m256 denom_safe = _mm256_blendv_ps(v_one, denom, active); // bitwise, no flop - __m256 smc = _mm256_div_ps(numer, denom_safe); // # 8 DIVs - - __m256 sm_r_ab = _mm256_mul_ps(smc, r_ab2_n); // # 8 MULTs - __m256 sm_r_ab2 = _mm256_mul_ps(smc, r_ab_n); // # 8 MULTs - - // scalar: f_x = r_ab_x * sm_r_ab + r_ab2_x * sm_r_ab2 - __m256 f_x = _mm256_fmadd_ps(r_ab2_x, sm_r_ab2, _mm256_mul_ps(r_ab_x, sm_r_ab)); // # 16 MULTs, 8 ADDs - __m256 f_y = _mm256_fmadd_ps(r_ab2_y, sm_r_ab2, _mm256_mul_ps(r_ab_y, sm_r_ab)); // # 16 MULTs, 8 ADDs - - // float w_val: default dt_neg, switch to c_neg_times_dt when - //(e_dot_f < 0 AND e_dot_f_sq > f_norm_sq * cos_phi_sq). - // this is the DeMorgan of the scalar's if (e_dot_f >= 0 || e_dot_f_sq <= rhs) - __m256 f_norm_sq = _mm256_fmadd_ps(f_x, f_x, _mm256_mul_ps(f_y, f_y)); // # 16 MULTs, 8 ADDs - __m256 rhs = _mm256_mul_ps(f_norm_sq, v_cos_phi_sq); // # 8 MULTs - __m256 e_dot_f = _mm256_fmadd_ps(eix, f_x, _mm256_mul_ps(eiy, f_y)); // # 16 MULTs, 8 ADDs - __m256 e_dot_f_sq = _mm256_mul_ps(e_dot_f, e_dot_f); // # 8 MULTs - - __m256 c1 = _mm256_cmp_ps(e_dot_f, v_zero, _CMP_LT_OQ); - __m256 c2 = _mm256_cmp_ps(e_dot_f_sq, rhs, _CMP_GT_OQ); - __m256 cond = _mm256_and_ps(c1, c2); - __m256 w_val = _mm256_blendv_ps(v_dt_neg, v_c_neg_dt, cond); - - // mask out i==j lane and padding before accumulating. - // AND with all-zeros = 0, AND with all-ones passes through, cheaper than blendv here. - __m256 f_x_safe = _mm256_and_ps(f_x, active); // bitwise, no flop - __m256 f_y_safe = _mm256_and_ps(f_y, active); // bitwise, no flop - acc_x = _mm256_fmadd_ps(f_x_safe, w_val, acc_x); // # 8 MULTs, 8 ADDs - acc_y = _mm256_fmadd_ps(f_y_safe, w_val, acc_y); // # 8 MULTs, 8 ADDs - } - - // horizontal sum of acc_x and acc_y at the same time - __m256 hsum = _mm256_hadd_ps(acc_x, acc_y); // # 8 ADDs (x and y interleaved) - __m128 hsum_lo = _mm256_castps256_ps128(hsum); - __m128 hsum_hi = _mm256_extractf128_ps(hsum, 1); - __m128 sum4 = _mm_add_ps(hsum_lo, hsum_hi); // # 4 ADDs - sum4 = _mm_hadd_ps(sum4, sum4); // # 4 ADDs (total hadd: 16 ADDs for x+y) - alignas(16) float sum_out[4]; - _mm_store_ps(sum_out, sum4); - f_alpha_dt_x += sum_out[0]; // # 1 ADD - f_alpha_dt_y += sum_out[1]; // # 1 ADD - - // obstacle loop kept scalar, board.n_obstacles is 0 in this setup anyway - for (int k = 0; k < board.n_obstacles; k++) { - - float v1_x = pos_x[i] - board.obstacles[k].start_x; // # 1 ADD - float v1_y = pos_y[i] - board.obstacles[k].start_y; // # 1 ADD - float v2_x = board.obstacles[k].obstacle_v_x; - float v2_y = board.obstacles[k].obstacle_v_y; - - float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; // # 3 MULTs, 1 ADD - - if (projection < 0.0) - projection = 0.0; - else if (projection > 1.0) - projection = 1.0; - - float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); // # 1 MULT, 2 ADDs - float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); // # 1 MULT, 2 ADDs - - float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); // # 2 MULTs, 1 ADD, 1 SQRT - r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; - - float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; // # 2 MULTs, 1 EXP, 1 DIV - float f_alpha_B_neg_x = r_aB_x * scalar_mult; // # 1 MULT - float f_alpha_B_neg_y = r_aB_y * scalar_mult; // # 1 MULT - - float w_val; - - float e_dot_f = (f_alpha_B_neg_y == 0) ? 0 : (f_alpha_B_neg_y < 0 ? -e_y[i] : e_y[i]); - - if (e_dot_f >= cos_phi) - w_val = dt_neg; - else - w_val = c_neg_times_dt; - - float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; // # 1 MULT - float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; // # 1 MULT - - f_alpha_dt_x += f_alpha_B_dt_x; // # 1 ADD - f_alpha_dt_y += f_alpha_B_dt_y; // # 1 ADD - } - - w_x[i] += f_alpha_dt_x; // # 1 ADD - w_y[i] += f_alpha_dt_y; // # 1 ADD - } - - // position update loop stays scalar, same as the double AVX2 variant does - for (int i = 0; i < n_p; i++) { - - float w_norm = sqrt(w_x[i] * w_x[i] + w_y[i] * w_y[i]); // # 2 MULTs, 1 ADD, 1 SQRT - float w_norm2 = w_norm > EPS ? w_norm : EPS; - float correction_factor = min(1.0f, v_max[i] / w_norm2); // # 1 DIV - - curr_vel_x[i] = w_x[i] * correction_factor; // # 1 MULT - curr_vel_y[i] = w_y[i] * correction_factor; // # 1 MULT - - pos_x[i] = pos_x[i] + curr_vel_x[i] * dt; // # 1 MULT, 1 ADD - pos_y[i] = pos_y[i] + curr_vel_y[i] * dt; // # 1 MULT, 1 ADD - - if (color[i] == 0 && pos_x[i] > (BOARD_LENGTH - 1.5)) { - pos_x[i] = 1.0; - destination_y[i] = pos_y[i]; - w_x[i] = desired_v0[i]; - w_y[i] = 0.0; - curr_vel_x[i] = w_x[i]; - curr_vel_y[i] = w_y[i]; - } - if (color[i] == 1 && pos_x[i] < 1.5) { - pos_x[i] = BOARD_LENGTH - 1.0; - destination_y[i] = pos_y[i]; - w_x[i] = -desired_v0[i]; - w_y[i] = 0.0; - curr_vel_x[i] = w_x[i]; - curr_vel_y[i] = w_y[i]; - } - - pos_y[i] = clamp(pos_y[i], WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - - float ex = destination_x[i] - pos_x[i]; // # 1 ADD - float ey = destination_y[i] - pos_y[i]; // # 1 ADD - - float e_norm = sqrt(ex * ex + ey * ey); // # 2 MULTs, 1 ADD, 1 SQRT - float e_norm2 = e_norm > EPS ? e_norm : EPS; - float e_norm_inv = 1.0 / e_norm2; // # 1 DIV - - e_x[i] = ex * e_norm_inv; // # 1 MULT - e_y[i] = ey * e_norm_inv; // # 1 MULT - - float velocity_norm_sq = curr_vel_x[i] * curr_vel_x[i] + curr_vel_y[i] * curr_vel_y[i]; // # 2 MULTs, 1 ADD - float velocity_norm = sqrt(velocity_norm_sq); // # 1 SQRT - - sb_sq[i] = velocity_norm_sq * delta_t_sq; // # 1 MULT - sb_e_x[i] = e_x[i] * (velocity_norm * delta_t); // # 2 MULTs (vel_norm*delta_t shared with next line) - sb_e_y[i] = e_y[i] * (velocity_norm * delta_t); // # 1 MULT - -#if !BENCHMARK - if (dump_path && (t % dump_interval == 0)) { - samples.emplace_back(t + 1, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } -#endif - } - } - -#if !BENCHMARK - if (dump_path) { - ofstream out(dump_path); - out << "time,id,x,y,p.e.x,p.e.y,color\n"; - - for (auto &[t, id, x, y, e_x, e_y, c] : samples) { - out << t << ',' << id << ',' << x << ',' << y << ',' << e_x << ',' << e_y << ',' << c << '\n'; - } - } -#endif - - return 0; -} diff --git a/variants/variant_float_inlining_SoA_AVX2_polyexp.cpp b/variants/variant_float_inlining_SoA_AVX2_polyexp.cpp index bff9db4..f0a8056 100644 --- a/variants/variant_float_inlining_SoA_AVX2_polyexp.cpp +++ b/variants/variant_float_inlining_SoA_AVX2_polyexp.cpp @@ -170,46 +170,55 @@ Pedestrian *init_pedestrians(int n_p) { Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } -// vectorized expf for a __m256 (8 lanes), no libm call. -// same trick as the double polyexp: exp(x) = 2^n * exp(r) where n = round(x / ln2), r = x - n*ln2. -// after range reduce r is in [-ln2/2, ln2/2] ~= [-0.347, 0.347]. -// degree-5 taylor is enough for float (worst-case abs error ~1e-5, way under 1cm verify tolerance). -// 2^n is free via the schraudolph bit trick on the ieee 754 exponent slot. -// float layout: sign(1) | exp(8, bias 127) | mantissa(23), so we shift the biased exponent by 23. +// simd expf, degree-12 taylor on the [-ln2/2, ln2/2] reduced range, +// schraudolph 2^n bit trick on the exponent slot. +// # 128 MULTs, 112 ADDs static inline __m256 exp256_ps(__m256 x) { - // n = round(x * log2(e)) const __m256 log2e = _mm256_set1_ps(1.4426950408889634f); - __m256 nf = _mm256_round_ps(_mm256_mul_ps(x, log2e), - _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); + __m256 nf = _mm256_round_ps(_mm256_mul_ps(x, log2e), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); // # 8 MULTs - // r = x - n * ln(2) const __m256 ln2 = _mm256_set1_ps(0.6931471805599453f); - __m256 r = _mm256_fnmadd_ps(nf, ln2, x); + __m256 r = _mm256_fnmadd_ps(nf, ln2, x); // # 8 MULTs, 8 ADDs - // poly(r) ~ exp(r), degree-5 horner from highest coeff downwards - const __m256 c5 = _mm256_set1_ps(1.0f / 120.0f); - const __m256 c4 = _mm256_set1_ps(1.0f / 24.0f); - const __m256 c3 = _mm256_set1_ps(1.0f / 6.0f); - const __m256 c2 = _mm256_set1_ps(0.5f); - const __m256 c1 = _mm256_set1_ps(1.0f); - const __m256 c0 = _mm256_set1_ps(1.0f); + const __m256 c13 = _mm256_set1_ps(c13_scalar); + const __m256 c12 = _mm256_set1_ps(c12_scalar); + const __m256 c11 = _mm256_set1_ps(c11_scalar); + const __m256 c10 = _mm256_set1_ps(c10_scalar); + const __m256 c9 = _mm256_set1_ps(c9_scalar); + const __m256 c8 = _mm256_set1_ps(c8_scalar); + const __m256 c7 = _mm256_set1_ps(c7_scalar); + const __m256 c6 = _mm256_set1_ps(c6_scalar); + const __m256 c5 = _mm256_set1_ps(c5_scalar); + const __m256 c4 = _mm256_set1_ps(c4_scalar); + const __m256 c3 = _mm256_set1_ps(c3_scalar); + const __m256 c2 = _mm256_set1_ps(c2_scalar); + const __m256 c1 = _mm256_set1_ps(c1_scalar); + const __m256 c0 = _mm256_set1_ps(c0_scalar); - __m256 p = c5; + __m256 p = c13; + + // # 13 * (8 MULTs, 8 ADDs) + // # = 104 MULTs, 104 ADDs + p = _mm256_fmadd_ps(p, r, c12); + p = _mm256_fmadd_ps(p, r, c11); + p = _mm256_fmadd_ps(p, r, c10); + p = _mm256_fmadd_ps(p, r, c9); + p = _mm256_fmadd_ps(p, r, c8); + p = _mm256_fmadd_ps(p, r, c7); + p = _mm256_fmadd_ps(p, r, c6); + p = _mm256_fmadd_ps(p, r, c5); p = _mm256_fmadd_ps(p, r, c4); p = _mm256_fmadd_ps(p, r, c3); p = _mm256_fmadd_ps(p, r, c2); p = _mm256_fmadd_ps(p, r, c1); p = _mm256_fmadd_ps(p, r, c0); - // 2^n via bit trick: float bias 127, exponent slot at bit 23. - // padding lanes (sb_e=0, pos=1e9) overflow this, but the active mask zeroes them out - // before accumulation so the garbage doesnt matter. - __m256i ni = _mm256_cvtps_epi32(nf); + __m256i ni = _mm256_cvtps_epi32(nf); __m256i biased = _mm256_add_epi32(ni, _mm256_set1_epi32(127)); __m256i scaled = _mm256_slli_epi32(biased, 23); - __m256 pow2n = _mm256_castsi256_ps(scaled); + __m256 pow2n = _mm256_castsi256_ps(scaled); - return _mm256_mul_ps(p, pow2n); + return _mm256_mul_ps(p, pow2n); // # 8 MULTs } int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { @@ -249,15 +258,21 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c const __m256 v_np = _mm256_set1_ps((float)n_p); const __m256 v_exp_min = _mm256_set1_ps(-87.0f); // clamp for polyexp, below this exp(x) ~ 0 anyway + // # flops per iteration (one pass of the outer time loop): + // # ADDs: n_p * 22 + n_p * n_p_pad * 29 + n_p * board.n_obstacles * 10 + n_p * 7 + // # MULTs: n_p * 4 + n_p * n_p_pad * 40 + n_p * board.n_obstacles * 13 + n_p * 16 + // # DIVs: n_p * n_p_pad * 1 + n_p * board.n_obstacles + n_p * 2 + // # SQRTs: n_p * n_p_pad * 3 + n_p * board.n_obstacles + n_p * 3 + // # EXPs: n_p * board.n_obstacles for (int t = 0; t < n_iter; t++) { for (int i = 0; i < n_p; i++) { - float desired_velocity_x = e_x[i] * desired_v0[i]; - float desired_velocity_y = e_y[i] * desired_v0[i]; + float desired_velocity_x = e_x[i] * desired_v0[i]; // # 1 MULT + float desired_velocity_y = e_y[i] * desired_v0[i]; // # 1 MULT - float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; - float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; + float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; // # 1 MULT, 1 ADD + float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; // # 1 MULT, 1 ADD const __m256 pix = _mm256_set1_ps(pos_x[i]); const __m256 piy = _mm256_set1_ps(pos_y[i]); @@ -269,7 +284,7 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m256 acc_y = _mm256_setzero_ps(); for (int j = 0; j < n_p_pad; j += 8) { - __m256 j_idx = _mm256_add_ps(_mm256_set1_ps((float)j), lane_off); + __m256 j_idx = _mm256_add_ps(_mm256_set1_ps((float)j), lane_off); // # 8 ADDs __m256 m_neq_i = _mm256_cmp_ps(j_idx, v_i, _CMP_NEQ_OQ); __m256 m_in_range = _mm256_cmp_ps(j_idx, v_np, _CMP_LT_OQ); @@ -281,90 +296,90 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m256 sbe_jy = _mm256_loadu_ps(&sb_e_y[j]); __m256 sb_jsq = _mm256_loadu_ps(&sb_sq[j]); - __m256 r_ab_x = _mm256_sub_ps(pix, pjx); - __m256 r_ab_y = _mm256_sub_ps(piy, pjy); - __m256 r_ab_n2 = _mm256_fmadd_ps(r_ab_x, r_ab_x, _mm256_mul_ps(r_ab_y, r_ab_y)); - __m256 r_ab_n = _mm256_sqrt_ps(r_ab_n2); + __m256 r_ab_x = _mm256_sub_ps(pix, pjx); // # 8 ADDs + __m256 r_ab_y = _mm256_sub_ps(piy, pjy); // # 8 ADDs + __m256 r_ab_n2 = _mm256_fmadd_ps(r_ab_x, r_ab_x, _mm256_mul_ps(r_ab_y, r_ab_y)); // # 16 MULTs, 8 ADDs + __m256 r_ab_n = _mm256_sqrt_ps(r_ab_n2); // # 8 SQRTs r_ab_n = _mm256_max_ps(r_ab_n, v_eps); - __m256 r_ab2_x = _mm256_sub_ps(r_ab_x, sbe_jx); - __m256 r_ab2_y = _mm256_sub_ps(r_ab_y, sbe_jy); - __m256 r_ab2_n2 = _mm256_fmadd_ps(r_ab2_x, r_ab2_x, _mm256_mul_ps(r_ab2_y, r_ab2_y)); - __m256 r_ab2_n = _mm256_sqrt_ps(r_ab2_n2); + __m256 r_ab2_x = _mm256_sub_ps(r_ab_x, sbe_jx); // # 8 ADDs + __m256 r_ab2_y = _mm256_sub_ps(r_ab_y, sbe_jy); // # 8 ADDs + __m256 r_ab2_n2 = _mm256_fmadd_ps(r_ab2_x, r_ab2_x, _mm256_mul_ps(r_ab2_y, r_ab2_y)); // # 16 MULTs, 8 ADDs + __m256 r_ab2_n = _mm256_sqrt_ps(r_ab2_n2); // # 8 SQRTs r_ab2_n = _mm256_max_ps(r_ab2_n, v_eps); - __m256 r_sum = _mm256_add_ps(r_ab_n, r_ab2_n); - __m256 two_b_sq = _mm256_fmsub_ps(r_sum, r_sum, sb_jsq); + __m256 r_sum = _mm256_add_ps(r_ab_n, r_ab2_n); // # 8 ADDs + __m256 two_b_sq = _mm256_fmsub_ps(r_sum, r_sum, sb_jsq); // # 8 MULTs, 8 ADDs two_b_sq = _mm256_max_ps(two_b_sq, v_eps_sq); - __m256 two_b = _mm256_sqrt_ps(two_b_sq); + __m256 two_b = _mm256_sqrt_ps(two_b_sq); // # 8 SQRTs // simd polynomial expf, no libm call. replaces the 8-iter scalar loop that gcc refused to unroll. // clamp e_arg >= -87 first: exp(-87) ~ 1.6e-38 is already basically 0, and the schraudolph 2^n // bit trick blows up if (nf + 127) goes negative (which happens for padding lanes where e_arg ~ -4.7e9). - __m256 e_arg = _mm256_mul_ps(two_b, v_neg_2s_inv); + __m256 e_arg = _mm256_mul_ps(two_b, v_neg_2s_inv); // # 8 MULTs e_arg = _mm256_max_ps(e_arg, v_exp_min); - __m256 e_val = exp256_ps(e_arg); + __m256 e_val = exp256_ps(e_arg); // # 128 MULTs, 112 ADDs - __m256 numer = _mm256_mul_ps(_mm256_mul_ps(r_sum, v_neg_v0_div_2s), e_val); - __m256 denom = _mm256_mul_ps(_mm256_mul_ps(two_b, r_ab_n), r_ab2_n); - __m256 denom_safe = _mm256_blendv_ps(v_one, denom, active); - __m256 smc = _mm256_div_ps(numer, denom_safe); + __m256 numer = _mm256_mul_ps(_mm256_mul_ps(r_sum, v_neg_v0_div_2s), e_val); // # 16 MULTs + __m256 denom = _mm256_mul_ps(_mm256_mul_ps(two_b, r_ab_n), r_ab2_n); // # 16 MULTs + __m256 denom_safe = _mm256_blendv_ps(v_one, denom, active); // bitwise, no flop + __m256 smc = _mm256_div_ps(numer, denom_safe); // # 8 DIVs - __m256 sm_r_ab = _mm256_mul_ps(smc, r_ab2_n); - __m256 sm_r_ab2 = _mm256_mul_ps(smc, r_ab_n); + __m256 sm_r_ab = _mm256_mul_ps(smc, r_ab2_n); // # 8 MULTs + __m256 sm_r_ab2 = _mm256_mul_ps(smc, r_ab_n); // # 8 MULTs - __m256 f_x = _mm256_fmadd_ps(r_ab2_x, sm_r_ab2, _mm256_mul_ps(r_ab_x, sm_r_ab)); - __m256 f_y = _mm256_fmadd_ps(r_ab2_y, sm_r_ab2, _mm256_mul_ps(r_ab_y, sm_r_ab)); + __m256 f_x = _mm256_fmadd_ps(r_ab2_x, sm_r_ab2, _mm256_mul_ps(r_ab_x, sm_r_ab)); // # 16 MULTs, 8 ADDs + __m256 f_y = _mm256_fmadd_ps(r_ab2_y, sm_r_ab2, _mm256_mul_ps(r_ab_y, sm_r_ab)); // # 16 MULTs, 8 ADDs - __m256 f_norm_sq = _mm256_fmadd_ps(f_x, f_x, _mm256_mul_ps(f_y, f_y)); - __m256 rhs = _mm256_mul_ps(f_norm_sq, v_cos_phi_sq); - __m256 e_dot_f = _mm256_fmadd_ps(eix, f_x, _mm256_mul_ps(eiy, f_y)); - __m256 e_dot_f_sq = _mm256_mul_ps(e_dot_f, e_dot_f); + __m256 f_norm_sq = _mm256_fmadd_ps(f_x, f_x, _mm256_mul_ps(f_y, f_y)); // # 16 MULTs, 8 ADDs + __m256 rhs = _mm256_mul_ps(f_norm_sq, v_cos_phi_sq); // # 8 MULTs + __m256 e_dot_f = _mm256_fmadd_ps(eix, f_x, _mm256_mul_ps(eiy, f_y)); // # 16 MULTs, 8 ADDs + __m256 e_dot_f_sq = _mm256_mul_ps(e_dot_f, e_dot_f); // # 8 MULTs __m256 c1 = _mm256_cmp_ps(e_dot_f, v_zero, _CMP_LT_OQ); __m256 c2 = _mm256_cmp_ps(e_dot_f_sq, rhs, _CMP_GT_OQ); __m256 cond = _mm256_and_ps(c1, c2); __m256 w_val = _mm256_blendv_ps(v_dt_neg, v_c_neg_dt, cond); - __m256 f_x_safe = _mm256_and_ps(f_x, active); - __m256 f_y_safe = _mm256_and_ps(f_y, active); - acc_x = _mm256_fmadd_ps(f_x_safe, w_val, acc_x); - acc_y = _mm256_fmadd_ps(f_y_safe, w_val, acc_y); + __m256 f_x_safe = _mm256_and_ps(f_x, active); // bitwise, no flop + __m256 f_y_safe = _mm256_and_ps(f_y, active); // bitwise, no flop + acc_x = _mm256_fmadd_ps(f_x_safe, w_val, acc_x); // # 8 MULTs, 8 ADDs + acc_y = _mm256_fmadd_ps(f_y_safe, w_val, acc_y); // # 8 MULTs, 8 ADDs } - __m256 hsum = _mm256_hadd_ps(acc_x, acc_y); + __m256 hsum = _mm256_hadd_ps(acc_x, acc_y); // # 8 ADDs __m128 hsum_lo = _mm256_castps256_ps128(hsum); __m128 hsum_hi = _mm256_extractf128_ps(hsum, 1); - __m128 sum4 = _mm_add_ps(hsum_lo, hsum_hi); - sum4 = _mm_hadd_ps(sum4, sum4); + __m128 sum4 = _mm_add_ps(hsum_lo, hsum_hi); // # 4 ADDs + sum4 = _mm_hadd_ps(sum4, sum4); // # 4 ADDs alignas(16) float sum_out[4]; _mm_store_ps(sum_out, sum4); - f_alpha_dt_x += sum_out[0]; - f_alpha_dt_y += sum_out[1]; + f_alpha_dt_x += sum_out[0]; // # 1 ADD + f_alpha_dt_y += sum_out[1]; // # 1 ADD for (int k = 0; k < board.n_obstacles; k++) { - float v1_x = pos_x[i] - board.obstacles[k].start_x; - float v1_y = pos_y[i] - board.obstacles[k].start_y; + float v1_x = pos_x[i] - board.obstacles[k].start_x; // # 1 ADD + float v1_y = pos_y[i] - board.obstacles[k].start_y; // # 1 ADD float v2_x = board.obstacles[k].obstacle_v_x; float v2_y = board.obstacles[k].obstacle_v_y; - float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; + float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; // # 3 MULTs, 1 ADD if (projection < 0.0) projection = 0.0; else if (projection > 1.0) projection = 1.0; - float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); - float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); + float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); // # 1 MULT, 2 ADDs + float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); // # 1 MULT, 2 ADDs - float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); + float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); // # 2 MULTs, 1 ADD, 1 SQRT r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; - float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; - float f_alpha_B_neg_x = r_aB_x * scalar_mult; - float f_alpha_B_neg_y = r_aB_y * scalar_mult; + float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; // # 2 MULTs, 1 EXP, 1 DIV + float f_alpha_B_neg_x = r_aB_x * scalar_mult; // # 1 MULT + float f_alpha_B_neg_y = r_aB_y * scalar_mult; // # 1 MULT float w_val; @@ -375,28 +390,28 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c else w_val = c_neg_times_dt; - float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; - float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; + float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; // # 1 MULT + float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; // # 1 MULT - f_alpha_dt_x += f_alpha_B_dt_x; - f_alpha_dt_y += f_alpha_B_dt_y; + f_alpha_dt_x += f_alpha_B_dt_x; // # 1 ADD + f_alpha_dt_y += f_alpha_B_dt_y; // # 1 ADD } - w_x[i] += f_alpha_dt_x; - w_y[i] += f_alpha_dt_y; + w_x[i] += f_alpha_dt_x; // # 1 ADD + w_y[i] += f_alpha_dt_y; // # 1 ADD } for (int i = 0; i < n_p; i++) { - float w_norm = sqrt(w_x[i] * w_x[i] + w_y[i] * w_y[i]); + float w_norm = sqrt(w_x[i] * w_x[i] + w_y[i] * w_y[i]); // # 2 MULTs, 1 ADD, 1 SQRT float w_norm2 = w_norm > EPS ? w_norm : EPS; - float correction_factor = min(1.0f, v_max[i] / w_norm2); + float correction_factor = min(1.0f, v_max[i] / w_norm2); // # 1 DIV - curr_vel_x[i] = w_x[i] * correction_factor; - curr_vel_y[i] = w_y[i] * correction_factor; + curr_vel_x[i] = w_x[i] * correction_factor; // # 1 MULT + curr_vel_y[i] = w_y[i] * correction_factor; // # 1 MULT - pos_x[i] = pos_x[i] + curr_vel_x[i] * dt; - pos_y[i] = pos_y[i] + curr_vel_y[i] * dt; + pos_x[i] = pos_x[i] + curr_vel_x[i] * dt; // # 1 MULT, 1 ADD + pos_y[i] = pos_y[i] + curr_vel_y[i] * dt; // # 1 MULT, 1 ADD if (color[i] == 0 && pos_x[i] > (BOARD_LENGTH - 1.5)) { pos_x[i] = 1.0; @@ -417,22 +432,22 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c pos_y[i] = clamp(pos_y[i], WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - float ex = destination_x[i] - pos_x[i]; - float ey = destination_y[i] - pos_y[i]; + float ex = destination_x[i] - pos_x[i]; // # 1 ADD + float ey = destination_y[i] - pos_y[i]; // # 1 ADD - float e_norm = sqrt(ex * ex + ey * ey); + float e_norm = sqrt(ex * ex + ey * ey); // # 2 MULTs, 1 ADD, 1 SQRT float e_norm2 = e_norm > EPS ? e_norm : EPS; - float e_norm_inv = 1.0 / e_norm2; + float e_norm_inv = 1.0 / e_norm2; // # 1 DIV - e_x[i] = ex * e_norm_inv; - e_y[i] = ey * e_norm_inv; + e_x[i] = ex * e_norm_inv; // # 1 MULT + e_y[i] = ey * e_norm_inv; // # 1 MULT - float velocity_norm_sq = curr_vel_x[i] * curr_vel_x[i] + curr_vel_y[i] * curr_vel_y[i]; - float velocity_norm = sqrt(velocity_norm_sq); + float velocity_norm_sq = curr_vel_x[i] * curr_vel_x[i] + curr_vel_y[i] * curr_vel_y[i]; // # 2 MULTs, 1 ADD + float velocity_norm = sqrt(velocity_norm_sq); // # 1 SQRT - sb_sq[i] = velocity_norm_sq * delta_t_sq; - sb_e_x[i] = e_x[i] * (velocity_norm * delta_t); - sb_e_y[i] = e_y[i] * (velocity_norm * delta_t); + sb_sq[i] = velocity_norm_sq * delta_t_sq; // # 1 MULT + sb_e_x[i] = e_x[i] * (velocity_norm * delta_t); // # 2 MULTs (vel_norm*delta_t shared with next line) + sb_e_y[i] = e_y[i] * (velocity_norm * delta_t); // # 1 MULT #if !BENCHMARK if (dump_path && (t % dump_interval == 0)) { diff --git a/variants/variant_float_inlining_SoA_AVX2_polyexp_expfix.cpp b/variants/variant_float_inlining_SoA_AVX2_polyexp_expfix.cpp deleted file mode 100644 index 572a2bc..0000000 --- a/variants/variant_float_inlining_SoA_AVX2_polyexp_expfix.cpp +++ /dev/null @@ -1,472 +0,0 @@ -// # Changes: simd polynomial expf, replaces the 8 scalar expf calls in the j loop -// # Predecessor: variant_float_inlining_SoA_AVX2.cpp - -// the for-loop of 8 scalar expf calls was serialised by gcc (it didnt unroll), big perf hit. -// replace with one inlined simd polynomial approx, no libm call at all. - -#include "../headers/board_reduced_float.hpp" -#include "../headers/constants_float.hpp" -#include "../headers/pedestrian_reduced_float.hpp" - -#include // avx2 - -#include -#include -#include -#include -#include -#include -#include -#include - -#define SEED 42 -#define BOARD_WIDTH 10.0f -#define BOARD_LENGTH 50.0f -#define WALL_EPS 1e-3f -#define BOARD_WIDTH_MINUS_WALL_EPS 9.999f - -#ifndef RANDOM_SEED -#define RANDOM_SEED 0 -#endif - -#ifndef BENCHMARK -#define BENCHMARK 0 -#endif - -using namespace std; - -vector pos_x, pos_y; -vector sb_sq; -vector sb_e_x, sb_e_y; -vector e_x, e_y; -vector curr_vel_x, curr_vel_y; -vector w_x, w_y; -vector desired_v0; -vector v_max; -vector destination_x, destination_y; -vector color; - -Pedestrian *init_pedestrians(int n_p) { -#if RANDOM_SEED - random_device rd; - mt19937 gen(rd()); -#else - mt19937 gen(SEED); -#endif - - normal_distribution velocity_gen(v0_mean, v0_std_dev); - uniform_real_distribution y_gen(0.3, BOARD_WIDTH - 0.3); - uniform_real_distribution x_gen_left(2.0, BOARD_LENGTH / 2.0); - uniform_real_distribution x_gen_right(BOARD_LENGTH / 2.0, BOARD_LENGTH - 2.0); - - const int n_p_pad = (n_p + 7) & ~7; - - pos_x.resize(n_p_pad); - pos_y.resize(n_p_pad); - sb_sq.resize(n_p_pad); - sb_e_x.resize(n_p_pad); - sb_e_y.resize(n_p_pad); - e_x.resize(n_p_pad); - e_y.resize(n_p_pad); - curr_vel_x.resize(n_p_pad); - curr_vel_y.resize(n_p_pad); - w_x.resize(n_p_pad); - w_y.resize(n_p_pad); - desired_v0.resize(n_p_pad); - v_max.resize(n_p_pad); - destination_x.resize(n_p_pad); - destination_y.resize(n_p_pad); - color.resize(n_p_pad); - - int n_p_half = n_p / 2; - - for (int i = 0; i < n_p_half; i++) { - float x = x_gen_left(gen); - float y = y_gen(gen); - - float dest_x = BOARD_LENGTH + 30.0; - float dest_y = y; - - float init_e_x = dest_x - x; - float init_e_y = dest_y - y; - float init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - float init_e_unit_x = init_e_x / init_e_norm; - float init_e_unit_y = init_e_y / init_e_norm; - - float d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1); - - float v_m = 1.3 * d_v0; - - color[i] = 0; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - w_x[i] = 0.0f; - w_y[i] = 0.0f; - curr_vel_x[i] = 0.0f; - curr_vel_y[i] = 0.0f; - sb_sq[i] = 0.0f; - sb_e_x[i] = 0.0f; - sb_e_y[i] = 0.0f; - } - - for (int i = n_p_half; i < n_p; i++) { - float x = x_gen_right(gen); - float y = y_gen(gen); - - float dest_x = -30; - float dest_y = y; - - float init_e_x = dest_x - x; - float init_e_y = dest_y - y; - float init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - float init_e_unit_x = init_e_x / init_e_norm; - float init_e_unit_y = init_e_y / init_e_norm; - - float d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1); - - float v_m = 1.3 * d_v0; - - color[i] = 1; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - w_x[i] = 0.0f; - w_y[i] = 0.0f; - curr_vel_x[i] = 0.0f; - curr_vel_y[i] = 0.0f; - sb_sq[i] = 0.0f; - sb_e_x[i] = 0.0f; - sb_e_y[i] = 0.0f; - } - - for (int j = n_p; j < n_p_pad; j++) { - pos_x[j] = 1e9f; - pos_y[j] = 1e9f; - sb_sq[j] = 0.0f; - sb_e_x[j] = 0.0f; - sb_e_y[j] = 0.0f; - } - return nullptr; -} - -Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } - -// simd expf, degree-12 taylor on the [-ln2/2, ln2/2] reduced range, -// schraudolph 2^n bit trick on the exponent slot. -// # 128 MULTs, 112 ADDs -static inline __m256 exp256_ps(__m256 x) { - const __m256 log2e = _mm256_set1_ps(1.4426950408889634f); - __m256 nf = _mm256_round_ps(_mm256_mul_ps(x, log2e), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); // # 8 MULTs - - const __m256 ln2 = _mm256_set1_ps(0.6931471805599453f); - __m256 r = _mm256_fnmadd_ps(nf, ln2, x); // # 8 MULTs, 8 ADDs - - const __m256 c13 = _mm256_set1_ps(c13_scalar); - const __m256 c12 = _mm256_set1_ps(c12_scalar); - const __m256 c11 = _mm256_set1_ps(c11_scalar); - const __m256 c10 = _mm256_set1_ps(c10_scalar); - const __m256 c9 = _mm256_set1_ps(c9_scalar); - const __m256 c8 = _mm256_set1_ps(c8_scalar); - const __m256 c7 = _mm256_set1_ps(c7_scalar); - const __m256 c6 = _mm256_set1_ps(c6_scalar); - const __m256 c5 = _mm256_set1_ps(c5_scalar); - const __m256 c4 = _mm256_set1_ps(c4_scalar); - const __m256 c3 = _mm256_set1_ps(c3_scalar); - const __m256 c2 = _mm256_set1_ps(c2_scalar); - const __m256 c1 = _mm256_set1_ps(c1_scalar); - const __m256 c0 = _mm256_set1_ps(c0_scalar); - - __m256 p = c13; - - // # 13 * (8 MULTs, 8 ADDs) - // # = 104 MULTs, 104 ADDs - p = _mm256_fmadd_ps(p, r, c12); - p = _mm256_fmadd_ps(p, r, c11); - p = _mm256_fmadd_ps(p, r, c10); - p = _mm256_fmadd_ps(p, r, c9); - p = _mm256_fmadd_ps(p, r, c8); - p = _mm256_fmadd_ps(p, r, c7); - p = _mm256_fmadd_ps(p, r, c6); - p = _mm256_fmadd_ps(p, r, c5); - p = _mm256_fmadd_ps(p, r, c4); - p = _mm256_fmadd_ps(p, r, c3); - p = _mm256_fmadd_ps(p, r, c2); - p = _mm256_fmadd_ps(p, r, c1); - p = _mm256_fmadd_ps(p, r, c0); - - __m256i ni = _mm256_cvtps_epi32(nf); - __m256i biased = _mm256_add_epi32(ni, _mm256_set1_epi32(127)); - __m256i scaled = _mm256_slli_epi32(biased, 23); - __m256 pow2n = _mm256_castsi256_ps(scaled); - - return _mm256_mul_ps(p, pow2n); // # 8 MULTs -} - -int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { - (void)pedestrians; -#if BENCHMARK - (void)dump_path; -#endif - -#if !BENCHMARK - const int dump_interval = 1; - - vector> samples; - - if (dump_path) { - samples.reserve(static_cast(n_iter / dump_interval + 1) * n_p); - - for (int i = 0; i < n_p; i++) { - samples.emplace_back(0, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } - } -#endif - - const int n_p_pad = (n_p + 7) & ~7; - - alignas(32) const float lane_offset_arr[8] = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f}; - const __m256 lane_off = _mm256_load_ps(lane_offset_arr); - - const __m256 v_neg_v0_div_2s = _mm256_set1_ps(NEG_V0_AB_div_TWO_SIGMA); - const __m256 v_neg_2s_inv = _mm256_set1_ps(NEG_TWO_SIGMA_INV); - const __m256 v_cos_phi_sq = _mm256_set1_ps(cos_phi_sq); - const __m256 v_dt_neg = _mm256_set1_ps(dt_neg); - const __m256 v_c_neg_dt = _mm256_set1_ps(c_neg_times_dt); - const __m256 v_zero = _mm256_setzero_ps(); - const __m256 v_one = _mm256_set1_ps(1.0f); - const __m256 v_eps = _mm256_set1_ps(EPS); - const __m256 v_eps_sq = _mm256_set1_ps(EPS_SQ); - const __m256 v_np = _mm256_set1_ps((float)n_p); - const __m256 v_exp_min = _mm256_set1_ps(-87.0f); // clamp for polyexp, below this exp(x) ~ 0 anyway - - // # flops per iteration (one pass of the outer time loop): - // # ADDs: n_p * 22 + n_p * n_p_pad * 29 + n_p * board.n_obstacles * 10 + n_p * 7 - // # MULTs: n_p * 4 + n_p * n_p_pad * 40 + n_p * board.n_obstacles * 13 + n_p * 16 - // # DIVs: n_p * n_p_pad * 1 + n_p * board.n_obstacles + n_p * 2 - // # SQRTs: n_p * n_p_pad * 3 + n_p * board.n_obstacles + n_p * 3 - // # EXPs: n_p * board.n_obstacles - for (int t = 0; t < n_iter; t++) { - - for (int i = 0; i < n_p; i++) { - - float desired_velocity_x = e_x[i] * desired_v0[i]; // # 1 MULT - float desired_velocity_y = e_y[i] * desired_v0[i]; // # 1 MULT - - float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; // # 1 MULT, 1 ADD - float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; // # 1 MULT, 1 ADD - - const __m256 pix = _mm256_set1_ps(pos_x[i]); - const __m256 piy = _mm256_set1_ps(pos_y[i]); - const __m256 eix = _mm256_set1_ps(e_x[i]); - const __m256 eiy = _mm256_set1_ps(e_y[i]); - const __m256 v_i = _mm256_set1_ps((float)i); - - __m256 acc_x = _mm256_setzero_ps(); - __m256 acc_y = _mm256_setzero_ps(); - - for (int j = 0; j < n_p_pad; j += 8) { - __m256 j_idx = _mm256_add_ps(_mm256_set1_ps((float)j), lane_off); // # 8 ADDs - - __m256 m_neq_i = _mm256_cmp_ps(j_idx, v_i, _CMP_NEQ_OQ); - __m256 m_in_range = _mm256_cmp_ps(j_idx, v_np, _CMP_LT_OQ); - __m256 active = _mm256_and_ps(m_neq_i, m_in_range); - - __m256 pjx = _mm256_loadu_ps(&pos_x[j]); - __m256 pjy = _mm256_loadu_ps(&pos_y[j]); - __m256 sbe_jx = _mm256_loadu_ps(&sb_e_x[j]); - __m256 sbe_jy = _mm256_loadu_ps(&sb_e_y[j]); - __m256 sb_jsq = _mm256_loadu_ps(&sb_sq[j]); - - __m256 r_ab_x = _mm256_sub_ps(pix, pjx); // # 8 ADDs - __m256 r_ab_y = _mm256_sub_ps(piy, pjy); // # 8 ADDs - __m256 r_ab_n2 = _mm256_fmadd_ps(r_ab_x, r_ab_x, _mm256_mul_ps(r_ab_y, r_ab_y)); // # 16 MULTs, 8 ADDs - __m256 r_ab_n = _mm256_sqrt_ps(r_ab_n2); // # 8 SQRTs - r_ab_n = _mm256_max_ps(r_ab_n, v_eps); - - __m256 r_ab2_x = _mm256_sub_ps(r_ab_x, sbe_jx); // # 8 ADDs - __m256 r_ab2_y = _mm256_sub_ps(r_ab_y, sbe_jy); // # 8 ADDs - __m256 r_ab2_n2 = _mm256_fmadd_ps(r_ab2_x, r_ab2_x, _mm256_mul_ps(r_ab2_y, r_ab2_y)); // # 16 MULTs, 8 ADDs - __m256 r_ab2_n = _mm256_sqrt_ps(r_ab2_n2); // # 8 SQRTs - r_ab2_n = _mm256_max_ps(r_ab2_n, v_eps); - - __m256 r_sum = _mm256_add_ps(r_ab_n, r_ab2_n); // # 8 ADDs - __m256 two_b_sq = _mm256_fmsub_ps(r_sum, r_sum, sb_jsq); // # 8 MULTs, 8 ADDs - two_b_sq = _mm256_max_ps(two_b_sq, v_eps_sq); - __m256 two_b = _mm256_sqrt_ps(two_b_sq); // # 8 SQRTs - - // simd polynomial expf, no libm call. replaces the 8-iter scalar loop that gcc refused to unroll. - // clamp e_arg >= -87 first: exp(-87) ~ 1.6e-38 is already basically 0, and the schraudolph 2^n - // bit trick blows up if (nf + 127) goes negative (which happens for padding lanes where e_arg ~ -4.7e9). - __m256 e_arg = _mm256_mul_ps(two_b, v_neg_2s_inv); // # 8 MULTs - e_arg = _mm256_max_ps(e_arg, v_exp_min); - __m256 e_val = exp256_ps(e_arg); // # 128 MULTs, 112 ADDs - - __m256 numer = _mm256_mul_ps(_mm256_mul_ps(r_sum, v_neg_v0_div_2s), e_val); // # 16 MULTs - __m256 denom = _mm256_mul_ps(_mm256_mul_ps(two_b, r_ab_n), r_ab2_n); // # 16 MULTs - __m256 denom_safe = _mm256_blendv_ps(v_one, denom, active); // bitwise, no flop - __m256 smc = _mm256_div_ps(numer, denom_safe); // # 8 DIVs - - __m256 sm_r_ab = _mm256_mul_ps(smc, r_ab2_n); // # 8 MULTs - __m256 sm_r_ab2 = _mm256_mul_ps(smc, r_ab_n); // # 8 MULTs - - __m256 f_x = _mm256_fmadd_ps(r_ab2_x, sm_r_ab2, _mm256_mul_ps(r_ab_x, sm_r_ab)); // # 16 MULTs, 8 ADDs - __m256 f_y = _mm256_fmadd_ps(r_ab2_y, sm_r_ab2, _mm256_mul_ps(r_ab_y, sm_r_ab)); // # 16 MULTs, 8 ADDs - - __m256 f_norm_sq = _mm256_fmadd_ps(f_x, f_x, _mm256_mul_ps(f_y, f_y)); // # 16 MULTs, 8 ADDs - __m256 rhs = _mm256_mul_ps(f_norm_sq, v_cos_phi_sq); // # 8 MULTs - __m256 e_dot_f = _mm256_fmadd_ps(eix, f_x, _mm256_mul_ps(eiy, f_y)); // # 16 MULTs, 8 ADDs - __m256 e_dot_f_sq = _mm256_mul_ps(e_dot_f, e_dot_f); // # 8 MULTs - - __m256 c1 = _mm256_cmp_ps(e_dot_f, v_zero, _CMP_LT_OQ); - __m256 c2 = _mm256_cmp_ps(e_dot_f_sq, rhs, _CMP_GT_OQ); - __m256 cond = _mm256_and_ps(c1, c2); - __m256 w_val = _mm256_blendv_ps(v_dt_neg, v_c_neg_dt, cond); - - __m256 f_x_safe = _mm256_and_ps(f_x, active); // bitwise, no flop - __m256 f_y_safe = _mm256_and_ps(f_y, active); // bitwise, no flop - acc_x = _mm256_fmadd_ps(f_x_safe, w_val, acc_x); // # 8 MULTs, 8 ADDs - acc_y = _mm256_fmadd_ps(f_y_safe, w_val, acc_y); // # 8 MULTs, 8 ADDs - } - - __m256 hsum = _mm256_hadd_ps(acc_x, acc_y); // # 8 ADDs - __m128 hsum_lo = _mm256_castps256_ps128(hsum); - __m128 hsum_hi = _mm256_extractf128_ps(hsum, 1); - __m128 sum4 = _mm_add_ps(hsum_lo, hsum_hi); // # 4 ADDs - sum4 = _mm_hadd_ps(sum4, sum4); // # 4 ADDs - alignas(16) float sum_out[4]; - _mm_store_ps(sum_out, sum4); - f_alpha_dt_x += sum_out[0]; // # 1 ADD - f_alpha_dt_y += sum_out[1]; // # 1 ADD - - for (int k = 0; k < board.n_obstacles; k++) { - - float v1_x = pos_x[i] - board.obstacles[k].start_x; // # 1 ADD - float v1_y = pos_y[i] - board.obstacles[k].start_y; // # 1 ADD - float v2_x = board.obstacles[k].obstacle_v_x; - float v2_y = board.obstacles[k].obstacle_v_y; - - float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; // # 3 MULTs, 1 ADD - - if (projection < 0.0) - projection = 0.0; - else if (projection > 1.0) - projection = 1.0; - - float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); // # 1 MULT, 2 ADDs - float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); // # 1 MULT, 2 ADDs - - float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); // # 2 MULTs, 1 ADD, 1 SQRT - r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; - - float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; // # 2 MULTs, 1 EXP, 1 DIV - float f_alpha_B_neg_x = r_aB_x * scalar_mult; // # 1 MULT - float f_alpha_B_neg_y = r_aB_y * scalar_mult; // # 1 MULT - - float w_val; - - float e_dot_f = (f_alpha_B_neg_y == 0) ? 0 : (f_alpha_B_neg_y < 0 ? -e_y[i] : e_y[i]); - - if (e_dot_f >= cos_phi) - w_val = dt_neg; - else - w_val = c_neg_times_dt; - - float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; // # 1 MULT - float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; // # 1 MULT - - f_alpha_dt_x += f_alpha_B_dt_x; // # 1 ADD - f_alpha_dt_y += f_alpha_B_dt_y; // # 1 ADD - } - - w_x[i] += f_alpha_dt_x; // # 1 ADD - w_y[i] += f_alpha_dt_y; // # 1 ADD - } - - for (int i = 0; i < n_p; i++) { - - float w_norm = sqrt(w_x[i] * w_x[i] + w_y[i] * w_y[i]); // # 2 MULTs, 1 ADD, 1 SQRT - float w_norm2 = w_norm > EPS ? w_norm : EPS; - float correction_factor = min(1.0f, v_max[i] / w_norm2); // # 1 DIV - - curr_vel_x[i] = w_x[i] * correction_factor; // # 1 MULT - curr_vel_y[i] = w_y[i] * correction_factor; // # 1 MULT - - pos_x[i] = pos_x[i] + curr_vel_x[i] * dt; // # 1 MULT, 1 ADD - pos_y[i] = pos_y[i] + curr_vel_y[i] * dt; // # 1 MULT, 1 ADD - - if (color[i] == 0 && pos_x[i] > (BOARD_LENGTH - 1.5)) { - pos_x[i] = 1.0; - destination_y[i] = pos_y[i]; - w_x[i] = desired_v0[i]; - w_y[i] = 0.0; - curr_vel_x[i] = w_x[i]; - curr_vel_y[i] = w_y[i]; - } - if (color[i] == 1 && pos_x[i] < 1.5) { - pos_x[i] = BOARD_LENGTH - 1.0; - destination_y[i] = pos_y[i]; - w_x[i] = -desired_v0[i]; - w_y[i] = 0.0; - curr_vel_x[i] = w_x[i]; - curr_vel_y[i] = w_y[i]; - } - - pos_y[i] = clamp(pos_y[i], WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - - float ex = destination_x[i] - pos_x[i]; // # 1 ADD - float ey = destination_y[i] - pos_y[i]; // # 1 ADD - - float e_norm = sqrt(ex * ex + ey * ey); // # 2 MULTs, 1 ADD, 1 SQRT - float e_norm2 = e_norm > EPS ? e_norm : EPS; - float e_norm_inv = 1.0 / e_norm2; // # 1 DIV - - e_x[i] = ex * e_norm_inv; // # 1 MULT - e_y[i] = ey * e_norm_inv; // # 1 MULT - - float velocity_norm_sq = curr_vel_x[i] * curr_vel_x[i] + curr_vel_y[i] * curr_vel_y[i]; // # 2 MULTs, 1 ADD - float velocity_norm = sqrt(velocity_norm_sq); // # 1 SQRT - - sb_sq[i] = velocity_norm_sq * delta_t_sq; // # 1 MULT - sb_e_x[i] = e_x[i] * (velocity_norm * delta_t); // # 2 MULTs (vel_norm*delta_t shared with next line) - sb_e_y[i] = e_y[i] * (velocity_norm * delta_t); // # 1 MULT - -#if !BENCHMARK - if (dump_path && (t % dump_interval == 0)) { - samples.emplace_back(t + 1, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } -#endif - } - } - -#if !BENCHMARK - if (dump_path) { - ofstream out(dump_path); - out << "time,id,x,y,p.e.x,p.e.y,color\n"; - - for (auto &[t, id, x, y, e_x, e_y, c] : samples) { - out << t << ',' << id << ',' << x << ',' << y << ',' << e_x << ',' << e_y << ',' << c << '\n'; - } - } -#endif - - return 0; -} diff --git a/variants/variant_float_inlining_SoA_AVX2_polyexp_rsqrt.cpp b/variants/variant_float_inlining_SoA_AVX2_polyexp_rsqrt.cpp index b75d74b..c42d59d 100644 --- a/variants/variant_float_inlining_SoA_AVX2_polyexp_rsqrt.cpp +++ b/variants/variant_float_inlining_SoA_AVX2_polyexp_rsqrt.cpp @@ -187,23 +187,43 @@ Pedestrian *init_pedestrians(int n_p) { Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } -// simd expf, same as the predecessor. degree-5 taylor on the [-ln2/2, ln2/2] reduced range, +// simd expf, degree-12 taylor on the [-ln2/2, ln2/2] reduced range, // schraudolph 2^n bit trick on the exponent slot. +// # 128 MULTs, 112 ADDs static inline __m256 exp256_ps(__m256 x) { const __m256 log2e = _mm256_set1_ps(1.4426950408889634f); - __m256 nf = _mm256_round_ps(_mm256_mul_ps(x, log2e), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); + __m256 nf = _mm256_round_ps(_mm256_mul_ps(x, log2e), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); // # 8 MULTs const __m256 ln2 = _mm256_set1_ps(0.6931471805599453f); - __m256 r = _mm256_fnmadd_ps(nf, ln2, x); + __m256 r = _mm256_fnmadd_ps(nf, ln2, x); // # 8 MULTs, 8 ADDs - const __m256 c5 = _mm256_set1_ps(1.0f / 120.0f); - const __m256 c4 = _mm256_set1_ps(1.0f / 24.0f); - const __m256 c3 = _mm256_set1_ps(1.0f / 6.0f); - const __m256 c2 = _mm256_set1_ps(0.5f); - const __m256 c1 = _mm256_set1_ps(1.0f); - const __m256 c0 = _mm256_set1_ps(1.0f); + const __m256 c13 = _mm256_set1_ps(c13_scalar); + const __m256 c12 = _mm256_set1_ps(c12_scalar); + const __m256 c11 = _mm256_set1_ps(c11_scalar); + const __m256 c10 = _mm256_set1_ps(c10_scalar); + const __m256 c9 = _mm256_set1_ps(c9_scalar); + const __m256 c8 = _mm256_set1_ps(c8_scalar); + const __m256 c7 = _mm256_set1_ps(c7_scalar); + const __m256 c6 = _mm256_set1_ps(c6_scalar); + const __m256 c5 = _mm256_set1_ps(c5_scalar); + const __m256 c4 = _mm256_set1_ps(c4_scalar); + const __m256 c3 = _mm256_set1_ps(c3_scalar); + const __m256 c2 = _mm256_set1_ps(c2_scalar); + const __m256 c1 = _mm256_set1_ps(c1_scalar); + const __m256 c0 = _mm256_set1_ps(c0_scalar); - __m256 p = c5; + __m256 p = c13; + + // # 13 * (8 MULTs, 8 ADDs) + // # = 104 MULTs, 104 ADDs + p = _mm256_fmadd_ps(p, r, c12); + p = _mm256_fmadd_ps(p, r, c11); + p = _mm256_fmadd_ps(p, r, c10); + p = _mm256_fmadd_ps(p, r, c9); + p = _mm256_fmadd_ps(p, r, c8); + p = _mm256_fmadd_ps(p, r, c7); + p = _mm256_fmadd_ps(p, r, c6); + p = _mm256_fmadd_ps(p, r, c5); p = _mm256_fmadd_ps(p, r, c4); p = _mm256_fmadd_ps(p, r, c3); p = _mm256_fmadd_ps(p, r, c2); @@ -215,7 +235,7 @@ static inline __m256 exp256_ps(__m256 x) { __m256i scaled = _mm256_slli_epi32(biased, 23); __m256 pow2n = _mm256_castsi256_ps(scaled); - return _mm256_mul_ps(p, pow2n); + return _mm256_mul_ps(p, pow2n); // # 8 MULTs } int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { @@ -253,15 +273,21 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c const __m256 v_np = _mm256_set1_ps((float)n_p); const __m256 v_exp_min = _mm256_set1_ps(-87.0f); + // # flops per iteration (one pass of the outer time loop): + // # ADDs: n_p * 22 + n_p * n_p_pad * 29 + n_p * board.n_obstacles * 10 + n_p * 7 + // # MULTs: n_p * 4 + n_p * n_p_pad * 42 + n_p * board.n_obstacles * 13 + n_p * 16 + // # DIVs: n_p * n_p_pad * 3 + n_p * board.n_obstacles + n_p * 2 + // # SQRTs: n_p * n_p_pad * 3 + n_p * board.n_obstacles + n_p * 3 + // # EXPs: n_p * board.n_obstacles for (int t = 0; t < n_iter; t++) { for (int i = 0; i < n_p; i++) { - float desired_velocity_x = e_x[i] * desired_v0[i]; - float desired_velocity_y = e_y[i] * desired_v0[i]; + float desired_velocity_x = e_x[i] * desired_v0[i]; // # 1 MULT + float desired_velocity_y = e_y[i] * desired_v0[i]; // # 1 MULT - float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; - float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; + float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; // # 1 MULT, 1 ADD + float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; // # 1 MULT, 1 ADD const __m256 pix = _mm256_set1_ps(pos_x[i]); const __m256 piy = _mm256_set1_ps(pos_y[i]); @@ -273,7 +299,7 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m256 acc_y = _mm256_setzero_ps(); for (int j = 0; j < n_p_pad; j += 8) { - __m256 j_idx = _mm256_add_ps(_mm256_set1_ps((float)j), lane_off); + __m256 j_idx = _mm256_add_ps(_mm256_set1_ps((float)j), lane_off); // # 8 ADDs __m256 m_neq_i = _mm256_cmp_ps(j_idx, v_i, _CMP_NEQ_OQ); __m256 m_in_range = _mm256_cmp_ps(j_idx, v_np, _CMP_LT_OQ); @@ -285,93 +311,93 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m256 sbe_jy = _mm256_loadu_ps(&sb_e_y[j]); __m256 sb_jsq = _mm256_loadu_ps(&sb_sq[j]); - __m256 r_ab_x = _mm256_sub_ps(pix, pjx); - __m256 r_ab_y = _mm256_sub_ps(piy, pjy); - __m256 r_ab_n2 = _mm256_fmadd_ps(r_ab_x, r_ab_x, _mm256_mul_ps(r_ab_y, r_ab_y)); + __m256 r_ab_x = _mm256_sub_ps(pix, pjx); // # 8 ADDs + __m256 r_ab_y = _mm256_sub_ps(piy, pjy); // # 8 ADDs + __m256 r_ab_n2 = _mm256_fmadd_ps(r_ab_x, r_ab_x, _mm256_mul_ps(r_ab_y, r_ab_y)); // # 16 MULTs, 8 ADDs // clamp before rsqrt: rsqrt(0) = inf, then x*inf = 0*inf = NaN downstream. EPS_SQ // means the inv_sqrt tops out at 1/EPS and r_ab_n = EPS_SQ/EPS = EPS, matches the predecessor. r_ab_n2 = _mm256_max_ps(r_ab_n2, v_eps_sq); - __m256 inv_r_ab_n = _mm256_rsqrt_ps(r_ab_n2); - __m256 r_ab_n = _mm256_mul_ps(r_ab_n2, inv_r_ab_n); + __m256 inv_r_ab_n = _mm256_rsqrt_ps(r_ab_n2); // # 8 SQRTs, 8 DIVs + __m256 r_ab_n = _mm256_mul_ps(r_ab_n2, inv_r_ab_n); // # 8 MULTs - __m256 r_ab2_x = _mm256_sub_ps(r_ab_x, sbe_jx); - __m256 r_ab2_y = _mm256_sub_ps(r_ab_y, sbe_jy); - __m256 r_ab2_n2 = _mm256_fmadd_ps(r_ab2_x, r_ab2_x, _mm256_mul_ps(r_ab2_y, r_ab2_y)); + __m256 r_ab2_x = _mm256_sub_ps(r_ab_x, sbe_jx); // # 8 ADDs + __m256 r_ab2_y = _mm256_sub_ps(r_ab_y, sbe_jy); // # 8 ADDs + __m256 r_ab2_n2 = _mm256_fmadd_ps(r_ab2_x, r_ab2_x, _mm256_mul_ps(r_ab2_y, r_ab2_y)); // # 16 MULTs, 8 ADDs r_ab2_n2 = _mm256_max_ps(r_ab2_n2, v_eps_sq); - __m256 inv_r_ab2_n = _mm256_rsqrt_ps(r_ab2_n2); - __m256 r_ab2_n = _mm256_mul_ps(r_ab2_n2, inv_r_ab2_n); + __m256 inv_r_ab2_n = _mm256_rsqrt_ps(r_ab2_n2); // # 8 SQRTs, 8 DIVs + __m256 r_ab2_n = _mm256_mul_ps(r_ab2_n2, inv_r_ab2_n); // # 8 MULTs - __m256 r_sum = _mm256_add_ps(r_ab_n, r_ab2_n); - __m256 two_b_sq = _mm256_fmsub_ps(r_sum, r_sum, sb_jsq); + __m256 r_sum = _mm256_add_ps(r_ab_n, r_ab2_n); // # 8 ADDs + __m256 two_b_sq = _mm256_fmsub_ps(r_sum, r_sum, sb_jsq); // # 8 MULTs, 8 ADDs two_b_sq = _mm256_max_ps(two_b_sq, v_eps_sq); - __m256 inv_two_b = _mm256_rsqrt_ps(two_b_sq); - __m256 two_b = _mm256_mul_ps(two_b_sq, inv_two_b); + __m256 inv_two_b = _mm256_rsqrt_ps(two_b_sq); // # 8 SQRTs, 8 DIVs + __m256 two_b = _mm256_mul_ps(two_b_sq, inv_two_b); // # 8 MULTs - __m256 e_arg = _mm256_mul_ps(two_b, v_neg_2s_inv); + __m256 e_arg = _mm256_mul_ps(two_b, v_neg_2s_inv); // # 8 MULTs e_arg = _mm256_max_ps(e_arg, v_exp_min); - __m256 e_val = exp256_ps(e_arg); + __m256 e_val = exp256_ps(e_arg); // # 128 MULTs, 112 ADDs // smc = numer/denom in the predecessor. with inv-sqrts in hand the divide is free: // sm_r_ab = smc * r_ab2_n = numer / (two_b * r_ab_n) = numer * inv_two_b * inv_r_ab_n // sm_r_ab2 = smc * r_ab_n = numer / (two_b * r_ab2_n) = numer * inv_two_b * inv_r_ab2_n // for the i==j and padding lanes inv_two_b*inv_r_ab_n is huge, but the active-mask AND on // f_x/f_y below zeros the lane out before accumulation so it cant pollute anything. - __m256 numer_inv_two_b = _mm256_mul_ps(_mm256_mul_ps(r_sum, v_neg_v0_div_2s), _mm256_mul_ps(e_val, inv_two_b)); - __m256 sm_r_ab = _mm256_mul_ps(numer_inv_two_b, inv_r_ab_n); - __m256 sm_r_ab2 = _mm256_mul_ps(numer_inv_two_b, inv_r_ab2_n); + __m256 numer_inv_two_b = _mm256_mul_ps(_mm256_mul_ps(r_sum, v_neg_v0_div_2s), _mm256_mul_ps(e_val, inv_two_b)); // # 24 MULTs + __m256 sm_r_ab = _mm256_mul_ps(numer_inv_two_b, inv_r_ab_n); // # 8 MULTs + __m256 sm_r_ab2 = _mm256_mul_ps(numer_inv_two_b, inv_r_ab2_n); // # 8 MULTs - __m256 f_x = _mm256_fmadd_ps(r_ab2_x, sm_r_ab2, _mm256_mul_ps(r_ab_x, sm_r_ab)); - __m256 f_y = _mm256_fmadd_ps(r_ab2_y, sm_r_ab2, _mm256_mul_ps(r_ab_y, sm_r_ab)); + __m256 f_x = _mm256_fmadd_ps(r_ab2_x, sm_r_ab2, _mm256_mul_ps(r_ab_x, sm_r_ab)); // # 16 MULTs, 8 ADDs + __m256 f_y = _mm256_fmadd_ps(r_ab2_y, sm_r_ab2, _mm256_mul_ps(r_ab_y, sm_r_ab)); // # 16 MULTs, 8 ADDs - __m256 f_norm_sq = _mm256_fmadd_ps(f_x, f_x, _mm256_mul_ps(f_y, f_y)); - __m256 rhs = _mm256_mul_ps(f_norm_sq, v_cos_phi_sq); - __m256 e_dot_f = _mm256_fmadd_ps(eix, f_x, _mm256_mul_ps(eiy, f_y)); - __m256 e_dot_f_sq = _mm256_mul_ps(e_dot_f, e_dot_f); + __m256 f_norm_sq = _mm256_fmadd_ps(f_x, f_x, _mm256_mul_ps(f_y, f_y)); // # 16 MULTs, 8 ADDs + __m256 rhs = _mm256_mul_ps(f_norm_sq, v_cos_phi_sq); // # 8 MULTs + __m256 e_dot_f = _mm256_fmadd_ps(eix, f_x, _mm256_mul_ps(eiy, f_y)); // # 16 MULTs, 8 ADDs + __m256 e_dot_f_sq = _mm256_mul_ps(e_dot_f, e_dot_f); // # 8 MULTs __m256 c1 = _mm256_cmp_ps(e_dot_f, v_zero, _CMP_LT_OQ); __m256 c2 = _mm256_cmp_ps(e_dot_f_sq, rhs, _CMP_GT_OQ); __m256 cond = _mm256_and_ps(c1, c2); __m256 w_val = _mm256_blendv_ps(v_dt_neg, v_c_neg_dt, cond); - __m256 f_x_safe = _mm256_and_ps(f_x, active); - __m256 f_y_safe = _mm256_and_ps(f_y, active); - acc_x = _mm256_fmadd_ps(f_x_safe, w_val, acc_x); - acc_y = _mm256_fmadd_ps(f_y_safe, w_val, acc_y); + __m256 f_x_safe = _mm256_and_ps(f_x, active); // bitwise, no flop + __m256 f_y_safe = _mm256_and_ps(f_y, active); // bitwise, no flop + acc_x = _mm256_fmadd_ps(f_x_safe, w_val, acc_x); // # 8 MULTs, 8 ADDs + acc_y = _mm256_fmadd_ps(f_y_safe, w_val, acc_y); // # 8 MULTs, 8 ADDs } - __m256 hsum = _mm256_hadd_ps(acc_x, acc_y); + __m256 hsum = _mm256_hadd_ps(acc_x, acc_y); // # 8 ADDs (x and y interleaved) __m128 hsum_lo = _mm256_castps256_ps128(hsum); __m128 hsum_hi = _mm256_extractf128_ps(hsum, 1); - __m128 sum4 = _mm_add_ps(hsum_lo, hsum_hi); - sum4 = _mm_hadd_ps(sum4, sum4); + __m128 sum4 = _mm_add_ps(hsum_lo, hsum_hi); // # 4 ADDs + sum4 = _mm_hadd_ps(sum4, sum4); // # 4 ADDs (total hadd: 16 ADDs for x+y) alignas(16) float sum_out[4]; _mm_store_ps(sum_out, sum4); - f_alpha_dt_x += sum_out[0]; - f_alpha_dt_y += sum_out[1]; + f_alpha_dt_x += sum_out[0]; // # 1 ADD + f_alpha_dt_y += sum_out[1]; // # 1 ADD for (int k = 0; k < board.n_obstacles; k++) { - float v1_x = pos_x[i] - board.obstacles[k].start_x; - float v1_y = pos_y[i] - board.obstacles[k].start_y; + float v1_x = pos_x[i] - board.obstacles[k].start_x; // # 1 ADD + float v1_y = pos_y[i] - board.obstacles[k].start_y; // # 1 ADD float v2_x = board.obstacles[k].obstacle_v_x; float v2_y = board.obstacles[k].obstacle_v_y; - float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; + float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; // # 3 MULTs, 1 ADD if (projection < 0.0) projection = 0.0; else if (projection > 1.0) projection = 1.0; - float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); - float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); + float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); // # 1 MULT, 2 ADDs + float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); // # 1 MULT, 2 ADDs - float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); + float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); // # 2 MULTs, 1 ADD, 1 SQRT r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; - float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; - float f_alpha_B_neg_x = r_aB_x * scalar_mult; - float f_alpha_B_neg_y = r_aB_y * scalar_mult; + float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; // # 2 MULTs, 1 EXP, 1 DIV + float f_alpha_B_neg_x = r_aB_x * scalar_mult; // # 1 MULT + float f_alpha_B_neg_y = r_aB_y * scalar_mult; // # 1 MULT float w_val; @@ -382,28 +408,28 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c else w_val = c_neg_times_dt; - float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; - float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; + float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; // # 1 MULT + float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; // # 1 MULT - f_alpha_dt_x += f_alpha_B_dt_x; - f_alpha_dt_y += f_alpha_B_dt_y; + f_alpha_dt_x += f_alpha_B_dt_x; // # 1 ADD + f_alpha_dt_y += f_alpha_B_dt_y; // # 1 ADD } - w_x[i] += f_alpha_dt_x; - w_y[i] += f_alpha_dt_y; + w_x[i] += f_alpha_dt_x; // # 1 ADD + w_y[i] += f_alpha_dt_y; // # 1 ADD } for (int i = 0; i < n_p; i++) { - float w_norm = sqrt(w_x[i] * w_x[i] + w_y[i] * w_y[i]); + float w_norm = sqrt(w_x[i] * w_x[i] + w_y[i] * w_y[i]); // # 2 MULTs, 1 ADD, 1 SQRT float w_norm2 = w_norm > EPS ? w_norm : EPS; - float correction_factor = min(1.0f, v_max[i] / w_norm2); + float correction_factor = min(1.0f, v_max[i] / w_norm2); // # 1 DIV - curr_vel_x[i] = w_x[i] * correction_factor; - curr_vel_y[i] = w_y[i] * correction_factor; + curr_vel_x[i] = w_x[i] * correction_factor; // # 1 MULT + curr_vel_y[i] = w_y[i] * correction_factor; // # 1 MULT - pos_x[i] = pos_x[i] + curr_vel_x[i] * dt; - pos_y[i] = pos_y[i] + curr_vel_y[i] * dt; + pos_x[i] = pos_x[i] + curr_vel_x[i] * dt; // # 1 MULT, 1 ADD + pos_y[i] = pos_y[i] + curr_vel_y[i] * dt; // # 1 MULT, 1 ADD if (color[i] == 0 && pos_x[i] > (BOARD_LENGTH - 1.5)) { pos_x[i] = 1.0; @@ -424,22 +450,22 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c pos_y[i] = clamp(pos_y[i], WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - float ex = destination_x[i] - pos_x[i]; - float ey = destination_y[i] - pos_y[i]; + float ex = destination_x[i] - pos_x[i]; // # 1 ADD + float ey = destination_y[i] - pos_y[i]; // # 1 ADD - float e_norm = sqrt(ex * ex + ey * ey); + float e_norm = sqrt(ex * ex + ey * ey); // # 2 MULTs, 1 ADD, 1 SQRT float e_norm2 = e_norm > EPS ? e_norm : EPS; - float e_norm_inv = 1.0 / e_norm2; + float e_norm_inv = 1.0 / e_norm2; // # 1 DIV - e_x[i] = ex * e_norm_inv; - e_y[i] = ey * e_norm_inv; + e_x[i] = ex * e_norm_inv; // # 1 MULT + e_y[i] = ey * e_norm_inv; // # 1 MULT - float velocity_norm_sq = curr_vel_x[i] * curr_vel_x[i] + curr_vel_y[i] * curr_vel_y[i]; - float velocity_norm = sqrt(velocity_norm_sq); + float velocity_norm_sq = curr_vel_x[i] * curr_vel_x[i] + curr_vel_y[i] * curr_vel_y[i]; // # 2 MULTs, 1 ADD + float velocity_norm = sqrt(velocity_norm_sq); // # 1 SQRT - sb_sq[i] = velocity_norm_sq * delta_t_sq; - sb_e_x[i] = e_x[i] * (velocity_norm * delta_t); - sb_e_y[i] = e_y[i] * (velocity_norm * delta_t); + sb_sq[i] = velocity_norm_sq * delta_t_sq; // # 1 MULT + sb_e_x[i] = e_x[i] * (velocity_norm * delta_t); // # 2 MULTs (vel_norm*delta_t shared with next line) + sb_e_y[i] = e_y[i] * (velocity_norm * delta_t); // # 1 MULT #if !BENCHMARK if (dump_path && (t % dump_interval == 0)) { diff --git a/variants/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_expfix.cpp b/variants/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_expfix.cpp deleted file mode 100644 index 0de7907..0000000 --- a/variants/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_expfix.cpp +++ /dev/null @@ -1,490 +0,0 @@ -// # Changes: pure vrsqrtps -// # Predecessor: variant_float_inlining_SoA_AVX2_polyexp.cpp - -// -// We first tried rsqrt + 1 Newton step to keep full sqrt precision, but it -// turned out slower than just using vsqrtps. The Newton step needs 2 muls -// and an fnmadd on top of rsqrt, so the whole recovered sqrt ends up at -// ~20 cycles of latency, while vsqrtps is only 12. Since the OoO core was -// already running multiple sqrts in parallel, sqrt throughput wasn't really -// the bottleneck. All the Newton step did was make the dependency chain -// longer, which hurt more than the faster rsqrt helped. -// -// So we drop the Newton step. rsqrt + 1 mul gives us a sqrt in 8 cycles -// with about 12-bit precision, which is well within the 1cm verify tolerance. - -// The main structural win is killing the vdivps. rsqrt produces 1/sqrt(x) -// directly, so we keep the inverses around (inv_r_ab_n, inv_r_ab2_n, -// inv_two_b) and rewrite the force scaling. The original had -// "numer / (two_b * r_ab_n * r_ab2_n)" which needs a vdivps; now it's -// "numer * inv_two_b * inv_r_ab_n * inv_r_ab2_n", trading one divide for -// two muls. Divide was the long-pole op on port 0, so this is the bigger -// of the two changes. - -#include "../headers/board_reduced_float.hpp" -#include "../headers/constants_float.hpp" -#include "../headers/pedestrian_reduced_float.hpp" - -#include // avx2 - -#include -#include -#include -#include -#include -#include -#include -#include - -#define SEED 42 -#define BOARD_WIDTH 10.0f -#define BOARD_LENGTH 50.0f -#define WALL_EPS 1e-3f -#define BOARD_WIDTH_MINUS_WALL_EPS 9.999f - -#ifndef RANDOM_SEED -#define RANDOM_SEED 0 -#endif - -#ifndef BENCHMARK -#define BENCHMARK 0 -#endif - -using namespace std; - -vector pos_x, pos_y; -vector sb_sq; -vector sb_e_x, sb_e_y; -vector e_x, e_y; -vector curr_vel_x, curr_vel_y; -vector w_x, w_y; -vector desired_v0; -vector v_max; -vector destination_x, destination_y; -vector color; - -Pedestrian *init_pedestrians(int n_p) { -#if RANDOM_SEED - random_device rd; - mt19937 gen(rd()); -#else - mt19937 gen(SEED); -#endif - - normal_distribution velocity_gen(v0_mean, v0_std_dev); - uniform_real_distribution y_gen(0.3, BOARD_WIDTH - 0.3); - uniform_real_distribution x_gen_left(2.0, BOARD_LENGTH / 2.0); - uniform_real_distribution x_gen_right(BOARD_LENGTH / 2.0, BOARD_LENGTH - 2.0); - - const int n_p_pad = (n_p + 7) & ~7; - - pos_x.resize(n_p_pad); - pos_y.resize(n_p_pad); - sb_sq.resize(n_p_pad); - sb_e_x.resize(n_p_pad); - sb_e_y.resize(n_p_pad); - e_x.resize(n_p_pad); - e_y.resize(n_p_pad); - curr_vel_x.resize(n_p_pad); - curr_vel_y.resize(n_p_pad); - w_x.resize(n_p_pad); - w_y.resize(n_p_pad); - desired_v0.resize(n_p_pad); - v_max.resize(n_p_pad); - destination_x.resize(n_p_pad); - destination_y.resize(n_p_pad); - color.resize(n_p_pad); - - int n_p_half = n_p / 2; - - for (int i = 0; i < n_p_half; i++) { - float x = x_gen_left(gen); - float y = y_gen(gen); - - float dest_x = BOARD_LENGTH + 30.0; - float dest_y = y; - - float init_e_x = dest_x - x; - float init_e_y = dest_y - y; - float init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - float init_e_unit_x = init_e_x / init_e_norm; - float init_e_unit_y = init_e_y / init_e_norm; - - float d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1); - - float v_m = 1.3 * d_v0; - - color[i] = 0; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - w_x[i] = 0.0f; - w_y[i] = 0.0f; - curr_vel_x[i] = 0.0f; - curr_vel_y[i] = 0.0f; - sb_sq[i] = 0.0f; - sb_e_x[i] = 0.0f; - sb_e_y[i] = 0.0f; - } - - for (int i = n_p_half; i < n_p; i++) { - float x = x_gen_right(gen); - float y = y_gen(gen); - - float dest_x = -30; - float dest_y = y; - - float init_e_x = dest_x - x; - float init_e_y = dest_y - y; - float init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - float init_e_unit_x = init_e_x / init_e_norm; - float init_e_unit_y = init_e_y / init_e_norm; - - float d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1); - - float v_m = 1.3 * d_v0; - - color[i] = 1; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - w_x[i] = 0.0f; - w_y[i] = 0.0f; - curr_vel_x[i] = 0.0f; - curr_vel_y[i] = 0.0f; - sb_sq[i] = 0.0f; - sb_e_x[i] = 0.0f; - sb_e_y[i] = 0.0f; - } - - for (int j = n_p; j < n_p_pad; j++) { - pos_x[j] = 1e9f; - pos_y[j] = 1e9f; - sb_sq[j] = 0.0f; - sb_e_x[j] = 0.0f; - sb_e_y[j] = 0.0f; - } - return nullptr; -} - -Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } - -// simd expf, degree-12 taylor on the [-ln2/2, ln2/2] reduced range, -// schraudolph 2^n bit trick on the exponent slot. -// # 128 MULTs, 112 ADDs -static inline __m256 exp256_ps(__m256 x) { - const __m256 log2e = _mm256_set1_ps(1.4426950408889634f); - __m256 nf = _mm256_round_ps(_mm256_mul_ps(x, log2e), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); // # 8 MULTs - - const __m256 ln2 = _mm256_set1_ps(0.6931471805599453f); - __m256 r = _mm256_fnmadd_ps(nf, ln2, x); // # 8 MULTs, 8 ADDs - - const __m256 c13 = _mm256_set1_ps(c13_scalar); - const __m256 c12 = _mm256_set1_ps(c12_scalar); - const __m256 c11 = _mm256_set1_ps(c11_scalar); - const __m256 c10 = _mm256_set1_ps(c10_scalar); - const __m256 c9 = _mm256_set1_ps(c9_scalar); - const __m256 c8 = _mm256_set1_ps(c8_scalar); - const __m256 c7 = _mm256_set1_ps(c7_scalar); - const __m256 c6 = _mm256_set1_ps(c6_scalar); - const __m256 c5 = _mm256_set1_ps(c5_scalar); - const __m256 c4 = _mm256_set1_ps(c4_scalar); - const __m256 c3 = _mm256_set1_ps(c3_scalar); - const __m256 c2 = _mm256_set1_ps(c2_scalar); - const __m256 c1 = _mm256_set1_ps(c1_scalar); - const __m256 c0 = _mm256_set1_ps(c0_scalar); - - __m256 p = c13; - - // # 13 * (8 MULTs, 8 ADDs) - // # = 104 MULTs, 104 ADDs - p = _mm256_fmadd_ps(p, r, c12); - p = _mm256_fmadd_ps(p, r, c11); - p = _mm256_fmadd_ps(p, r, c10); - p = _mm256_fmadd_ps(p, r, c9); - p = _mm256_fmadd_ps(p, r, c8); - p = _mm256_fmadd_ps(p, r, c7); - p = _mm256_fmadd_ps(p, r, c6); - p = _mm256_fmadd_ps(p, r, c5); - p = _mm256_fmadd_ps(p, r, c4); - p = _mm256_fmadd_ps(p, r, c3); - p = _mm256_fmadd_ps(p, r, c2); - p = _mm256_fmadd_ps(p, r, c1); - p = _mm256_fmadd_ps(p, r, c0); - - __m256i ni = _mm256_cvtps_epi32(nf); - __m256i biased = _mm256_add_epi32(ni, _mm256_set1_epi32(127)); - __m256i scaled = _mm256_slli_epi32(biased, 23); - __m256 pow2n = _mm256_castsi256_ps(scaled); - - return _mm256_mul_ps(p, pow2n); // # 8 MULTs -} - -int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { - (void)pedestrians; -#if BENCHMARK - (void)dump_path; -#endif - -#if !BENCHMARK - const int dump_interval = 1; - - vector> samples; - - if (dump_path) { - samples.reserve(static_cast(n_iter / dump_interval + 1) * n_p); - - for (int i = 0; i < n_p; i++) { - samples.emplace_back(0, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } - } -#endif - - const int n_p_pad = (n_p + 7) & ~7; - - alignas(32) const float lane_offset_arr[8] = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f}; - const __m256 lane_off = _mm256_load_ps(lane_offset_arr); - - const __m256 v_neg_v0_div_2s = _mm256_set1_ps(NEG_V0_AB_div_TWO_SIGMA); - const __m256 v_neg_2s_inv = _mm256_set1_ps(NEG_TWO_SIGMA_INV); - const __m256 v_cos_phi_sq = _mm256_set1_ps(cos_phi_sq); - const __m256 v_dt_neg = _mm256_set1_ps(dt_neg); - const __m256 v_c_neg_dt = _mm256_set1_ps(c_neg_times_dt); - const __m256 v_zero = _mm256_setzero_ps(); - const __m256 v_eps_sq = _mm256_set1_ps(EPS_SQ); - const __m256 v_np = _mm256_set1_ps((float)n_p); - const __m256 v_exp_min = _mm256_set1_ps(-87.0f); - - // # flops per iteration (one pass of the outer time loop): - // # ADDs: n_p * 22 + n_p * n_p_pad * 29 + n_p * board.n_obstacles * 10 + n_p * 7 - // # MULTs: n_p * 4 + n_p * n_p_pad * 42 + n_p * board.n_obstacles * 13 + n_p * 16 - // # DIVs: n_p * n_p_pad * 3 + n_p * board.n_obstacles + n_p * 2 - // # SQRTs: n_p * n_p_pad * 3 + n_p * board.n_obstacles + n_p * 3 - // # EXPs: n_p * board.n_obstacles - for (int t = 0; t < n_iter; t++) { - - for (int i = 0; i < n_p; i++) { - - float desired_velocity_x = e_x[i] * desired_v0[i]; // # 1 MULT - float desired_velocity_y = e_y[i] * desired_v0[i]; // # 1 MULT - - float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; // # 1 MULT, 1 ADD - float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; // # 1 MULT, 1 ADD - - const __m256 pix = _mm256_set1_ps(pos_x[i]); - const __m256 piy = _mm256_set1_ps(pos_y[i]); - const __m256 eix = _mm256_set1_ps(e_x[i]); - const __m256 eiy = _mm256_set1_ps(e_y[i]); - const __m256 v_i = _mm256_set1_ps((float)i); - - __m256 acc_x = _mm256_setzero_ps(); - __m256 acc_y = _mm256_setzero_ps(); - - for (int j = 0; j < n_p_pad; j += 8) { - __m256 j_idx = _mm256_add_ps(_mm256_set1_ps((float)j), lane_off); // # 8 ADDs - - __m256 m_neq_i = _mm256_cmp_ps(j_idx, v_i, _CMP_NEQ_OQ); - __m256 m_in_range = _mm256_cmp_ps(j_idx, v_np, _CMP_LT_OQ); - __m256 active = _mm256_and_ps(m_neq_i, m_in_range); - - __m256 pjx = _mm256_loadu_ps(&pos_x[j]); - __m256 pjy = _mm256_loadu_ps(&pos_y[j]); - __m256 sbe_jx = _mm256_loadu_ps(&sb_e_x[j]); - __m256 sbe_jy = _mm256_loadu_ps(&sb_e_y[j]); - __m256 sb_jsq = _mm256_loadu_ps(&sb_sq[j]); - - __m256 r_ab_x = _mm256_sub_ps(pix, pjx); // # 8 ADDs - __m256 r_ab_y = _mm256_sub_ps(piy, pjy); // # 8 ADDs - __m256 r_ab_n2 = _mm256_fmadd_ps(r_ab_x, r_ab_x, _mm256_mul_ps(r_ab_y, r_ab_y)); // # 16 MULTs, 8 ADDs - // clamp before rsqrt: rsqrt(0) = inf, then x*inf = 0*inf = NaN downstream. EPS_SQ - // means the inv_sqrt tops out at 1/EPS and r_ab_n = EPS_SQ/EPS = EPS, matches the predecessor. - r_ab_n2 = _mm256_max_ps(r_ab_n2, v_eps_sq); - __m256 inv_r_ab_n = _mm256_rsqrt_ps(r_ab_n2); // # 8 SQRTs, 8 DIVs - __m256 r_ab_n = _mm256_mul_ps(r_ab_n2, inv_r_ab_n); // # 8 MULTs - - __m256 r_ab2_x = _mm256_sub_ps(r_ab_x, sbe_jx); // # 8 ADDs - __m256 r_ab2_y = _mm256_sub_ps(r_ab_y, sbe_jy); // # 8 ADDs - __m256 r_ab2_n2 = _mm256_fmadd_ps(r_ab2_x, r_ab2_x, _mm256_mul_ps(r_ab2_y, r_ab2_y)); // # 16 MULTs, 8 ADDs - r_ab2_n2 = _mm256_max_ps(r_ab2_n2, v_eps_sq); - __m256 inv_r_ab2_n = _mm256_rsqrt_ps(r_ab2_n2); // # 8 SQRTs, 8 DIVs - __m256 r_ab2_n = _mm256_mul_ps(r_ab2_n2, inv_r_ab2_n); // # 8 MULTs - - __m256 r_sum = _mm256_add_ps(r_ab_n, r_ab2_n); // # 8 ADDs - __m256 two_b_sq = _mm256_fmsub_ps(r_sum, r_sum, sb_jsq); // # 8 MULTs, 8 ADDs - two_b_sq = _mm256_max_ps(two_b_sq, v_eps_sq); - __m256 inv_two_b = _mm256_rsqrt_ps(two_b_sq); // # 8 SQRTs, 8 DIVs - __m256 two_b = _mm256_mul_ps(two_b_sq, inv_two_b); // # 8 MULTs - - __m256 e_arg = _mm256_mul_ps(two_b, v_neg_2s_inv); // # 8 MULTs - e_arg = _mm256_max_ps(e_arg, v_exp_min); - __m256 e_val = exp256_ps(e_arg); // # 128 MULTs, 112 ADDs - - // smc = numer/denom in the predecessor. with inv-sqrts in hand the divide is free: - // sm_r_ab = smc * r_ab2_n = numer / (two_b * r_ab_n) = numer * inv_two_b * inv_r_ab_n - // sm_r_ab2 = smc * r_ab_n = numer / (two_b * r_ab2_n) = numer * inv_two_b * inv_r_ab2_n - // for the i==j and padding lanes inv_two_b*inv_r_ab_n is huge, but the active-mask AND on - // f_x/f_y below zeros the lane out before accumulation so it cant pollute anything. - __m256 numer_inv_two_b = _mm256_mul_ps(_mm256_mul_ps(r_sum, v_neg_v0_div_2s), _mm256_mul_ps(e_val, inv_two_b)); // # 24 MULTs - __m256 sm_r_ab = _mm256_mul_ps(numer_inv_two_b, inv_r_ab_n); // # 8 MULTs - __m256 sm_r_ab2 = _mm256_mul_ps(numer_inv_two_b, inv_r_ab2_n); // # 8 MULTs - - __m256 f_x = _mm256_fmadd_ps(r_ab2_x, sm_r_ab2, _mm256_mul_ps(r_ab_x, sm_r_ab)); // # 16 MULTs, 8 ADDs - __m256 f_y = _mm256_fmadd_ps(r_ab2_y, sm_r_ab2, _mm256_mul_ps(r_ab_y, sm_r_ab)); // # 16 MULTs, 8 ADDs - - __m256 f_norm_sq = _mm256_fmadd_ps(f_x, f_x, _mm256_mul_ps(f_y, f_y)); // # 16 MULTs, 8 ADDs - __m256 rhs = _mm256_mul_ps(f_norm_sq, v_cos_phi_sq); // # 8 MULTs - __m256 e_dot_f = _mm256_fmadd_ps(eix, f_x, _mm256_mul_ps(eiy, f_y)); // # 16 MULTs, 8 ADDs - __m256 e_dot_f_sq = _mm256_mul_ps(e_dot_f, e_dot_f); // # 8 MULTs - - __m256 c1 = _mm256_cmp_ps(e_dot_f, v_zero, _CMP_LT_OQ); - __m256 c2 = _mm256_cmp_ps(e_dot_f_sq, rhs, _CMP_GT_OQ); - __m256 cond = _mm256_and_ps(c1, c2); - __m256 w_val = _mm256_blendv_ps(v_dt_neg, v_c_neg_dt, cond); - - __m256 f_x_safe = _mm256_and_ps(f_x, active); // bitwise, no flop - __m256 f_y_safe = _mm256_and_ps(f_y, active); // bitwise, no flop - acc_x = _mm256_fmadd_ps(f_x_safe, w_val, acc_x); // # 8 MULTs, 8 ADDs - acc_y = _mm256_fmadd_ps(f_y_safe, w_val, acc_y); // # 8 MULTs, 8 ADDs - } - - __m256 hsum = _mm256_hadd_ps(acc_x, acc_y); // # 8 ADDs (x and y interleaved) - __m128 hsum_lo = _mm256_castps256_ps128(hsum); - __m128 hsum_hi = _mm256_extractf128_ps(hsum, 1); - __m128 sum4 = _mm_add_ps(hsum_lo, hsum_hi); // # 4 ADDs - sum4 = _mm_hadd_ps(sum4, sum4); // # 4 ADDs (total hadd: 16 ADDs for x+y) - alignas(16) float sum_out[4]; - _mm_store_ps(sum_out, sum4); - f_alpha_dt_x += sum_out[0]; // # 1 ADD - f_alpha_dt_y += sum_out[1]; // # 1 ADD - - for (int k = 0; k < board.n_obstacles; k++) { - - float v1_x = pos_x[i] - board.obstacles[k].start_x; // # 1 ADD - float v1_y = pos_y[i] - board.obstacles[k].start_y; // # 1 ADD - float v2_x = board.obstacles[k].obstacle_v_x; - float v2_y = board.obstacles[k].obstacle_v_y; - - float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; // # 3 MULTs, 1 ADD - - if (projection < 0.0) - projection = 0.0; - else if (projection > 1.0) - projection = 1.0; - - float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); // # 1 MULT, 2 ADDs - float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); // # 1 MULT, 2 ADDs - - float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); // # 2 MULTs, 1 ADD, 1 SQRT - r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; - - float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; // # 2 MULTs, 1 EXP, 1 DIV - float f_alpha_B_neg_x = r_aB_x * scalar_mult; // # 1 MULT - float f_alpha_B_neg_y = r_aB_y * scalar_mult; // # 1 MULT - - float w_val; - - float e_dot_f = (f_alpha_B_neg_y == 0) ? 0 : (f_alpha_B_neg_y < 0 ? -e_y[i] : e_y[i]); - - if (e_dot_f >= cos_phi) - w_val = dt_neg; - else - w_val = c_neg_times_dt; - - float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; // # 1 MULT - float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; // # 1 MULT - - f_alpha_dt_x += f_alpha_B_dt_x; // # 1 ADD - f_alpha_dt_y += f_alpha_B_dt_y; // # 1 ADD - } - - w_x[i] += f_alpha_dt_x; // # 1 ADD - w_y[i] += f_alpha_dt_y; // # 1 ADD - } - - for (int i = 0; i < n_p; i++) { - - float w_norm = sqrt(w_x[i] * w_x[i] + w_y[i] * w_y[i]); // # 2 MULTs, 1 ADD, 1 SQRT - float w_norm2 = w_norm > EPS ? w_norm : EPS; - float correction_factor = min(1.0f, v_max[i] / w_norm2); // # 1 DIV - - curr_vel_x[i] = w_x[i] * correction_factor; // # 1 MULT - curr_vel_y[i] = w_y[i] * correction_factor; // # 1 MULT - - pos_x[i] = pos_x[i] + curr_vel_x[i] * dt; // # 1 MULT, 1 ADD - pos_y[i] = pos_y[i] + curr_vel_y[i] * dt; // # 1 MULT, 1 ADD - - if (color[i] == 0 && pos_x[i] > (BOARD_LENGTH - 1.5)) { - pos_x[i] = 1.0; - destination_y[i] = pos_y[i]; - w_x[i] = desired_v0[i]; - w_y[i] = 0.0; - curr_vel_x[i] = w_x[i]; - curr_vel_y[i] = w_y[i]; - } - if (color[i] == 1 && pos_x[i] < 1.5) { - pos_x[i] = BOARD_LENGTH - 1.0; - destination_y[i] = pos_y[i]; - w_x[i] = -desired_v0[i]; - w_y[i] = 0.0; - curr_vel_x[i] = w_x[i]; - curr_vel_y[i] = w_y[i]; - } - - pos_y[i] = clamp(pos_y[i], WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - - float ex = destination_x[i] - pos_x[i]; // # 1 ADD - float ey = destination_y[i] - pos_y[i]; // # 1 ADD - - float e_norm = sqrt(ex * ex + ey * ey); // # 2 MULTs, 1 ADD, 1 SQRT - float e_norm2 = e_norm > EPS ? e_norm : EPS; - float e_norm_inv = 1.0 / e_norm2; // # 1 DIV - - e_x[i] = ex * e_norm_inv; // # 1 MULT - e_y[i] = ey * e_norm_inv; // # 1 MULT - - float velocity_norm_sq = curr_vel_x[i] * curr_vel_x[i] + curr_vel_y[i] * curr_vel_y[i]; // # 2 MULTs, 1 ADD - float velocity_norm = sqrt(velocity_norm_sq); // # 1 SQRT - - sb_sq[i] = velocity_norm_sq * delta_t_sq; // # 1 MULT - sb_e_x[i] = e_x[i] * (velocity_norm * delta_t); // # 2 MULTs (vel_norm*delta_t shared with next line) - sb_e_y[i] = e_y[i] * (velocity_norm * delta_t); // # 1 MULT - -#if !BENCHMARK - if (dump_path && (t % dump_interval == 0)) { - samples.emplace_back(t + 1, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } -#endif - } - } - -#if !BENCHMARK - if (dump_path) { - ofstream out(dump_path); - out << "time,id,x,y,p.e.x,p.e.y,color\n"; - - for (auto &[t, id, x, y, e_x, e_y, c] : samples) { - out << t << ',' << id << ',' << x << ',' << y << ',' << e_x << ',' << e_y << ',' << c << '\n'; - } - } -#endif - - return 0; -} diff --git a/variants/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt.cpp b/variants/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt.cpp index 2efc3c5..e6760fb 100644 --- a/variants/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt.cpp +++ b/variants/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt.cpp @@ -187,23 +187,43 @@ Pedestrian *init_pedestrians(int n_p) { Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } -// simd expf, same as the predecessor. degree-5 taylor on the [-ln2/2, ln2/2] reduced range, +// simd expf, degree-12 taylor on the [-ln2/2, ln2/2] reduced range, // schraudolph 2^n bit trick on the exponent slot. +// # 128 MULTs, 112 ADDs static inline __m256 exp256_ps(__m256 x) { const __m256 log2e = _mm256_set1_ps(1.4426950408889634f); - __m256 nf = _mm256_round_ps(_mm256_mul_ps(x, log2e), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); + __m256 nf = _mm256_round_ps(_mm256_mul_ps(x, log2e), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); // # 8 MULTs const __m256 ln2 = _mm256_set1_ps(0.6931471805599453f); - __m256 r = _mm256_fnmadd_ps(nf, ln2, x); + __m256 r = _mm256_fnmadd_ps(nf, ln2, x); // # 8 MULTs, 8 ADDs - const __m256 c5 = _mm256_set1_ps(1.0f / 120.0f); - const __m256 c4 = _mm256_set1_ps(1.0f / 24.0f); - const __m256 c3 = _mm256_set1_ps(1.0f / 6.0f); - const __m256 c2 = _mm256_set1_ps(0.5f); - const __m256 c1 = _mm256_set1_ps(1.0f); - const __m256 c0 = _mm256_set1_ps(1.0f); + const __m256 c13 = _mm256_set1_ps(c13_scalar); + const __m256 c12 = _mm256_set1_ps(c12_scalar); + const __m256 c11 = _mm256_set1_ps(c11_scalar); + const __m256 c10 = _mm256_set1_ps(c10_scalar); + const __m256 c9 = _mm256_set1_ps(c9_scalar); + const __m256 c8 = _mm256_set1_ps(c8_scalar); + const __m256 c7 = _mm256_set1_ps(c7_scalar); + const __m256 c6 = _mm256_set1_ps(c6_scalar); + const __m256 c5 = _mm256_set1_ps(c5_scalar); + const __m256 c4 = _mm256_set1_ps(c4_scalar); + const __m256 c3 = _mm256_set1_ps(c3_scalar); + const __m256 c2 = _mm256_set1_ps(c2_scalar); + const __m256 c1 = _mm256_set1_ps(c1_scalar); + const __m256 c0 = _mm256_set1_ps(c0_scalar); - __m256 p = c5; + __m256 p = c13; + + // # 13 * (8 MULTs, 8 ADDs) + // # = 104 MULTs, 104 ADDs + p = _mm256_fmadd_ps(p, r, c12); + p = _mm256_fmadd_ps(p, r, c11); + p = _mm256_fmadd_ps(p, r, c10); + p = _mm256_fmadd_ps(p, r, c9); + p = _mm256_fmadd_ps(p, r, c8); + p = _mm256_fmadd_ps(p, r, c7); + p = _mm256_fmadd_ps(p, r, c6); + p = _mm256_fmadd_ps(p, r, c5); p = _mm256_fmadd_ps(p, r, c4); p = _mm256_fmadd_ps(p, r, c3); p = _mm256_fmadd_ps(p, r, c2); @@ -215,7 +235,7 @@ static inline __m256 exp256_ps(__m256 x) { __m256i scaled = _mm256_slli_epi32(biased, 23); __m256 pow2n = _mm256_castsi256_ps(scaled); - return _mm256_mul_ps(p, pow2n); + return _mm256_mul_ps(p, pow2n); // # 8 MULTs } int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { @@ -253,15 +273,21 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c // const __m256 v_np = _mm256_set1_ps((float)n_p); const __m256 v_exp_min = _mm256_set1_ps(-87.0f); + // # flops per iteration (one pass of the outer time loop): + // # ADDs: n_p * 22 + n_p * n_p_pad * 28 + n_p * board.n_obstacles * 10 + n_p * 7 + // # MULTs: n_p * 4 + n_p * n_p_pad * 42 + n_p * board.n_obstacles * 13 + n_p * 16 + // # DIVs: n_p * n_p_pad * 3 + n_p * board.n_obstacles + n_p * 2 + // # SQRTs: n_p * n_p_pad * 3 + n_p * board.n_obstacles + n_p * 3 + // # EXPs: n_p * board.n_obstacles for (int t = 0; t < n_iter; t++) { for (int i = 0; i < n_p; i++) { - float desired_velocity_x = e_x[i] * desired_v0[i]; - float desired_velocity_y = e_y[i] * desired_v0[i]; + float desired_velocity_x = e_x[i] * desired_v0[i]; // # 1 MULT + float desired_velocity_y = e_y[i] * desired_v0[i]; // # 1 MULT - float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; - float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; + float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; // # 1 MULT, 1 ADD + float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; // # 1 MULT, 1 ADD // ghost-self trick: park pedestrian i at 1e9 for its own j-loop, broadcasting i's // real position from a saved copy. then the j==i lane reads 1e9 like a padding lane @@ -291,51 +317,51 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m256 sbe_jy = _mm256_loadu_ps(&sb_e_y[j]); __m256 sb_jsq = _mm256_loadu_ps(&sb_sq[j]); - __m256 r_ab_x = _mm256_sub_ps(pix, pjx); - __m256 r_ab_y = _mm256_sub_ps(piy, pjy); - __m256 r_ab_n2 = _mm256_fmadd_ps(r_ab_x, r_ab_x, _mm256_mul_ps(r_ab_y, r_ab_y)); + __m256 r_ab_x = _mm256_sub_ps(pix, pjx); // # 8 ADDs + __m256 r_ab_y = _mm256_sub_ps(piy, pjy); // # 8 ADDs + __m256 r_ab_n2 = _mm256_fmadd_ps(r_ab_x, r_ab_x, _mm256_mul_ps(r_ab_y, r_ab_y)); // # 16 MULTs, 8 ADDs // clamp before rsqrt: rsqrt(0) = inf, then x*inf = 0*inf = NaN downstream. EPS_SQ // means the inv_sqrt tops out at 1/EPS and r_ab_n = EPS_SQ/EPS = EPS, matches the predecessor. r_ab_n2 = _mm256_max_ps(r_ab_n2, v_eps_sq); - __m256 inv_r_ab_n = _mm256_rsqrt_ps(r_ab_n2); + __m256 inv_r_ab_n = _mm256_rsqrt_ps(r_ab_n2); // # 8 SQRTs, 8 DIVs //__m256 r_ab_n = _mm256_mul_ps(r_ab_n2, inv_r_ab_n); - __m256 r_ab2_x = _mm256_sub_ps(r_ab_x, sbe_jx); - __m256 r_ab2_y = _mm256_sub_ps(r_ab_y, sbe_jy); - __m256 r_ab2_n2 = _mm256_fmadd_ps(r_ab2_x, r_ab2_x, _mm256_mul_ps(r_ab2_y, r_ab2_y)); + __m256 r_ab2_x = _mm256_sub_ps(r_ab_x, sbe_jx); // # 8 ADDs + __m256 r_ab2_y = _mm256_sub_ps(r_ab_y, sbe_jy); // # 8 ADDs + __m256 r_ab2_n2 = _mm256_fmadd_ps(r_ab2_x, r_ab2_x, _mm256_mul_ps(r_ab2_y, r_ab2_y)); // # 16 MULTs, 8 ADDs r_ab2_n2 = _mm256_max_ps(r_ab2_n2, v_eps_sq); - __m256 inv_r_ab2_n = _mm256_rsqrt_ps(r_ab2_n2); + __m256 inv_r_ab2_n = _mm256_rsqrt_ps(r_ab2_n2); // # 8 SQRTs, 8 DIVs //__m256 r_ab2_n = _mm256_mul_ps(r_ab2_n2, inv_r_ab2_n); // r_sum = |r_ab| + |r_ab2|, fused. sqrt(x) = x * rsqrt(x) // the two norms are used only here (later code uses inv_r_ab_n / inv_r_ab2_n), so fold the two // recovery muls + add into one mul + one fmadd. -1 FP op, -2 live regs. - __m256 r_sum = _mm256_fmadd_ps(r_ab2_n2, inv_r_ab2_n, _mm256_mul_ps(r_ab_n2, inv_r_ab_n)); - __m256 two_b_sq = _mm256_fmsub_ps(r_sum, r_sum, sb_jsq); + __m256 r_sum = _mm256_fmadd_ps(r_ab2_n2, inv_r_ab2_n, _mm256_mul_ps(r_ab_n2, inv_r_ab_n)); // # 16 MULTs, 8 ADDs + __m256 two_b_sq = _mm256_fmsub_ps(r_sum, r_sum, sb_jsq); // # 8 MULTs, 8 ADDs two_b_sq = _mm256_max_ps(two_b_sq, v_eps_sq); - __m256 inv_two_b = _mm256_rsqrt_ps(two_b_sq); - __m256 two_b = _mm256_mul_ps(two_b_sq, inv_two_b); + __m256 inv_two_b = _mm256_rsqrt_ps(two_b_sq); // # 8 SQRTs, 8 DIVs + __m256 two_b = _mm256_mul_ps(two_b_sq, inv_two_b); // # 8 MULTs - __m256 e_arg = _mm256_mul_ps(two_b, v_neg_2s_inv); + __m256 e_arg = _mm256_mul_ps(two_b, v_neg_2s_inv); // # 8 MULTs e_arg = _mm256_max_ps(e_arg, v_exp_min); - __m256 e_val = exp256_ps(e_arg); + __m256 e_val = exp256_ps(e_arg); // # 128 MULTs, 112 ADDs // smc = numer/denom in the predecessor. with inv-sqrts in hand the divide is free: // sm_r_ab = smc * r_ab2_n = numer / (two_b * r_ab_n) = numer * inv_two_b * inv_r_ab_n // sm_r_ab2 = smc * r_ab_n = numer / (two_b * r_ab2_n) = numer * inv_two_b * inv_r_ab2_n // for the i==j and padding lanes inv_two_b*inv_r_ab_n is huge, but the active-mask AND on // f_x/f_y below zeros the lane out before accumulation so it cant pollute anything. - __m256 numer_inv_two_b = _mm256_mul_ps(_mm256_mul_ps(r_sum, v_neg_v0_div_2s), _mm256_mul_ps(e_val, inv_two_b)); - __m256 sm_r_ab = _mm256_mul_ps(numer_inv_two_b, inv_r_ab_n); - __m256 sm_r_ab2 = _mm256_mul_ps(numer_inv_two_b, inv_r_ab2_n); + __m256 numer_inv_two_b = _mm256_mul_ps(_mm256_mul_ps(r_sum, v_neg_v0_div_2s), _mm256_mul_ps(e_val, inv_two_b)); // # 24 MULTs + __m256 sm_r_ab = _mm256_mul_ps(numer_inv_two_b, inv_r_ab_n); // # 8 MULTs + __m256 sm_r_ab2 = _mm256_mul_ps(numer_inv_two_b, inv_r_ab2_n); // # 8 MULTs - __m256 f_x = _mm256_fmadd_ps(r_ab2_x, sm_r_ab2, _mm256_mul_ps(r_ab_x, sm_r_ab)); - __m256 f_y = _mm256_fmadd_ps(r_ab2_y, sm_r_ab2, _mm256_mul_ps(r_ab_y, sm_r_ab)); + __m256 f_x = _mm256_fmadd_ps(r_ab2_x, sm_r_ab2, _mm256_mul_ps(r_ab_x, sm_r_ab)); // # 16 MULTs, 8 ADDs + __m256 f_y = _mm256_fmadd_ps(r_ab2_y, sm_r_ab2, _mm256_mul_ps(r_ab_y, sm_r_ab)); // # 16 MULTs, 8 ADDs - __m256 f_norm_sq = _mm256_fmadd_ps(f_x, f_x, _mm256_mul_ps(f_y, f_y)); - __m256 rhs = _mm256_mul_ps(f_norm_sq, v_cos_phi_sq); - __m256 e_dot_f = _mm256_fmadd_ps(eix, f_x, _mm256_mul_ps(eiy, f_y)); - __m256 e_dot_f_sq = _mm256_mul_ps(e_dot_f, e_dot_f); + __m256 f_norm_sq = _mm256_fmadd_ps(f_x, f_x, _mm256_mul_ps(f_y, f_y)); // # 16 MULTs, 8 ADDs + __m256 rhs = _mm256_mul_ps(f_norm_sq, v_cos_phi_sq); // # 8 MULTs + __m256 e_dot_f = _mm256_fmadd_ps(eix, f_x, _mm256_mul_ps(eiy, f_y)); // # 16 MULTs, 8 ADDs + __m256 e_dot_f_sq = _mm256_mul_ps(e_dot_f, e_dot_f); // # 8 MULTs __m256 c1 = _mm256_cmp_ps(e_dot_f, v_zero, _CMP_LT_OQ); __m256 c2 = _mm256_cmp_ps(e_dot_f_sq, rhs, _CMP_GT_OQ); @@ -344,47 +370,47 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c //__m256 f_x_safe = _mm256_and_ps(f_x, active); //__m256 f_y_safe = _mm256_and_ps(f_y, active); - acc_x = _mm256_fmadd_ps(f_x, w_val, acc_x); - acc_y = _mm256_fmadd_ps(f_y, w_val, acc_y); + acc_x = _mm256_fmadd_ps(f_x, w_val, acc_x); // # 8 MULTs, 8 ADDs + acc_y = _mm256_fmadd_ps(f_y, w_val, acc_y); // # 8 MULTs, 8 ADDs } // restore the values pos_x[i] = saved_pix; pos_y[i] = saved_piy; - __m256 hsum = _mm256_hadd_ps(acc_x, acc_y); + __m256 hsum = _mm256_hadd_ps(acc_x, acc_y); // # 8 ADDs (x and y interleaved) __m128 hsum_lo = _mm256_castps256_ps128(hsum); __m128 hsum_hi = _mm256_extractf128_ps(hsum, 1); - __m128 sum4 = _mm_add_ps(hsum_lo, hsum_hi); - sum4 = _mm_hadd_ps(sum4, sum4); + __m128 sum4 = _mm_add_ps(hsum_lo, hsum_hi); // # 4 ADDs + sum4 = _mm_hadd_ps(sum4, sum4); // # 4 ADDs (total hadd: 16 ADDs for x+y) alignas(16) float sum_out[4]; _mm_store_ps(sum_out, sum4); - f_alpha_dt_x += sum_out[0]; - f_alpha_dt_y += sum_out[1]; + f_alpha_dt_x += sum_out[0]; // # 1 ADD + f_alpha_dt_y += sum_out[1]; // # 1 ADD for (int k = 0; k < board.n_obstacles; k++) { - float v1_x = pos_x[i] - board.obstacles[k].start_x; - float v1_y = pos_y[i] - board.obstacles[k].start_y; + float v1_x = pos_x[i] - board.obstacles[k].start_x; // # 1 ADD + float v1_y = pos_y[i] - board.obstacles[k].start_y; // # 1 ADD float v2_x = board.obstacles[k].obstacle_v_x; float v2_y = board.obstacles[k].obstacle_v_y; - float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; + float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; // # 3 MULTs, 1 ADD if (projection < 0.0) projection = 0.0; else if (projection > 1.0) projection = 1.0; - float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); - float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); + float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); // # 1 MULT, 2 ADDs + float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); // # 1 MULT, 2 ADDs - float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); + float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); // # 2 MULTs, 1 ADD, 1 SQRT r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; - float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; - float f_alpha_B_neg_x = r_aB_x * scalar_mult; - float f_alpha_B_neg_y = r_aB_y * scalar_mult; + float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; // # 2 MULTs, 1 EXP, 1 DIV + float f_alpha_B_neg_x = r_aB_x * scalar_mult; // # 1 MULT + float f_alpha_B_neg_y = r_aB_y * scalar_mult; // # 1 MULT float w_val; @@ -395,28 +421,28 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c else w_val = c_neg_times_dt; - float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; - float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; + float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; // # 1 MULT + float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; // # 1 MULT - f_alpha_dt_x += f_alpha_B_dt_x; - f_alpha_dt_y += f_alpha_B_dt_y; + f_alpha_dt_x += f_alpha_B_dt_x; // # 1 ADD + f_alpha_dt_y += f_alpha_B_dt_y; // # 1 ADD } - w_x[i] += f_alpha_dt_x; - w_y[i] += f_alpha_dt_y; + w_x[i] += f_alpha_dt_x; // # 1 ADD + w_y[i] += f_alpha_dt_y; // # 1 ADD } for (int i = 0; i < n_p; i++) { - float w_norm = sqrt(w_x[i] * w_x[i] + w_y[i] * w_y[i]); + float w_norm = sqrt(w_x[i] * w_x[i] + w_y[i] * w_y[i]); // # 2 MULTs, 1 ADD, 1 SQRT float w_norm2 = w_norm > EPS ? w_norm : EPS; - float correction_factor = min(1.0f, v_max[i] / w_norm2); + float correction_factor = min(1.0f, v_max[i] / w_norm2); // # 1 DIV - curr_vel_x[i] = w_x[i] * correction_factor; - curr_vel_y[i] = w_y[i] * correction_factor; + curr_vel_x[i] = w_x[i] * correction_factor; // # 1 MULT + curr_vel_y[i] = w_y[i] * correction_factor; // # 1 MULT - pos_x[i] = pos_x[i] + curr_vel_x[i] * dt; - pos_y[i] = pos_y[i] + curr_vel_y[i] * dt; + pos_x[i] = pos_x[i] + curr_vel_x[i] * dt; // # 1 MULT, 1 ADD + pos_y[i] = pos_y[i] + curr_vel_y[i] * dt; // # 1 MULT, 1 ADD if (color[i] == 0 && pos_x[i] > (BOARD_LENGTH - 1.5)) { pos_x[i] = 1.0; @@ -437,22 +463,22 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c pos_y[i] = clamp(pos_y[i], WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - float ex = destination_x[i] - pos_x[i]; - float ey = destination_y[i] - pos_y[i]; + float ex = destination_x[i] - pos_x[i]; // # 1 ADD + float ey = destination_y[i] - pos_y[i]; // # 1 ADD - float e_norm = sqrt(ex * ex + ey * ey); + float e_norm = sqrt(ex * ex + ey * ey); // # 2 MULTs, 1 ADD, 1 SQRT float e_norm2 = e_norm > EPS ? e_norm : EPS; - float e_norm_inv = 1.0 / e_norm2; + float e_norm_inv = 1.0 / e_norm2; // # 1 DIV - e_x[i] = ex * e_norm_inv; - e_y[i] = ey * e_norm_inv; + e_x[i] = ex * e_norm_inv; // # 1 MULT + e_y[i] = ey * e_norm_inv; // # 1 MULT - float velocity_norm_sq = curr_vel_x[i] * curr_vel_x[i] + curr_vel_y[i] * curr_vel_y[i]; - float velocity_norm = sqrt(velocity_norm_sq); + float velocity_norm_sq = curr_vel_x[i] * curr_vel_x[i] + curr_vel_y[i] * curr_vel_y[i]; // # 2 MULTs, 1 ADD + float velocity_norm = sqrt(velocity_norm_sq); // # 1 SQRT - sb_sq[i] = velocity_norm_sq * delta_t_sq; - sb_e_x[i] = e_x[i] * (velocity_norm * delta_t); - sb_e_y[i] = e_y[i] * (velocity_norm * delta_t); + sb_sq[i] = velocity_norm_sq * delta_t_sq; // # 1 MULT + sb_e_x[i] = e_x[i] * (velocity_norm * delta_t); // # 2 MULTs (vel_norm*delta_t shared with next line) + sb_e_y[i] = e_y[i] * (velocity_norm * delta_t); // # 1 MULT #if !BENCHMARK if (dump_path && (t % dump_interval == 0)) { diff --git a/variants/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt_expfix.cpp b/variants/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt_expfix.cpp deleted file mode 100644 index e6760fb..0000000 --- a/variants/variant_float_inlining_SoA_AVX2_polyexp_rsqrt_loopopt_expfix.cpp +++ /dev/null @@ -1,503 +0,0 @@ -// # Changes: pure vrsqrtps -// # Predecessor: variant_float_inlining_SoA_AVX2_polyexp.cpp - -// -// We first tried rsqrt + 1 Newton step to keep full sqrt precision, but it -// turned out slower than just using vsqrtps. The Newton step needs 2 muls -// and an fnmadd on top of rsqrt, so the whole recovered sqrt ends up at -// ~20 cycles of latency, while vsqrtps is only 12. Since the OoO core was -// already running multiple sqrts in parallel, sqrt throughput wasn't really -// the bottleneck. All the Newton step did was make the dependency chain -// longer, which hurt more than the faster rsqrt helped. -// -// So we drop the Newton step. rsqrt + 1 mul gives us a sqrt in 8 cycles -// with about 12-bit precision, which is well within the 1cm verify tolerance. - -// The main structural win is killing the vdivps. rsqrt produces 1/sqrt(x) -// directly, so we keep the inverses around (inv_r_ab_n, inv_r_ab2_n, -// inv_two_b) and rewrite the force scaling. The original had -// "numer / (two_b * r_ab_n * r_ab2_n)" which needs a vdivps; now it's -// "numer * inv_two_b * inv_r_ab_n * inv_r_ab2_n", trading one divide for -// two muls. Divide was the long-pole op on port 0, so this is the bigger -// of the two changes. - -#include "../headers/board_reduced_float.hpp" -#include "../headers/constants_float.hpp" -#include "../headers/pedestrian_reduced_float.hpp" - -#include // avx2 - -#include -#include -#include -#include -#include -#include -#include -#include - -#define SEED 42 -#define BOARD_WIDTH 10.0f -#define BOARD_LENGTH 50.0f -#define WALL_EPS 1e-3f -#define BOARD_WIDTH_MINUS_WALL_EPS 9.999f - -#ifndef RANDOM_SEED -#define RANDOM_SEED 0 -#endif - -#ifndef BENCHMARK -#define BENCHMARK 0 -#endif - -using namespace std; - -vector pos_x, pos_y; -vector sb_sq; -vector sb_e_x, sb_e_y; -vector e_x, e_y; -vector curr_vel_x, curr_vel_y; -vector w_x, w_y; -vector desired_v0; -vector v_max; -vector destination_x, destination_y; -vector color; - -Pedestrian *init_pedestrians(int n_p) { -#if RANDOM_SEED - random_device rd; - mt19937 gen(rd()); -#else - mt19937 gen(SEED); -#endif - - normal_distribution velocity_gen(v0_mean, v0_std_dev); - uniform_real_distribution y_gen(0.3, BOARD_WIDTH - 0.3); - uniform_real_distribution x_gen_left(2.0, BOARD_LENGTH / 2.0); - uniform_real_distribution x_gen_right(BOARD_LENGTH / 2.0, BOARD_LENGTH - 2.0); - - const int n_p_pad = (n_p + 7) & ~7; - - pos_x.resize(n_p_pad); - pos_y.resize(n_p_pad); - sb_sq.resize(n_p_pad); - sb_e_x.resize(n_p_pad); - sb_e_y.resize(n_p_pad); - e_x.resize(n_p_pad); - e_y.resize(n_p_pad); - curr_vel_x.resize(n_p_pad); - curr_vel_y.resize(n_p_pad); - w_x.resize(n_p_pad); - w_y.resize(n_p_pad); - desired_v0.resize(n_p_pad); - v_max.resize(n_p_pad); - destination_x.resize(n_p_pad); - destination_y.resize(n_p_pad); - color.resize(n_p_pad); - - int n_p_half = n_p / 2; - - for (int i = 0; i < n_p_half; i++) { - float x = x_gen_left(gen); - float y = y_gen(gen); - - float dest_x = BOARD_LENGTH + 30.0; - float dest_y = y; - - float init_e_x = dest_x - x; - float init_e_y = dest_y - y; - float init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - float init_e_unit_x = init_e_x / init_e_norm; - float init_e_unit_y = init_e_y / init_e_norm; - - float d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1); - - float v_m = 1.3 * d_v0; - - color[i] = 0; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - w_x[i] = 0.0f; - w_y[i] = 0.0f; - curr_vel_x[i] = 0.0f; - curr_vel_y[i] = 0.0f; - sb_sq[i] = 0.0f; - sb_e_x[i] = 0.0f; - sb_e_y[i] = 0.0f; - } - - for (int i = n_p_half; i < n_p; i++) { - float x = x_gen_right(gen); - float y = y_gen(gen); - - float dest_x = -30; - float dest_y = y; - - float init_e_x = dest_x - x; - float init_e_y = dest_y - y; - float init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - float init_e_unit_x = init_e_x / init_e_norm; - float init_e_unit_y = init_e_y / init_e_norm; - - float d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1); - - float v_m = 1.3 * d_v0; - - color[i] = 1; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - w_x[i] = 0.0f; - w_y[i] = 0.0f; - curr_vel_x[i] = 0.0f; - curr_vel_y[i] = 0.0f; - sb_sq[i] = 0.0f; - sb_e_x[i] = 0.0f; - sb_e_y[i] = 0.0f; - } - - for (int j = n_p; j < n_p_pad; j++) { - pos_x[j] = 1e9f; - pos_y[j] = 1e9f; - sb_sq[j] = 0.0f; - sb_e_x[j] = 0.0f; - sb_e_y[j] = 0.0f; - } - return nullptr; -} - -Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } - -// simd expf, degree-12 taylor on the [-ln2/2, ln2/2] reduced range, -// schraudolph 2^n bit trick on the exponent slot. -// # 128 MULTs, 112 ADDs -static inline __m256 exp256_ps(__m256 x) { - const __m256 log2e = _mm256_set1_ps(1.4426950408889634f); - __m256 nf = _mm256_round_ps(_mm256_mul_ps(x, log2e), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); // # 8 MULTs - - const __m256 ln2 = _mm256_set1_ps(0.6931471805599453f); - __m256 r = _mm256_fnmadd_ps(nf, ln2, x); // # 8 MULTs, 8 ADDs - - const __m256 c13 = _mm256_set1_ps(c13_scalar); - const __m256 c12 = _mm256_set1_ps(c12_scalar); - const __m256 c11 = _mm256_set1_ps(c11_scalar); - const __m256 c10 = _mm256_set1_ps(c10_scalar); - const __m256 c9 = _mm256_set1_ps(c9_scalar); - const __m256 c8 = _mm256_set1_ps(c8_scalar); - const __m256 c7 = _mm256_set1_ps(c7_scalar); - const __m256 c6 = _mm256_set1_ps(c6_scalar); - const __m256 c5 = _mm256_set1_ps(c5_scalar); - const __m256 c4 = _mm256_set1_ps(c4_scalar); - const __m256 c3 = _mm256_set1_ps(c3_scalar); - const __m256 c2 = _mm256_set1_ps(c2_scalar); - const __m256 c1 = _mm256_set1_ps(c1_scalar); - const __m256 c0 = _mm256_set1_ps(c0_scalar); - - __m256 p = c13; - - // # 13 * (8 MULTs, 8 ADDs) - // # = 104 MULTs, 104 ADDs - p = _mm256_fmadd_ps(p, r, c12); - p = _mm256_fmadd_ps(p, r, c11); - p = _mm256_fmadd_ps(p, r, c10); - p = _mm256_fmadd_ps(p, r, c9); - p = _mm256_fmadd_ps(p, r, c8); - p = _mm256_fmadd_ps(p, r, c7); - p = _mm256_fmadd_ps(p, r, c6); - p = _mm256_fmadd_ps(p, r, c5); - p = _mm256_fmadd_ps(p, r, c4); - p = _mm256_fmadd_ps(p, r, c3); - p = _mm256_fmadd_ps(p, r, c2); - p = _mm256_fmadd_ps(p, r, c1); - p = _mm256_fmadd_ps(p, r, c0); - - __m256i ni = _mm256_cvtps_epi32(nf); - __m256i biased = _mm256_add_epi32(ni, _mm256_set1_epi32(127)); - __m256i scaled = _mm256_slli_epi32(biased, 23); - __m256 pow2n = _mm256_castsi256_ps(scaled); - - return _mm256_mul_ps(p, pow2n); // # 8 MULTs -} - -int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { - (void)pedestrians; -#if BENCHMARK - (void)dump_path; -#endif - -#if !BENCHMARK - const int dump_interval = 1; - - vector> samples; - - if (dump_path) { - samples.reserve(static_cast(n_iter / dump_interval + 1) * n_p); - - for (int i = 0; i < n_p; i++) { - samples.emplace_back(0, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } - } -#endif - - const int n_p_pad = (n_p + 7) & ~7; - - alignas(32) const float lane_offset_arr[8] = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f}; - const __m256 lane_off = _mm256_load_ps(lane_offset_arr); - - const __m256 v_neg_v0_div_2s = _mm256_set1_ps(NEG_V0_AB_div_TWO_SIGMA); - const __m256 v_neg_2s_inv = _mm256_set1_ps(NEG_TWO_SIGMA_INV); - const __m256 v_cos_phi_sq = _mm256_set1_ps(cos_phi_sq); - const __m256 v_dt_neg = _mm256_set1_ps(dt_neg); - const __m256 v_c_neg_dt = _mm256_set1_ps(c_neg_times_dt); - const __m256 v_zero = _mm256_setzero_ps(); - const __m256 v_eps_sq = _mm256_set1_ps(EPS_SQ); - // const __m256 v_np = _mm256_set1_ps((float)n_p); - const __m256 v_exp_min = _mm256_set1_ps(-87.0f); - - // # flops per iteration (one pass of the outer time loop): - // # ADDs: n_p * 22 + n_p * n_p_pad * 28 + n_p * board.n_obstacles * 10 + n_p * 7 - // # MULTs: n_p * 4 + n_p * n_p_pad * 42 + n_p * board.n_obstacles * 13 + n_p * 16 - // # DIVs: n_p * n_p_pad * 3 + n_p * board.n_obstacles + n_p * 2 - // # SQRTs: n_p * n_p_pad * 3 + n_p * board.n_obstacles + n_p * 3 - // # EXPs: n_p * board.n_obstacles - for (int t = 0; t < n_iter; t++) { - - for (int i = 0; i < n_p; i++) { - - float desired_velocity_x = e_x[i] * desired_v0[i]; // # 1 MULT - float desired_velocity_y = e_y[i] * desired_v0[i]; // # 1 MULT - - float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; // # 1 MULT, 1 ADD - float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; // # 1 MULT, 1 ADD - - // ghost-self trick: park pedestrian i at 1e9 for its own j-loop, broadcasting i's - // real position from a saved copy. then the j==i lane reads 1e9 like a padding lane - // -> ~1e-37 force, self-cancels with no mask. restored right after the loop. - const float saved_pix = pos_x[i]; - const float saved_piy = pos_y[i]; - const __m256 pix = _mm256_set1_ps(saved_pix); - const __m256 piy = _mm256_set1_ps(saved_piy); - const __m256 eix = _mm256_set1_ps(e_x[i]); - const __m256 eiy = _mm256_set1_ps(e_y[i]); - pos_x[i] = 1e9f; - pos_y[i] = 1e9f; - - __m256 acc_x = _mm256_setzero_ps(); - __m256 acc_y = _mm256_setzero_ps(); - - for (int j = 0; j < n_p_pad; j += 8) { - // __m256 j_idx = _mm256_add_ps(_mm256_set1_ps((float)j), lane_off); - // - // __m256 m_neq_i = _mm256_cmp_ps(j_idx, v_i, _CMP_NEQ_OQ); - // __m256 m_in_range = _mm256_cmp_ps(j_idx, v_np, _CMP_LT_OQ); - // __m256 active = _mm256_and_ps(m_neq_i, m_in_range); - - __m256 pjx = _mm256_loadu_ps(&pos_x[j]); - __m256 pjy = _mm256_loadu_ps(&pos_y[j]); - __m256 sbe_jx = _mm256_loadu_ps(&sb_e_x[j]); - __m256 sbe_jy = _mm256_loadu_ps(&sb_e_y[j]); - __m256 sb_jsq = _mm256_loadu_ps(&sb_sq[j]); - - __m256 r_ab_x = _mm256_sub_ps(pix, pjx); // # 8 ADDs - __m256 r_ab_y = _mm256_sub_ps(piy, pjy); // # 8 ADDs - __m256 r_ab_n2 = _mm256_fmadd_ps(r_ab_x, r_ab_x, _mm256_mul_ps(r_ab_y, r_ab_y)); // # 16 MULTs, 8 ADDs - // clamp before rsqrt: rsqrt(0) = inf, then x*inf = 0*inf = NaN downstream. EPS_SQ - // means the inv_sqrt tops out at 1/EPS and r_ab_n = EPS_SQ/EPS = EPS, matches the predecessor. - r_ab_n2 = _mm256_max_ps(r_ab_n2, v_eps_sq); - __m256 inv_r_ab_n = _mm256_rsqrt_ps(r_ab_n2); // # 8 SQRTs, 8 DIVs - //__m256 r_ab_n = _mm256_mul_ps(r_ab_n2, inv_r_ab_n); - - __m256 r_ab2_x = _mm256_sub_ps(r_ab_x, sbe_jx); // # 8 ADDs - __m256 r_ab2_y = _mm256_sub_ps(r_ab_y, sbe_jy); // # 8 ADDs - __m256 r_ab2_n2 = _mm256_fmadd_ps(r_ab2_x, r_ab2_x, _mm256_mul_ps(r_ab2_y, r_ab2_y)); // # 16 MULTs, 8 ADDs - r_ab2_n2 = _mm256_max_ps(r_ab2_n2, v_eps_sq); - __m256 inv_r_ab2_n = _mm256_rsqrt_ps(r_ab2_n2); // # 8 SQRTs, 8 DIVs - //__m256 r_ab2_n = _mm256_mul_ps(r_ab2_n2, inv_r_ab2_n); - - // r_sum = |r_ab| + |r_ab2|, fused. sqrt(x) = x * rsqrt(x) - // the two norms are used only here (later code uses inv_r_ab_n / inv_r_ab2_n), so fold the two - // recovery muls + add into one mul + one fmadd. -1 FP op, -2 live regs. - __m256 r_sum = _mm256_fmadd_ps(r_ab2_n2, inv_r_ab2_n, _mm256_mul_ps(r_ab_n2, inv_r_ab_n)); // # 16 MULTs, 8 ADDs - __m256 two_b_sq = _mm256_fmsub_ps(r_sum, r_sum, sb_jsq); // # 8 MULTs, 8 ADDs - two_b_sq = _mm256_max_ps(two_b_sq, v_eps_sq); - __m256 inv_two_b = _mm256_rsqrt_ps(two_b_sq); // # 8 SQRTs, 8 DIVs - __m256 two_b = _mm256_mul_ps(two_b_sq, inv_two_b); // # 8 MULTs - - __m256 e_arg = _mm256_mul_ps(two_b, v_neg_2s_inv); // # 8 MULTs - e_arg = _mm256_max_ps(e_arg, v_exp_min); - __m256 e_val = exp256_ps(e_arg); // # 128 MULTs, 112 ADDs - - // smc = numer/denom in the predecessor. with inv-sqrts in hand the divide is free: - // sm_r_ab = smc * r_ab2_n = numer / (two_b * r_ab_n) = numer * inv_two_b * inv_r_ab_n - // sm_r_ab2 = smc * r_ab_n = numer / (two_b * r_ab2_n) = numer * inv_two_b * inv_r_ab2_n - // for the i==j and padding lanes inv_two_b*inv_r_ab_n is huge, but the active-mask AND on - // f_x/f_y below zeros the lane out before accumulation so it cant pollute anything. - __m256 numer_inv_two_b = _mm256_mul_ps(_mm256_mul_ps(r_sum, v_neg_v0_div_2s), _mm256_mul_ps(e_val, inv_two_b)); // # 24 MULTs - __m256 sm_r_ab = _mm256_mul_ps(numer_inv_two_b, inv_r_ab_n); // # 8 MULTs - __m256 sm_r_ab2 = _mm256_mul_ps(numer_inv_two_b, inv_r_ab2_n); // # 8 MULTs - - __m256 f_x = _mm256_fmadd_ps(r_ab2_x, sm_r_ab2, _mm256_mul_ps(r_ab_x, sm_r_ab)); // # 16 MULTs, 8 ADDs - __m256 f_y = _mm256_fmadd_ps(r_ab2_y, sm_r_ab2, _mm256_mul_ps(r_ab_y, sm_r_ab)); // # 16 MULTs, 8 ADDs - - __m256 f_norm_sq = _mm256_fmadd_ps(f_x, f_x, _mm256_mul_ps(f_y, f_y)); // # 16 MULTs, 8 ADDs - __m256 rhs = _mm256_mul_ps(f_norm_sq, v_cos_phi_sq); // # 8 MULTs - __m256 e_dot_f = _mm256_fmadd_ps(eix, f_x, _mm256_mul_ps(eiy, f_y)); // # 16 MULTs, 8 ADDs - __m256 e_dot_f_sq = _mm256_mul_ps(e_dot_f, e_dot_f); // # 8 MULTs - - __m256 c1 = _mm256_cmp_ps(e_dot_f, v_zero, _CMP_LT_OQ); - __m256 c2 = _mm256_cmp_ps(e_dot_f_sq, rhs, _CMP_GT_OQ); - __m256 cond = _mm256_and_ps(c1, c2); - __m256 w_val = _mm256_blendv_ps(v_dt_neg, v_c_neg_dt, cond); - - //__m256 f_x_safe = _mm256_and_ps(f_x, active); - //__m256 f_y_safe = _mm256_and_ps(f_y, active); - acc_x = _mm256_fmadd_ps(f_x, w_val, acc_x); // # 8 MULTs, 8 ADDs - acc_y = _mm256_fmadd_ps(f_y, w_val, acc_y); // # 8 MULTs, 8 ADDs - } - - // restore the values - pos_x[i] = saved_pix; - pos_y[i] = saved_piy; - - __m256 hsum = _mm256_hadd_ps(acc_x, acc_y); // # 8 ADDs (x and y interleaved) - __m128 hsum_lo = _mm256_castps256_ps128(hsum); - __m128 hsum_hi = _mm256_extractf128_ps(hsum, 1); - __m128 sum4 = _mm_add_ps(hsum_lo, hsum_hi); // # 4 ADDs - sum4 = _mm_hadd_ps(sum4, sum4); // # 4 ADDs (total hadd: 16 ADDs for x+y) - alignas(16) float sum_out[4]; - _mm_store_ps(sum_out, sum4); - f_alpha_dt_x += sum_out[0]; // # 1 ADD - f_alpha_dt_y += sum_out[1]; // # 1 ADD - - for (int k = 0; k < board.n_obstacles; k++) { - - float v1_x = pos_x[i] - board.obstacles[k].start_x; // # 1 ADD - float v1_y = pos_y[i] - board.obstacles[k].start_y; // # 1 ADD - float v2_x = board.obstacles[k].obstacle_v_x; - float v2_y = board.obstacles[k].obstacle_v_y; - - float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; // # 3 MULTs, 1 ADD - - if (projection < 0.0) - projection = 0.0; - else if (projection > 1.0) - projection = 1.0; - - float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); // # 1 MULT, 2 ADDs - float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); // # 1 MULT, 2 ADDs - - float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); // # 2 MULTs, 1 ADD, 1 SQRT - r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; - - float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; // # 2 MULTs, 1 EXP, 1 DIV - float f_alpha_B_neg_x = r_aB_x * scalar_mult; // # 1 MULT - float f_alpha_B_neg_y = r_aB_y * scalar_mult; // # 1 MULT - - float w_val; - - float e_dot_f = (f_alpha_B_neg_y == 0) ? 0 : (f_alpha_B_neg_y < 0 ? -e_y[i] : e_y[i]); - - if (e_dot_f >= cos_phi) - w_val = dt_neg; - else - w_val = c_neg_times_dt; - - float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; // # 1 MULT - float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; // # 1 MULT - - f_alpha_dt_x += f_alpha_B_dt_x; // # 1 ADD - f_alpha_dt_y += f_alpha_B_dt_y; // # 1 ADD - } - - w_x[i] += f_alpha_dt_x; // # 1 ADD - w_y[i] += f_alpha_dt_y; // # 1 ADD - } - - for (int i = 0; i < n_p; i++) { - - float w_norm = sqrt(w_x[i] * w_x[i] + w_y[i] * w_y[i]); // # 2 MULTs, 1 ADD, 1 SQRT - float w_norm2 = w_norm > EPS ? w_norm : EPS; - float correction_factor = min(1.0f, v_max[i] / w_norm2); // # 1 DIV - - curr_vel_x[i] = w_x[i] * correction_factor; // # 1 MULT - curr_vel_y[i] = w_y[i] * correction_factor; // # 1 MULT - - pos_x[i] = pos_x[i] + curr_vel_x[i] * dt; // # 1 MULT, 1 ADD - pos_y[i] = pos_y[i] + curr_vel_y[i] * dt; // # 1 MULT, 1 ADD - - if (color[i] == 0 && pos_x[i] > (BOARD_LENGTH - 1.5)) { - pos_x[i] = 1.0; - destination_y[i] = pos_y[i]; - w_x[i] = desired_v0[i]; - w_y[i] = 0.0; - curr_vel_x[i] = w_x[i]; - curr_vel_y[i] = w_y[i]; - } - if (color[i] == 1 && pos_x[i] < 1.5) { - pos_x[i] = BOARD_LENGTH - 1.0; - destination_y[i] = pos_y[i]; - w_x[i] = -desired_v0[i]; - w_y[i] = 0.0; - curr_vel_x[i] = w_x[i]; - curr_vel_y[i] = w_y[i]; - } - - pos_y[i] = clamp(pos_y[i], WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - - float ex = destination_x[i] - pos_x[i]; // # 1 ADD - float ey = destination_y[i] - pos_y[i]; // # 1 ADD - - float e_norm = sqrt(ex * ex + ey * ey); // # 2 MULTs, 1 ADD, 1 SQRT - float e_norm2 = e_norm > EPS ? e_norm : EPS; - float e_norm_inv = 1.0 / e_norm2; // # 1 DIV - - e_x[i] = ex * e_norm_inv; // # 1 MULT - e_y[i] = ey * e_norm_inv; // # 1 MULT - - float velocity_norm_sq = curr_vel_x[i] * curr_vel_x[i] + curr_vel_y[i] * curr_vel_y[i]; // # 2 MULTs, 1 ADD - float velocity_norm = sqrt(velocity_norm_sq); // # 1 SQRT - - sb_sq[i] = velocity_norm_sq * delta_t_sq; // # 1 MULT - sb_e_x[i] = e_x[i] * (velocity_norm * delta_t); // # 2 MULTs (vel_norm*delta_t shared with next line) - sb_e_y[i] = e_y[i] * (velocity_norm * delta_t); // # 1 MULT - -#if !BENCHMARK - if (dump_path && (t % dump_interval == 0)) { - samples.emplace_back(t + 1, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } -#endif - } - } - -#if !BENCHMARK - if (dump_path) { - ofstream out(dump_path); - out << "time,id,x,y,p.e.x,p.e.y,color\n"; - - for (auto &[t, id, x, y, e_x, e_y, c] : samples) { - out << t << ',' << id << ',' << x << ',' << y << ',' << e_x << ',' << e_y << ',' << c << '\n'; - } - } -#endif - - return 0; -} diff --git a/variants/variant_float_inlining_SoA_AVX512_polyexp.cpp b/variants/variant_float_inlining_SoA_AVX512_polyexp.cpp index 95dd277..bcbeeea 100644 --- a/variants/variant_float_inlining_SoA_AVX512_polyexp.cpp +++ b/variants/variant_float_inlining_SoA_AVX512_polyexp.cpp @@ -13,6 +13,8 @@ #define SEED 42 #define BOARD_WIDTH 10.0f #define BOARD_LENGTH 50.0f +#define BOARD_LENGTH_MINUS_ONE BOARD_LENGTH - 1.0f +#define BOARD_LENGTH_MINUS_ONE_POINT_FIVE BOARD_LENGTH - 1.5f #define WALL_EPS 1e-3f #define BOARD_WIDTH_MINUS_WALL_EPS 9.999f @@ -161,21 +163,46 @@ Pedestrian *init_pedestrians(int n_p) { Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } +// # 256 MULTs, 224 ADDs static inline __m512 _avx512_exp_ps(__m512 x) { + const __m512 log2e = _mm512_set1_ps(1.4426950408889634f); + + // # 16 MULTs __m512 nf = _mm512_roundscale_ps(_mm512_mul_ps(x, log2e), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); const __m512 ln2 = _mm512_set1_ps(0.6931471805599453f); + + // # 16 MULTs, 16 ADDs __m512 r = _mm512_fnmadd_ps(nf, ln2, x); - const __m512 c5 = _mm512_set1_ps(1.0f / 120.0f); - const __m512 c4 = _mm512_set1_ps(1.0f / 24.0f); - const __m512 c3 = _mm512_set1_ps(1.0f / 6.0f); - const __m512 c2 = _mm512_set1_ps(0.5f); - const __m512 c1 = _mm512_set1_ps(1.0f); - const __m512 c0 = _mm512_set1_ps(1.0f); + const __m512 c13 = _mm512_set1_ps(c13_scalar); + const __m512 c12 = _mm512_set1_ps(c12_scalar); + const __m512 c11 = _mm512_set1_ps(c11_scalar); + const __m512 c10 = _mm512_set1_ps(c10_scalar); + const __m512 c9 = _mm512_set1_ps(c9_scalar); + const __m512 c8 = _mm512_set1_ps(c8_scalar); + const __m512 c7 = _mm512_set1_ps(c7_scalar); + const __m512 c6 = _mm512_set1_ps(c6_scalar); + const __m512 c5 = _mm512_set1_ps(c5_scalar); + const __m512 c4 = _mm512_set1_ps(c4_scalar); + const __m512 c3 = _mm512_set1_ps(c3_scalar); + const __m512 c2 = _mm512_set1_ps(c2_scalar); + const __m512 c1 = _mm512_set1_ps(c1_scalar); + const __m512 c0 = _mm512_set1_ps(c0_scalar); - __m512 p = c5; + __m512 p = c13; + + // # 13 * (16 MULTs, 16 ADDs) + // # = 208 MULTs, 208 ADDs + p = _mm512_fmadd_ps(p, r, c12); + p = _mm512_fmadd_ps(p, r, c11); + p = _mm512_fmadd_ps(p, r, c10); + p = _mm512_fmadd_ps(p, r, c9); + p = _mm512_fmadd_ps(p, r, c8); + p = _mm512_fmadd_ps(p, r, c7); + p = _mm512_fmadd_ps(p, r, c6); + p = _mm512_fmadd_ps(p, r, c5); p = _mm512_fmadd_ps(p, r, c4); p = _mm512_fmadd_ps(p, r, c3); p = _mm512_fmadd_ps(p, r, c2); @@ -187,6 +214,7 @@ static inline __m512 _avx512_exp_ps(__m512 x) { __m512i scaled = _mm512_slli_epi32(biased, 23); __m512 pow2n = _mm512_castsi512_ps(scaled); + // # 16 MULTs return _mm512_mul_ps(p, pow2n); } @@ -225,11 +253,42 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c const __m512 v_np = _mm512_set1_ps((float)n_p); const __m512 v_exp_min = _mm512_set1_ps(-87.0f); + // # ADDs: n_iter * ( + // # n_p * 36 + + // # n_p * n_p_pad * 29 + + // # n_p * board.n_obstacles * 10 + + // # n_p * 7 + // # ) + + // # MULTs: n_iter * ( + // # n_p * 4 + + // # n_p * n_p_pad * 40 + + // # n_p * board.n_obstacles * 13 + + // # n_p * 17 + // # ) + + // # DIVs: n_iter * ( + // # n_p * n_p_pad + + // # n_p * board.n_obstacles + + // # n_p * 2 + // # ) + + // # SQRTs: n_iter * ( + // # n_p * n_p_pad * 3 + + // # n_p * board.n_obstacles + + // # n_p * 3 + // # ) + + // # EXPs: n_iter * n_p * board.n_obstacles + for (int t = 0; t < n_iter; t++) { for (int i = 0; i < n_p; i++) { + + // # 2 MULTs float desired_velocity_x = e_x[i] * desired_v0[i]; float desired_velocity_y = e_y[i] * desired_v0[i]; + // # 2 ADDs, 2 MULTs float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; @@ -243,6 +302,8 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 acc_y = _mm512_setzero_ps(); for (int j = 0; j < n_p_pad; j += 16) { + + // # 16 ADDs __m512 j_idx = _mm512_add_ps(_mm512_set1_ps((float)j), lane_off); __mmask16 m_neq_i = _mm512_cmp_ps_mask(j_idx, v_i, _CMP_NEQ_OQ); @@ -255,42 +316,76 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 sbe_jy = _mm512_loadu_ps(&sb_e_y[j]); __m512 sb_jsq = _mm512_loadu_ps(&sb_sq[j]); + // # 32 ADDs __m512 r_ab_x = _mm512_sub_ps(pix, pjx); __m512 r_ab_y = _mm512_sub_ps(piy, pjy); + + // # 32 MULTs, 16 ADDs __m512 r_ab_n2 = _mm512_fmadd_ps(r_ab_x, r_ab_x, _mm512_mul_ps(r_ab_y, r_ab_y)); + + // # 16 SQRTs __m512 r_ab_n = _mm512_sqrt_ps(r_ab_n2); + r_ab_n = _mm512_max_ps(r_ab_n, v_eps); + // # 32 ADDs __m512 r_ab2_x = _mm512_sub_ps(r_ab_x, sbe_jx); __m512 r_ab2_y = _mm512_sub_ps(r_ab_y, sbe_jy); + + // # 32 MULTs, 16 ADDs __m512 r_ab2_n2 = _mm512_fmadd_ps(r_ab2_x, r_ab2_x, _mm512_mul_ps(r_ab2_y, r_ab2_y)); + + // # 16 SQRTs __m512 r_ab2_n = _mm512_sqrt_ps(r_ab2_n2); + r_ab2_n = _mm512_max_ps(r_ab2_n, v_eps); + // # 16 ADDs __m512 r_sum = _mm512_add_ps(r_ab_n, r_ab2_n); + + // # 16 MULTs, 16 ADDs __m512 two_b_sq = _mm512_fmsub_ps(r_sum, r_sum, sb_jsq); + two_b_sq = _mm512_max_ps(two_b_sq, v_eps_sq); + + // # 16 SQRTs __m512 two_b = _mm512_sqrt_ps(two_b_sq); + // # 16 MULTs __m512 e_arg = _mm512_mul_ps(two_b, v_neg_2s_inv); + e_arg = _mm512_max_ps(e_arg, v_exp_min); + + // # 256 MULTs, 224 ADDs __m512 e_val = _avx512_exp_ps(e_arg); + // # 64 MULTs __m512 numer = _mm512_mul_ps(_mm512_mul_ps(r_sum, v_neg_v0_div_2s), e_val); __m512 denom = _mm512_mul_ps(_mm512_mul_ps(two_b, r_ab_n), r_ab2_n); __m512 denom_safe = _mm512_mask_blend_ps(active, v_one, denom); + + // # 16 DIVs __m512 smc = _mm512_div_ps(numer, denom_safe); + // # 32 MULTs __m512 sm_r_ab = _mm512_mul_ps(smc, r_ab2_n); __m512 sm_r_ab2 = _mm512_mul_ps(smc, r_ab_n); + // # 64 MULTs, 32 ADDs __m512 f_x = _mm512_fmadd_ps(r_ab2_x, sm_r_ab2, _mm512_mul_ps(r_ab_x, sm_r_ab)); __m512 f_y = _mm512_fmadd_ps(r_ab2_y, sm_r_ab2, _mm512_mul_ps(r_ab_y, sm_r_ab)); + // # 32 MULTs, 16 ADDs __m512 f_norm_sq = _mm512_fmadd_ps(f_x, f_x, _mm512_mul_ps(f_y, f_y)); + + // # 16 MULTs __m512 rhs = _mm512_mul_ps(f_norm_sq, v_cos_phi_sq); + + // # 32 MULTs, 16 ADDs __m512 e_dot_f = _mm512_fmadd_ps(eix, f_x, _mm512_mul_ps(eiy, f_y)); + + // # 16 MULTs __m512 e_dot_f_sq = _mm512_mul_ps(e_dot_f, e_dot_f); __mmask16 c1 = _mm512_cmp_ps_mask(e_dot_f, v_zero, _CMP_LT_OQ); @@ -302,19 +397,24 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 f_x_safe = _mm512_maskz_mov_ps(active, f_x); __m512 f_y_safe = _mm512_maskz_mov_ps(active, f_y); + // # 32 MULTs, 32 ADDs acc_x = _mm512_fmadd_ps(f_x_safe, w_val, acc_x); acc_y = _mm512_fmadd_ps(f_y_safe, w_val, acc_y); } + // # 32 ADDs f_alpha_dt_x += _mm512_reduce_add_ps(acc_x); f_alpha_dt_y += _mm512_reduce_add_ps(acc_y); for (int k = 0; k < board.n_obstacles; k++) { + + // # 2 ADDs float v1_x = pos_x[i] - board.obstacles[k].start_x; float v1_y = pos_y[i] - board.obstacles[k].start_y; float v2_x = board.obstacles[k].obstacle_v_x; float v2_y = board.obstacles[k].obstacle_v_y; + // # 3 MULTs, 1 ADD float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; if (projection < 0.0f) @@ -322,12 +422,15 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c else if (projection > 1.0f) projection = 1.0f; + // # 4 ADDs, 2 MULTs float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); + // # 1 SQRT, 2 MULTs, 1 ADD float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; + // # 4 MULTs, 1 EXP, 1 DIV float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; float f_alpha_B_neg_x = r_aB_x * scalar_mult; float f_alpha_B_neg_y = r_aB_y * scalar_mult; @@ -338,9 +441,11 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c if (e_dot_f < cos_phi) w_val = c_neg_times_dt; + // # 2 MULTS float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; + // # 2 ADDs f_alpha_dt_x += f_alpha_B_dt_x; f_alpha_dt_y += f_alpha_B_dt_y; } @@ -350,17 +455,24 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c } for (int i = 0; i < n_p; i++) { + + // # 1 SQRT, 2 MULTs, 1 ADD float w_norm = sqrt(w_x[i] * w_x[i] + w_y[i] * w_y[i]); + float w_norm2 = w_norm > EPS ? w_norm : EPS; + + // # 1 DIV float correction_factor = min(1.0f, v_max[i] / w_norm2); + // # 2 MULTs curr_vel_x[i] = w_x[i] * correction_factor; curr_vel_y[i] = w_y[i] * correction_factor; + // # 2 MULTs, 2 ADDs pos_x[i] = pos_x[i] + curr_vel_x[i] * dt; pos_y[i] = pos_y[i] + curr_vel_y[i] * dt; - if (color[i] == 0 && pos_x[i] > (BOARD_LENGTH - 1.5f)) { + if (color[i] == 0 && pos_x[i] > BOARD_LENGTH_MINUS_ONE_POINT_FIVE) { pos_x[i] = 1.0f; destination_y[i] = pos_y[i]; w_x[i] = desired_v0[i]; @@ -369,7 +481,7 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c curr_vel_y[i] = w_y[i]; } if (color[i] == 1 && pos_x[i] < 1.5f) { - pos_x[i] = BOARD_LENGTH - 1.0f; + pos_x[i] = BOARD_LENGTH_MINUS_ONE; destination_y[i] = pos_y[i]; w_x[i] = -desired_v0[i]; w_y[i] = 0.0f; @@ -379,19 +491,29 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c pos_y[i] = clamp(pos_y[i], WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); + // # 2 ADDs float ex = destination_x[i] - pos_x[i]; float ey = destination_y[i] - pos_y[i]; + // # 1 SQRT, 2 MULTs, 1 ADD float e_norm = sqrt(ex * ex + ey * ey); + float e_norm2 = e_norm > EPS ? e_norm : EPS; + + // # 1 DIV float e_norm_inv = 1.0f / e_norm2; + // # 2 MULTs e_x[i] = ex * e_norm_inv; e_y[i] = ey * e_norm_inv; + // # 2 MULTs, 1 ADD float velocity_norm_sq = curr_vel_x[i] * curr_vel_x[i] + curr_vel_y[i] * curr_vel_y[i]; + + // # 1 SQRT float velocity_norm = sqrt(velocity_norm_sq); + // # 5 MULTs sb_sq[i] = velocity_norm_sq * delta_t_sq; sb_e_x[i] = e_x[i] * (velocity_norm * delta_t); sb_e_y[i] = e_y[i] * (velocity_norm * delta_t); diff --git a/variants/variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt.cpp b/variants/variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt.cpp index 1e3dbb5..57d5811 100644 --- a/variants/variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt.cpp +++ b/variants/variant_float_inlining_SoA_AVX512_polyexp_fastinvsqrt.cpp @@ -13,6 +13,8 @@ #define SEED 42 #define BOARD_WIDTH 10.0f #define BOARD_LENGTH 50.0f +#define BOARD_LENGTH_MINUS_ONE BOARD_LENGTH - 1.0f +#define BOARD_LENGTH_MINUS_ONE_POINT_FIVE BOARD_LENGTH - 1.5f #define WALL_EPS 1e-3f #define BOARD_WIDTH_MINUS_WALL_EPS 9.999f @@ -161,21 +163,46 @@ Pedestrian *init_pedestrians(int n_p) { Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } +// # 256 MULTs, 224 ADDs static inline __m512 _avx512_exp_ps(__m512 x) { + const __m512 log2e = _mm512_set1_ps(1.4426950408889634f); + + // # 16 MULTs __m512 nf = _mm512_roundscale_ps(_mm512_mul_ps(x, log2e), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); const __m512 ln2 = _mm512_set1_ps(0.6931471805599453f); + + // # 16 MULTs, 16 ADDs __m512 r = _mm512_fnmadd_ps(nf, ln2, x); - const __m512 c5 = _mm512_set1_ps(1.0f / 120.0f); - const __m512 c4 = _mm512_set1_ps(1.0f / 24.0f); - const __m512 c3 = _mm512_set1_ps(1.0f / 6.0f); - const __m512 c2 = _mm512_set1_ps(0.5f); - const __m512 c1 = _mm512_set1_ps(1.0f); - const __m512 c0 = _mm512_set1_ps(1.0f); + const __m512 c13 = _mm512_set1_ps(c13_scalar); + const __m512 c12 = _mm512_set1_ps(c12_scalar); + const __m512 c11 = _mm512_set1_ps(c11_scalar); + const __m512 c10 = _mm512_set1_ps(c10_scalar); + const __m512 c9 = _mm512_set1_ps(c9_scalar); + const __m512 c8 = _mm512_set1_ps(c8_scalar); + const __m512 c7 = _mm512_set1_ps(c7_scalar); + const __m512 c6 = _mm512_set1_ps(c6_scalar); + const __m512 c5 = _mm512_set1_ps(c5_scalar); + const __m512 c4 = _mm512_set1_ps(c4_scalar); + const __m512 c3 = _mm512_set1_ps(c3_scalar); + const __m512 c2 = _mm512_set1_ps(c2_scalar); + const __m512 c1 = _mm512_set1_ps(c1_scalar); + const __m512 c0 = _mm512_set1_ps(c0_scalar); - __m512 p = c5; + __m512 p = c13; + + // # 13 * (16 MULTs, 16 ADDs) + // # = 208 MULTs, 208 ADDs + p = _mm512_fmadd_ps(p, r, c12); + p = _mm512_fmadd_ps(p, r, c11); + p = _mm512_fmadd_ps(p, r, c10); + p = _mm512_fmadd_ps(p, r, c9); + p = _mm512_fmadd_ps(p, r, c8); + p = _mm512_fmadd_ps(p, r, c7); + p = _mm512_fmadd_ps(p, r, c6); + p = _mm512_fmadd_ps(p, r, c5); p = _mm512_fmadd_ps(p, r, c4); p = _mm512_fmadd_ps(p, r, c3); p = _mm512_fmadd_ps(p, r, c2); @@ -187,9 +214,11 @@ static inline __m512 _avx512_exp_ps(__m512 x) { __m512i scaled = _mm512_slli_epi32(biased, 23); __m512 pow2n = _mm512_castsi512_ps(scaled); + // # 16 MULTs return _mm512_mul_ps(p, pow2n); } +// # 7 MULTs, 2 ADDs static inline float fast_inv_sqrt(float number) { float y = number; @@ -199,7 +228,10 @@ static inline float fast_inv_sqrt(float number) { y = bit_cast(i); + // # 1 MULT float x2 = number * 0.5; + + // # 6 MULTs, 2 ADDs y = y * (1.5 - (x2 * y * y)); y = y * (1.5 - (x2 * y * y)); @@ -241,11 +273,41 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c const __m512 v_np = _mm512_set1_ps((float)n_p); const __m512 v_exp_min = _mm512_set1_ps(-87.0f); + // # ADDs: n_iter * ( + // # n_p * 36 + + // # n_p * n_p_pad * 29 + + // # n_p * board.n_obstacles * 10 + + // # n_p * 11 + // # ) + + // # MULTs: n_iter * ( + // # n_p * 4 + + // # n_p * n_p_pad * 40 + + // # n_p * board.n_obstacles * 13 + + // # n_p * 30 + // # ) + + // # DIVs: n_iter * ( + // # n_p * n_p_pad + + // # n_p * board.n_obstacles + // # ) + + // # SQRTs: n_iter * ( + // # n_p * n_p_pad * 3 + + // # n_p * board.n_obstacles + + // # n_p + // # ) + + // # EXPs: n_iter * n_p * board.n_obstacles + for (int t = 0; t < n_iter; t++) { for (int i = 0; i < n_p; i++) { + + // # 2 MULTs float desired_velocity_x = e_x[i] * desired_v0[i]; float desired_velocity_y = e_y[i] * desired_v0[i]; + // # 2 ADDs, 2 MULTs float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; @@ -259,6 +321,8 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 acc_y = _mm512_setzero_ps(); for (int j = 0; j < n_p_pad; j += 16) { + + // # 16 ADDs __m512 j_idx = _mm512_add_ps(_mm512_set1_ps((float)j), lane_off); __mmask16 m_neq_i = _mm512_cmp_ps_mask(j_idx, v_i, _CMP_NEQ_OQ); @@ -271,42 +335,76 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 sbe_jy = _mm512_loadu_ps(&sb_e_y[j]); __m512 sb_jsq = _mm512_loadu_ps(&sb_sq[j]); + // # 32 ADDs __m512 r_ab_x = _mm512_sub_ps(pix, pjx); __m512 r_ab_y = _mm512_sub_ps(piy, pjy); + + // # 32 MULTs, 16 ADDs __m512 r_ab_n2 = _mm512_fmadd_ps(r_ab_x, r_ab_x, _mm512_mul_ps(r_ab_y, r_ab_y)); + + // # 16 SQRTs __m512 r_ab_n = _mm512_sqrt_ps(r_ab_n2); + r_ab_n = _mm512_max_ps(r_ab_n, v_eps); + // # 32 ADDs __m512 r_ab2_x = _mm512_sub_ps(r_ab_x, sbe_jx); __m512 r_ab2_y = _mm512_sub_ps(r_ab_y, sbe_jy); + + // # 32 MULTs, 16 ADDs __m512 r_ab2_n2 = _mm512_fmadd_ps(r_ab2_x, r_ab2_x, _mm512_mul_ps(r_ab2_y, r_ab2_y)); + + // # 16 SQRTs __m512 r_ab2_n = _mm512_sqrt_ps(r_ab2_n2); + r_ab2_n = _mm512_max_ps(r_ab2_n, v_eps); + // # 16 ADDs __m512 r_sum = _mm512_add_ps(r_ab_n, r_ab2_n); + + // # 16 MULTs, 16 ADDs __m512 two_b_sq = _mm512_fmsub_ps(r_sum, r_sum, sb_jsq); + two_b_sq = _mm512_max_ps(two_b_sq, v_eps_sq); + + // # 16 SQRTs __m512 two_b = _mm512_sqrt_ps(two_b_sq); + // # 16 MULTs __m512 e_arg = _mm512_mul_ps(two_b, v_neg_2s_inv); + e_arg = _mm512_max_ps(e_arg, v_exp_min); + + // # 256 MULTs, 224 ADDs __m512 e_val = _avx512_exp_ps(e_arg); + // # 64 MULTs __m512 numer = _mm512_mul_ps(_mm512_mul_ps(r_sum, v_neg_v0_div_2s), e_val); __m512 denom = _mm512_mul_ps(_mm512_mul_ps(two_b, r_ab_n), r_ab2_n); __m512 denom_safe = _mm512_mask_blend_ps(active, v_one, denom); + + // # 16 DIVs __m512 smc = _mm512_div_ps(numer, denom_safe); + // # 32 MULTs __m512 sm_r_ab = _mm512_mul_ps(smc, r_ab2_n); __m512 sm_r_ab2 = _mm512_mul_ps(smc, r_ab_n); + // # 64 MULTs, 32 ADDs __m512 f_x = _mm512_fmadd_ps(r_ab2_x, sm_r_ab2, _mm512_mul_ps(r_ab_x, sm_r_ab)); __m512 f_y = _mm512_fmadd_ps(r_ab2_y, sm_r_ab2, _mm512_mul_ps(r_ab_y, sm_r_ab)); + // # 32 MULTs, 16 ADDs __m512 f_norm_sq = _mm512_fmadd_ps(f_x, f_x, _mm512_mul_ps(f_y, f_y)); + + // # 16 MULTs __m512 rhs = _mm512_mul_ps(f_norm_sq, v_cos_phi_sq); + + // # 32 MULTs, 16 ADDs __m512 e_dot_f = _mm512_fmadd_ps(eix, f_x, _mm512_mul_ps(eiy, f_y)); + + // # 16 MULTs __m512 e_dot_f_sq = _mm512_mul_ps(e_dot_f, e_dot_f); __mmask16 c1 = _mm512_cmp_ps_mask(e_dot_f, v_zero, _CMP_LT_OQ); @@ -318,19 +416,24 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 f_x_safe = _mm512_maskz_mov_ps(active, f_x); __m512 f_y_safe = _mm512_maskz_mov_ps(active, f_y); + // # 32 MULTs, 32 ADDs acc_x = _mm512_fmadd_ps(f_x_safe, w_val, acc_x); acc_y = _mm512_fmadd_ps(f_y_safe, w_val, acc_y); } + // # 32 ADDs f_alpha_dt_x += _mm512_reduce_add_ps(acc_x); f_alpha_dt_y += _mm512_reduce_add_ps(acc_y); for (int k = 0; k < board.n_obstacles; k++) { + + // # 2 ADDs float v1_x = pos_x[i] - board.obstacles[k].start_x; float v1_y = pos_y[i] - board.obstacles[k].start_y; float v2_x = board.obstacles[k].obstacle_v_x; float v2_y = board.obstacles[k].obstacle_v_y; + // # 3 MULTs, 1 ADD float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; if (projection < 0.0f) @@ -338,12 +441,17 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c else if (projection > 1.0f) projection = 1.0f; + // # 4 ADDs, 2 MULTs float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); + // # 1 SQRT, 2 MULTs, 1 ADD float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); + // # 2 MULTs, 1 EXP, 1 DIV float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; + + // # 2 MULTs float f_alpha_B_neg_x = r_aB_x * scalar_mult; float f_alpha_B_neg_y = r_aB_y * scalar_mult; @@ -353,28 +461,36 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c if (e_dot_f < cos_phi) w_val = c_neg_times_dt; + // # 2 MULTs float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; + // # 2 ADDs f_alpha_dt_x += f_alpha_B_dt_x; f_alpha_dt_y += f_alpha_B_dt_y; } + // # 2 ADDs w_x[i] += f_alpha_dt_x; w_y[i] += f_alpha_dt_y; } for (int i = 0; i < n_p; i++) { + // # 9 MULTs, 3 ADDs float w_norm_inv = fast_inv_sqrt(w_x[i] * w_x[i] + w_y[i] * w_y[i]); + + // # 1 MULT float correction_factor = min(1.0f, v_max[i] * w_norm_inv); + // # 2 MULTs curr_vel_x[i] = w_x[i] * correction_factor; curr_vel_y[i] = w_y[i] * correction_factor; + // # 2 MULTs, 2 ADDs pos_x[i] = pos_x[i] + curr_vel_x[i] * dt; pos_y[i] = pos_y[i] + curr_vel_y[i] * dt; - if (color[i] == 0 && pos_x[i] > (BOARD_LENGTH - 1.5f)) { + if (color[i] == 0 && pos_x[i] > (BOARD_LENGTH_MINUS_ONE_POINT_FIVE)) { pos_x[i] = 1.0f; destination_y[i] = pos_y[i]; w_x[i] = desired_v0[i]; @@ -383,7 +499,7 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c curr_vel_y[i] = w_y[i]; } if (color[i] == 1 && pos_x[i] < 1.5f) { - pos_x[i] = BOARD_LENGTH - 1.0f; + pos_x[i] = BOARD_LENGTH_MINUS_ONE; destination_y[i] = pos_y[i]; w_x[i] = -desired_v0[i]; w_y[i] = 0.0f; @@ -393,19 +509,29 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c pos_y[i] = clamp(pos_y[i], WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); + // # 2 ADDs float ex = destination_x[i] - pos_x[i]; float ey = destination_y[i] - pos_y[i]; + // # 9 MULTs, 3 ADDs float e_norm_inv = fast_inv_sqrt(ex * ex + ey * ey); + // # 2 MULTs e_x[i] = ex * e_norm_inv; e_y[i] = ey * e_norm_inv; + // # 2 MULTs, 1 ADD double velocity_norm_sq = curr_vel_x[i] * curr_vel_x[i] + curr_vel_y[i] * curr_vel_y[i]; + + // # 1 MULT double sb_sq_i = velocity_norm_sq * delta_t_sq; + + // # 1 SQRT double velocity_norm_mul_delta_t = sqrt(sb_sq_i); sb_sq[i] = sb_sq_i; + + // # 2 MULTs sb_e_x[i] = e_x[i] * velocity_norm_mul_delta_t; sb_e_y[i] = e_y[i] * velocity_norm_mul_delta_t; diff --git a/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx.cpp b/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx.cpp index 15e0cbe..89d349d 100644 --- a/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx.cpp +++ b/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx.cpp @@ -13,6 +13,8 @@ #define SEED 42 #define BOARD_WIDTH 10.0f #define BOARD_LENGTH 50.0f +#define BOARD_LENGTH_MINUS_ONE BOARD_LENGTH - 1.0f +#define BOARD_LENGTH_MINUS_ONE_POINT_FIVE BOARD_LENGTH - 1.5f #define WALL_EPS 1e-3f #define BOARD_WIDTH_MINUS_WALL_EPS 9.999f @@ -161,21 +163,46 @@ Pedestrian *init_pedestrians(int n_p) { Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } +// # 256 MULTs, 224 ADDs static inline __m512 _avx512_exp_ps(__m512 x) { + const __m512 log2e = _mm512_set1_ps(1.4426950408889634f); + + // # 16 MULTs __m512 nf = _mm512_roundscale_ps(_mm512_mul_ps(x, log2e), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); const __m512 ln2 = _mm512_set1_ps(0.6931471805599453f); + + // # 16 MULTs, 16 ADDs __m512 r = _mm512_fnmadd_ps(nf, ln2, x); - const __m512 c5 = _mm512_set1_ps(1.0f / 120.0f); - const __m512 c4 = _mm512_set1_ps(1.0f / 24.0f); - const __m512 c3 = _mm512_set1_ps(1.0f / 6.0f); - const __m512 c2 = _mm512_set1_ps(0.5f); - const __m512 c1 = _mm512_set1_ps(1.0f); - const __m512 c0 = _mm512_set1_ps(1.0f); + const __m512 c13 = _mm512_set1_ps(c13_scalar); + const __m512 c12 = _mm512_set1_ps(c12_scalar); + const __m512 c11 = _mm512_set1_ps(c11_scalar); + const __m512 c10 = _mm512_set1_ps(c10_scalar); + const __m512 c9 = _mm512_set1_ps(c9_scalar); + const __m512 c8 = _mm512_set1_ps(c8_scalar); + const __m512 c7 = _mm512_set1_ps(c7_scalar); + const __m512 c6 = _mm512_set1_ps(c6_scalar); + const __m512 c5 = _mm512_set1_ps(c5_scalar); + const __m512 c4 = _mm512_set1_ps(c4_scalar); + const __m512 c3 = _mm512_set1_ps(c3_scalar); + const __m512 c2 = _mm512_set1_ps(c2_scalar); + const __m512 c1 = _mm512_set1_ps(c1_scalar); + const __m512 c0 = _mm512_set1_ps(c0_scalar); - __m512 p = c5; + __m512 p = c13; + + // # 13 * (16 MULTs, 16 ADDs) + // # = 208 MULTs, 208 ADDs + p = _mm512_fmadd_ps(p, r, c12); + p = _mm512_fmadd_ps(p, r, c11); + p = _mm512_fmadd_ps(p, r, c10); + p = _mm512_fmadd_ps(p, r, c9); + p = _mm512_fmadd_ps(p, r, c8); + p = _mm512_fmadd_ps(p, r, c7); + p = _mm512_fmadd_ps(p, r, c6); + p = _mm512_fmadd_ps(p, r, c5); p = _mm512_fmadd_ps(p, r, c4); p = _mm512_fmadd_ps(p, r, c3); p = _mm512_fmadd_ps(p, r, c2); @@ -187,6 +214,7 @@ static inline __m512 _avx512_exp_ps(__m512 x) { __m512i scaled = _mm512_slli_epi32(biased, 23); __m512 pow2n = _mm512_castsi512_ps(scaled); + // # 16 MULTs return _mm512_mul_ps(p, pow2n); } @@ -225,11 +253,42 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c const __m512 v_np = _mm512_set1_ps((float)n_p); const __m512 v_exp_min = _mm512_set1_ps(-87.0f); + // # ADDs: n_iter * ( + // # n_p * 36 + + // # n_p * n_p_pad * 29 + + // # n_p * board.n_obstacles * 10 + + // # n_p_pad * 7 + // # ) + + // # MULTs: n_iter * ( + // # n_p * 4 + + // # n_p * n_p_pad * 40 + + // # n_p * board.n_obstacles * 13 + + // # n_p_pad * 15 + // # ) + + // # DIVs: n_iter * ( + // # n_p * n_p_pad + + // # n_p * board.n_obstacles + + // # n_p_pad * 2 + // # ) + + // # SQRTs: n_iter * ( + // # n_p * n_p_pad * 3 + + // # n_p * board.n_obstacles + + // # n_p_pad * 3 + // # ) + + // # EXPs: n_iter * n_p * board.n_obstacles + for (int t = 0; t < n_iter; t++) { for (int i = 0; i < n_p; i++) { + + // # 2 MULTs float desired_velocity_x = e_x[i] * desired_v0[i]; float desired_velocity_y = e_y[i] * desired_v0[i]; + // # 2 ADDs, 2 MULTs float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; @@ -243,6 +302,8 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 acc_y = _mm512_setzero_ps(); for (int j = 0; j < n_p_pad; j += 16) { + + // # 16 ADDs __m512 j_idx = _mm512_add_ps(_mm512_set1_ps((float)j), lane_off); __mmask16 m_neq_i = _mm512_cmp_ps_mask(j_idx, v_i, _CMP_NEQ_OQ); @@ -255,42 +316,75 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 sbe_jy = _mm512_loadu_ps(&sb_e_y[j]); __m512 sb_jsq = _mm512_loadu_ps(&sb_sq[j]); + // # 32 ADDs __m512 r_ab_x = _mm512_sub_ps(pix, pjx); __m512 r_ab_y = _mm512_sub_ps(piy, pjy); + + // # 32 MULTs, 16 ADDs __m512 r_ab_n2 = _mm512_fmadd_ps(r_ab_x, r_ab_x, _mm512_mul_ps(r_ab_y, r_ab_y)); + + // # 16 SQRTs __m512 r_ab_n = _mm512_sqrt_ps(r_ab_n2); + r_ab_n = _mm512_max_ps(r_ab_n, v_eps); + // # 32 ADDs __m512 r_ab2_x = _mm512_sub_ps(r_ab_x, sbe_jx); __m512 r_ab2_y = _mm512_sub_ps(r_ab_y, sbe_jy); + + // # 32 MULTs, 16 ADDs __m512 r_ab2_n2 = _mm512_fmadd_ps(r_ab2_x, r_ab2_x, _mm512_mul_ps(r_ab2_y, r_ab2_y)); + + // # 16 SQRTs __m512 r_ab2_n = _mm512_sqrt_ps(r_ab2_n2); + r_ab2_n = _mm512_max_ps(r_ab2_n, v_eps); + // # 16 ADDs __m512 r_sum = _mm512_add_ps(r_ab_n, r_ab2_n); + + // # 16 MULTs, 16 ADDs __m512 two_b_sq = _mm512_fmsub_ps(r_sum, r_sum, sb_jsq); + two_b_sq = _mm512_max_ps(two_b_sq, v_eps_sq); + + // # 16 SQRTs __m512 two_b = _mm512_sqrt_ps(two_b_sq); + // # 16 MULTs __m512 e_arg = _mm512_mul_ps(two_b, v_neg_2s_inv); + e_arg = _mm512_max_ps(e_arg, v_exp_min); + + // # 256 MULTs, 224 ADDs __m512 e_val = _avx512_exp_ps(e_arg); + // # 64 MULTs __m512 numer = _mm512_mul_ps(_mm512_mul_ps(r_sum, v_neg_v0_div_2s), e_val); __m512 denom = _mm512_mul_ps(_mm512_mul_ps(two_b, r_ab_n), r_ab2_n); - __m512 denom_safe = _mm512_mask_blend_ps(active, v_one, denom); + + // # 16 DIVs __m512 smc = _mm512_div_ps(numer, denom_safe); + // # 32 MULTs __m512 sm_r_ab = _mm512_mul_ps(smc, r_ab2_n); __m512 sm_r_ab2 = _mm512_mul_ps(smc, r_ab_n); + // # 64 MULTs, 32 ADDs __m512 f_x = _mm512_fmadd_ps(r_ab2_x, sm_r_ab2, _mm512_mul_ps(r_ab_x, sm_r_ab)); __m512 f_y = _mm512_fmadd_ps(r_ab2_y, sm_r_ab2, _mm512_mul_ps(r_ab_y, sm_r_ab)); + // # 32 MULTs, 16 ADDs __m512 f_norm_sq = _mm512_fmadd_ps(f_x, f_x, _mm512_mul_ps(f_y, f_y)); + + // # 16 MULTs __m512 rhs = _mm512_mul_ps(f_norm_sq, v_cos_phi_sq); + + // # 32 MULTs, 16 ADDs __m512 e_dot_f = _mm512_fmadd_ps(eix, f_x, _mm512_mul_ps(eiy, f_y)); + + // # 16 MULTs __m512 e_dot_f_sq = _mm512_mul_ps(e_dot_f, e_dot_f); __mmask16 c1 = _mm512_cmp_ps_mask(e_dot_f, v_zero, _CMP_LT_OQ); @@ -302,19 +396,24 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 f_x_safe = _mm512_maskz_mov_ps(active, f_x); __m512 f_y_safe = _mm512_maskz_mov_ps(active, f_y); + // # 32 MULTs, 32 ADDs acc_x = _mm512_fmadd_ps(f_x_safe, w_val, acc_x); acc_y = _mm512_fmadd_ps(f_y_safe, w_val, acc_y); } + // # 32 ADDs f_alpha_dt_x += _mm512_reduce_add_ps(acc_x); f_alpha_dt_y += _mm512_reduce_add_ps(acc_y); for (int k = 0; k < board.n_obstacles; k++) { + + // # 2 ADDs float v1_x = pos_x[i] - board.obstacles[k].start_x; float v1_y = pos_y[i] - board.obstacles[k].start_y; float v2_x = board.obstacles[k].obstacle_v_x; float v2_y = board.obstacles[k].obstacle_v_y; + // # 3 MULTs, 1 ADD float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; if (projection < 0.0f) @@ -322,12 +421,15 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c else if (projection > 1.0f) projection = 1.0f; + // # 4 ADDs, 2 MULTs float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); + // # 1 SQRT, 2 MULTs, 1 ADD float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; + // # 4 MULTs, 1 EXP, 1 DIV float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; float f_alpha_B_neg_x = r_aB_x * scalar_mult; float f_alpha_B_neg_y = r_aB_y * scalar_mult; @@ -338,19 +440,22 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c if (e_dot_f < cos_phi) w_val = c_neg_times_dt; + // # 2 MULTS float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; + // # 2 ADDs f_alpha_dt_x += f_alpha_B_dt_x; f_alpha_dt_y += f_alpha_B_dt_y; } + // # 2 ADDs w_x[i] += f_alpha_dt_x; w_y[i] += f_alpha_dt_y; } for (int i = 0; i < n_p_pad; i += 16) { - + __m512 w_x_i_vec = _mm512_loadu_ps(&w_x[i]); __m512 w_y_i_vec = _mm512_loadu_ps(&w_y[i]); __m512 v_max_i_vec = _mm512_loadu_ps(&v_max[i]); @@ -359,23 +464,31 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 destination_y_i_vec = _mm512_loadu_ps(&destination_y[i]); __m512 destination_x_i_vec = _mm512_loadu_ps(&destination_x[i]); __m512 desired_v0_i_vec = _mm512_loadu_ps(&desired_v0[i]); - - __m512i color_i_vec = _mm512_loadu_si512((__m512i*)&color[i]); + __m512i color_i_vec = _mm512_loadu_si512((__m512i *)&color[i]); + + // # 32 MULTs, 16 ADDs __m512 w_norm_sq = _mm512_fmadd_ps(w_x_i_vec, w_x_i_vec, _mm512_mul_ps(w_y_i_vec, w_y_i_vec)); + + // # 16 SQRTs __m512 w_norm = _mm512_sqrt_ps(w_norm_sq); __m512 w_norm_safe = _mm512_max_ps(w_norm, _mm512_set1_ps(EPS)); + + // # 16 DIVs __m512 correction_factor = _mm512_min_ps(_mm512_set1_ps(1.0f), _mm512_div_ps(v_max_i_vec, w_norm_safe)); + // # 32 MULTs __m512 curr_vel_x_i_vec = _mm512_mul_ps(w_x_i_vec, correction_factor); __m512 curr_vel_y_i_vec = _mm512_mul_ps(w_y_i_vec, correction_factor); __m512 dt_vec = _mm512_set1_ps(dt); + + // # 32 MULTs, 32 ADDs pos_x_i_vec = _mm512_fmadd_ps(curr_vel_x_i_vec, dt_vec, pos_x_i_vec); pos_y_i_vec = _mm512_fmadd_ps(curr_vel_y_i_vec, dt_vec, pos_y_i_vec); __mmask16 cond_1_left = _mm512_cmpeq_epi32_mask(color_i_vec, _mm512_setzero_si512()); - __mmask16 cond_1_right = _mm512_cmp_ps_mask(pos_x_i_vec, _mm512_set1_ps(BOARD_LENGTH - 1.5f), _CMP_GT_OQ); + __mmask16 cond_1_right = _mm512_cmp_ps_mask(pos_x_i_vec, _mm512_set1_ps(BOARD_LENGTH_MINUS_ONE_POINT_FIVE), _CMP_GT_OQ); __mmask16 cond_1 = cond_1_left & cond_1_right; pos_x_i_vec = _mm512_mask_blend_ps(cond_1, pos_x_i_vec, _mm512_set1_ps(1.0f)); @@ -389,7 +502,7 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __mmask16 cond_2_right = _mm512_cmp_ps_mask(pos_x_i_vec, _mm512_set1_ps(1.5f), _CMP_LT_OQ); __mmask16 cond_2 = cond_2_left & cond_2_right; - pos_x_i_vec = _mm512_mask_blend_ps(cond_2, pos_x_i_vec, _mm512_set1_ps(BOARD_LENGTH - 1.0f)); + pos_x_i_vec = _mm512_mask_blend_ps(cond_2, pos_x_i_vec, _mm512_set1_ps(BOARD_LENGTH_MINUS_ONE)); destination_y_i_vec = _mm512_mask_blend_ps(cond_2, destination_y_i_vec, pos_y_i_vec); __m512 neg_desired_v0 = _mm512_xor_ps(desired_v0_i_vec, _mm512_set1_ps(-0.0f)); w_x_i_vec = _mm512_mask_blend_ps(cond_2, w_x_i_vec, neg_desired_v0); @@ -400,16 +513,30 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c pos_y_i_vec = _mm512_max_ps(pos_y_i_vec, _mm512_set1_ps(WALL_EPS)); pos_y_i_vec = _mm512_min_ps(pos_y_i_vec, _mm512_set1_ps(BOARD_WIDTH_MINUS_WALL_EPS)); + // # 32 ADDs __m512 ex_vec = _mm512_sub_ps(destination_x_i_vec, pos_x_i_vec); __m512 ey_vec = _mm512_sub_ps(destination_y_i_vec, pos_y_i_vec); + + // # 32 MULTs, 16 ADDs __m512 e_norm_sq = _mm512_fmadd_ps(ex_vec, ex_vec, _mm512_mul_ps(ey_vec, ey_vec)); + + // # 16 SQRTs __m512 e_norm = _mm512_sqrt_ps(e_norm_sq); + + // # 16 DIVs __m512 e_norm_inv = _mm512_div_ps(_mm512_set1_ps(1.0f), e_norm); + + // # 32 MULTs __m512 e_x_i_vec = _mm512_mul_ps(ex_vec, e_norm_inv); __m512 e_y_i_vec = _mm512_mul_ps(ey_vec, e_norm_inv); + // # 32 MULTs, 16 ADDs __m512 vel_norm_sq = _mm512_fmadd_ps(curr_vel_x_i_vec, curr_vel_x_i_vec, _mm512_mul_ps(curr_vel_y_i_vec, curr_vel_y_i_vec)); + + // # 16 MULTs __m512 sb_sq_i_vec = _mm512_mul_ps(vel_norm_sq, _mm512_set1_ps(delta_t_sq)); + + // # 16 SQRTs __m512 vel_norm_dt = _mm512_sqrt_ps(sb_sq_i_vec); _mm512_storeu_ps(&curr_vel_x[i], curr_vel_x_i_vec); @@ -422,6 +549,8 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c _mm512_storeu_ps(&e_y[i], e_y_i_vec); _mm512_storeu_ps(&destination_y[i], destination_y_i_vec); _mm512_storeu_ps(&sb_sq[i], sb_sq_i_vec); + + // # 32 MULTs _mm512_storeu_ps(&sb_e_x[i], _mm512_mul_ps(e_x_i_vec, vel_norm_dt)); _mm512_storeu_ps(&sb_e_y[i], _mm512_mul_ps(e_y_i_vec, vel_norm_dt)); } diff --git a/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2.cpp b/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2.cpp index 83d3c57..3bcba7a 100644 --- a/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2.cpp +++ b/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2.cpp @@ -13,6 +13,8 @@ #define SEED 42 #define BOARD_WIDTH 10.0f #define BOARD_LENGTH 50.0f +#define BOARD_LENGTH_MINUS_ONE BOARD_LENGTH - 1.0f +#define BOARD_LENGTH_MINUS_ONE_POINT_FIVE BOARD_LENGTH - 1.5f #define WALL_EPS 1e-3f #define BOARD_WIDTH_MINUS_WALL_EPS 9.999f @@ -160,21 +162,46 @@ Pedestrian *init_pedestrians(int n_p) { Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } +// # 256 MULTs, 224 ADDs static inline __m512 _avx512_exp_ps(__m512 x) { + const __m512 log2e = _mm512_set1_ps(1.4426950408889634f); + + // # 16 MULTs __m512 nf = _mm512_roundscale_ps(_mm512_mul_ps(x, log2e), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); const __m512 ln2 = _mm512_set1_ps(0.6931471805599453f); + + // # 16 MULTs, 16 ADDs __m512 r = _mm512_fnmadd_ps(nf, ln2, x); - const __m512 c5 = _mm512_set1_ps(1.0f / 120.0f); - const __m512 c4 = _mm512_set1_ps(1.0f / 24.0f); - const __m512 c3 = _mm512_set1_ps(1.0f / 6.0f); - const __m512 c2 = _mm512_set1_ps(0.5f); - const __m512 c1 = _mm512_set1_ps(1.0f); - const __m512 c0 = _mm512_set1_ps(1.0f); + const __m512 c13 = _mm512_set1_ps(c13_scalar); + const __m512 c12 = _mm512_set1_ps(c12_scalar); + const __m512 c11 = _mm512_set1_ps(c11_scalar); + const __m512 c10 = _mm512_set1_ps(c10_scalar); + const __m512 c9 = _mm512_set1_ps(c9_scalar); + const __m512 c8 = _mm512_set1_ps(c8_scalar); + const __m512 c7 = _mm512_set1_ps(c7_scalar); + const __m512 c6 = _mm512_set1_ps(c6_scalar); + const __m512 c5 = _mm512_set1_ps(c5_scalar); + const __m512 c4 = _mm512_set1_ps(c4_scalar); + const __m512 c3 = _mm512_set1_ps(c3_scalar); + const __m512 c2 = _mm512_set1_ps(c2_scalar); + const __m512 c1 = _mm512_set1_ps(c1_scalar); + const __m512 c0 = _mm512_set1_ps(c0_scalar); - __m512 p = c5; + __m512 p = c13; + + // # 13 * (16 MULTs, 16 ADDs) + // # = 208 MULTs, 208 ADDs + p = _mm512_fmadd_ps(p, r, c12); + p = _mm512_fmadd_ps(p, r, c11); + p = _mm512_fmadd_ps(p, r, c10); + p = _mm512_fmadd_ps(p, r, c9); + p = _mm512_fmadd_ps(p, r, c8); + p = _mm512_fmadd_ps(p, r, c7); + p = _mm512_fmadd_ps(p, r, c6); + p = _mm512_fmadd_ps(p, r, c5); p = _mm512_fmadd_ps(p, r, c4); p = _mm512_fmadd_ps(p, r, c3); p = _mm512_fmadd_ps(p, r, c2); @@ -186,6 +213,7 @@ static inline __m512 _avx512_exp_ps(__m512 x) { __m512i scaled = _mm512_slli_epi32(biased, 23); __m512 pow2n = _mm512_castsi512_ps(scaled); + // # 16 MULTs return _mm512_mul_ps(p, pow2n); } @@ -224,11 +252,42 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c const __m512 v_np = _mm512_set1_ps((float)n_p); const __m512 v_exp_min = _mm512_set1_ps(-87.0f); + // # ADDs: n_iter * ( + // # n_p * 68 + + // # n_p * n_p_pad * 29 + + // # n_p * board.n_obstacles * 10 + + // # n_p_pad * 7 + // # ) + + // # MULTs: n_iter * ( + // # n_p * 4 + + // # n_p * n_p_pad * 40 + + // # n_p * board.n_obstacles * 13 + + // # n_p_pad * 15 + // # ) + + // # SQRTs: n_iter * ( + // # n_p * n_p_pad * 3 + + // # n_p * board.n_obstacles + + // # n_p_pad * 3 + // # ) + + // # DIVs: n_iter * ( + // # n_p * n_p_pad + + // # n_p * board.n_obstacles + + // # n_p_pad * 2 + // # ) + + // # EXPs: n_iter * n_p * board.n_obstacles + for (int t = 0; t < n_iter; t++) { for (int i = 0; i < n_p; i++) { + + // # 2 MULTs float desired_velocity_x = e_x[i] * desired_v0[i]; float desired_velocity_y = e_y[i] * desired_v0[i]; + // # 2 ADDs, 2 MULTs float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; @@ -244,6 +303,8 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 acc_y_1 = _mm512_setzero_ps(); for (int j = 0; j < n_p_pad; j += 32) { + + // # 32 ADDs __m512 j_idx_0 = _mm512_add_ps(_mm512_set1_ps((float)j), lane_off); __m512 j_idx_1 = _mm512_add_ps(_mm512_set1_ps((float)j + 16), lane_off); @@ -259,11 +320,9 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 pjx_0 = _mm512_loadu_ps(&pos_x[j]); __m512 pjx_1 = _mm512_loadu_ps(&pos_x[j + 16]); - __m512 pjy_0 = _mm512_loadu_ps(&pos_y[j]); __m512 pjy_1 = _mm512_loadu_ps(&pos_y[j + 16]); - __m512 sbe_jx_0 = _mm512_loadu_ps(&sb_e_x[j]); __m512 sbe_jx_1 = _mm512_loadu_ps(&sb_e_x[j + 16]); @@ -273,81 +332,105 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 sb_jsq_0 = _mm512_loadu_ps(&sb_sq[j]); __m512 sb_jsq_1 = _mm512_loadu_ps(&sb_sq[j + 16]); + // # 32 ADDs __m512 r_ab_x_0 = _mm512_sub_ps(pix, pjx_0); __m512 r_ab_x_1 = _mm512_sub_ps(pix, pjx_1); + // # 32 ADDs __m512 r_ab_y_0 = _mm512_sub_ps(piy, pjy_0); __m512 r_ab_y_1 = _mm512_sub_ps(piy, pjy_1); + // # 64 MULTs, 32 ADDs __m512 r_ab_n2_0 = _mm512_fmadd_ps(r_ab_x_0, r_ab_x_0, _mm512_mul_ps(r_ab_y_0, r_ab_y_0)); __m512 r_ab_n2_1 = _mm512_fmadd_ps(r_ab_x_1, r_ab_x_1, _mm512_mul_ps(r_ab_y_1, r_ab_y_1)); + // # 32 SQRTs __m512 r_ab_n_0 = _mm512_sqrt_ps(r_ab_n2_0); __m512 r_ab_n_1 = _mm512_sqrt_ps(r_ab_n2_1); + // # 32 ADDs __m512 r_ab2_x_0 = _mm512_sub_ps(r_ab_x_0, sbe_jx_0); __m512 r_ab2_x_1 = _mm512_sub_ps(r_ab_x_1, sbe_jx_1); + // # 32 ADDs __m512 r_ab2_y_0 = _mm512_sub_ps(r_ab_y_0, sbe_jy_0); __m512 r_ab2_y_1 = _mm512_sub_ps(r_ab_y_1, sbe_jy_1); + // # 64 MULTs, 32 ADDs __m512 r_ab2_n2_0 = _mm512_fmadd_ps(r_ab2_x_0, r_ab2_x_0, _mm512_mul_ps(r_ab2_y_0, r_ab2_y_0)); __m512 r_ab2_n2_1 = _mm512_fmadd_ps(r_ab2_x_1, r_ab2_x_1, _mm512_mul_ps(r_ab2_y_1, r_ab2_y_1)); + // # 32 SQRTs __m512 r_ab2_n_0 = _mm512_sqrt_ps(r_ab2_n2_0); __m512 r_ab2_n_1 = _mm512_sqrt_ps(r_ab2_n2_1); + // # 32 ADDs __m512 r_sum_0 = _mm512_add_ps(r_ab_n_0, r_ab2_n_0); __m512 r_sum_1 = _mm512_add_ps(r_ab_n_1, r_ab2_n_1); + // # 32 MULTs, 32 ADDs __m512 two_b_sq_0 = _mm512_fmsub_ps(r_sum_0, r_sum_0, sb_jsq_0); __m512 two_b_sq_1 = _mm512_fmsub_ps(r_sum_1, r_sum_1, sb_jsq_1); + // # 32 SQRTs __m512 two_b_0 = _mm512_sqrt_ps(two_b_sq_0); __m512 two_b_1 = _mm512_sqrt_ps(two_b_sq_1); + // # 32 MULTs __m512 e_arg_0 = _mm512_mul_ps(two_b_0, v_neg_2s_inv); __m512 e_arg_1 = _mm512_mul_ps(two_b_1, v_neg_2s_inv); e_arg_0 = _mm512_max_ps(e_arg_0, v_exp_min); e_arg_1 = _mm512_max_ps(e_arg_1, v_exp_min); + // # 512 MULTs, 448 ADDs __m512 e_val_0 = _avx512_exp_ps(e_arg_0); __m512 e_val_1 = _avx512_exp_ps(e_arg_1); + // # 64 MULTs __m512 numer_0 = _mm512_mul_ps(_mm512_mul_ps(r_sum_0, v_neg_v0_div_2s), e_val_0); __m512 numer_1 = _mm512_mul_ps(_mm512_mul_ps(r_sum_1, v_neg_v0_div_2s), e_val_1); + // # 64 MULTs __m512 denom_0 = _mm512_mul_ps(_mm512_mul_ps(two_b_0, r_ab_n_0), r_ab2_n_0); __m512 denom_1 = _mm512_mul_ps(_mm512_mul_ps(two_b_1, r_ab_n_1), r_ab2_n_1); __m512 denom_safe_0 = _mm512_mask_blend_ps(active_0, v_one, denom_0); __m512 denom_safe_1 = _mm512_mask_blend_ps(active_1, v_one, denom_1); + // # 32 DIVs __m512 smc_0 = _mm512_div_ps(numer_0, denom_safe_0); __m512 smc_1 = _mm512_div_ps(numer_1, denom_safe_1); + // # 32 MULTs __m512 sm_r_ab_0 = _mm512_mul_ps(smc_0, r_ab2_n_0); __m512 sm_r_ab_1 = _mm512_mul_ps(smc_1, r_ab2_n_1); + // # 32 MULTs __m512 sm_r_ab2_0 = _mm512_mul_ps(smc_0, r_ab_n_0); __m512 sm_r_ab2_1 = _mm512_mul_ps(smc_1, r_ab_n_1); + // # 64 MULTs, 32 ADDs __m512 f_x_0 = _mm512_fmadd_ps(r_ab2_x_0, sm_r_ab2_0, _mm512_mul_ps(r_ab_x_0, sm_r_ab_0)); __m512 f_x_1 = _mm512_fmadd_ps(r_ab2_x_1, sm_r_ab2_1, _mm512_mul_ps(r_ab_x_1, sm_r_ab_1)); + // # 64 MULTs, 32 ADDs __m512 f_y_0 = _mm512_fmadd_ps(r_ab2_y_0, sm_r_ab2_0, _mm512_mul_ps(r_ab_y_0, sm_r_ab_0)); __m512 f_y_1 = _mm512_fmadd_ps(r_ab2_y_1, sm_r_ab2_1, _mm512_mul_ps(r_ab_y_1, sm_r_ab_1)); + // # 64 MULTs, 32 ADDs __m512 f_norm_sq_0 = _mm512_fmadd_ps(f_x_0, f_x_0, _mm512_mul_ps(f_y_0, f_y_0)); __m512 f_norm_sq_1 = _mm512_fmadd_ps(f_x_1, f_x_1, _mm512_mul_ps(f_y_1, f_y_1)); + // # 32 MULTs __m512 rhs_0 = _mm512_mul_ps(f_norm_sq_0, v_cos_phi_sq); __m512 rhs_1 = _mm512_mul_ps(f_norm_sq_1, v_cos_phi_sq); + // # 64 MULTs, 32 ADDs __m512 e_dot_f_0 = _mm512_fmadd_ps(eix, f_x_0, _mm512_mul_ps(eiy, f_y_0)); __m512 e_dot_f_1 = _mm512_fmadd_ps(eix, f_x_1, _mm512_mul_ps(eiy, f_y_1)); + // # 32 MULTs __m512 e_dot_f_sq_0 = _mm512_mul_ps(e_dot_f_0, e_dot_f_0); __m512 e_dot_f_sq_1 = _mm512_mul_ps(e_dot_f_1, e_dot_f_1); @@ -369,22 +452,28 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 f_y_safe_0 = _mm512_maskz_mov_ps(active_0, f_y_0); __m512 f_y_safe_1 = _mm512_maskz_mov_ps(active_1, f_y_1); + // # 32 MULTs, 32 ADDs acc_x_0 = _mm512_fmadd_ps(f_x_safe_0, w_val_0, acc_x_0); acc_x_1 = _mm512_fmadd_ps(f_x_safe_1, w_val_1, acc_x_1); + // # 32 MULTs, 32 ADDs acc_y_0 = _mm512_fmadd_ps(f_y_safe_0, w_val_0, acc_y_0); acc_y_1 = _mm512_fmadd_ps(f_y_safe_1, w_val_1, acc_y_1); } + // # 64 ADDs f_alpha_dt_x += _mm512_reduce_add_ps(_mm512_add_ps(acc_x_0, acc_x_1)); f_alpha_dt_y += _mm512_reduce_add_ps(_mm512_add_ps(acc_y_0, acc_y_1)); for (int k = 0; k < board.n_obstacles; k++) { + + // # 2 ADDs float v1_x = pos_x[i] - board.obstacles[k].start_x; float v1_y = pos_y[i] - board.obstacles[k].start_y; float v2_x = board.obstacles[k].obstacle_v_x; float v2_y = board.obstacles[k].obstacle_v_y; + // # 3 MULTs, 1 ADD float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; if (projection < 0.0f) @@ -392,12 +481,15 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c else if (projection > 1.0f) projection = 1.0f; + // # 4 ADDs, 2 MULTs float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); + // # 1 SQRT, 2 MULTs, 1 ADD float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; + // # 1 EXP, 4 MULTs, 1 DIV float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; float f_alpha_B_neg_x = r_aB_x * scalar_mult; float f_alpha_B_neg_y = r_aB_y * scalar_mult; @@ -408,19 +500,22 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c if (e_dot_f < cos_phi) w_val = c_neg_times_dt; + // # 2 MULTs float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; + // # 2 ADDs f_alpha_dt_x += f_alpha_B_dt_x; f_alpha_dt_y += f_alpha_B_dt_y; } + // # 2 ADDs w_x[i] += f_alpha_dt_x; w_y[i] += f_alpha_dt_y; } for (int i = 0; i < n_p_pad; i += 16) { - + __m512 w_x_i_vec = _mm512_loadu_ps(&w_x[i]); __m512 w_y_i_vec = _mm512_loadu_ps(&w_y[i]); __m512 v_max_i_vec = _mm512_loadu_ps(&v_max[i]); @@ -429,22 +524,30 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 destination_y_i_vec = _mm512_loadu_ps(&destination_y[i]); __m512 destination_x_i_vec = _mm512_loadu_ps(&destination_x[i]); __m512 desired_v0_i_vec = _mm512_loadu_ps(&desired_v0[i]); - - __m512i color_i_vec = _mm512_loadu_si512((__m512i*)&color[i]); + __m512i color_i_vec = _mm512_loadu_si512((__m512i *)&color[i]); + + // # 32 MULTs, 16 ADDs __m512 w_norm_sq = _mm512_fmadd_ps(w_x_i_vec, w_x_i_vec, _mm512_mul_ps(w_y_i_vec, w_y_i_vec)); + + // # 16 SQRTs __m512 w_norm = _mm512_sqrt_ps(w_norm_sq); + + // # 16 DIVs __m512 correction_factor = _mm512_min_ps(_mm512_set1_ps(1.0f), _mm512_div_ps(v_max_i_vec, w_norm)); + // # 32 MULTs __m512 curr_vel_x_i_vec = _mm512_mul_ps(w_x_i_vec, correction_factor); __m512 curr_vel_y_i_vec = _mm512_mul_ps(w_y_i_vec, correction_factor); __m512 dt_vec = _mm512_set1_ps(dt); + + // # 32 MULTs, 32 ADDs pos_x_i_vec = _mm512_fmadd_ps(curr_vel_x_i_vec, dt_vec, pos_x_i_vec); pos_y_i_vec = _mm512_fmadd_ps(curr_vel_y_i_vec, dt_vec, pos_y_i_vec); __mmask16 cond_1_left = _mm512_cmpeq_epi32_mask(color_i_vec, _mm512_setzero_si512()); - __mmask16 cond_1_right = _mm512_cmp_ps_mask(pos_x_i_vec, _mm512_set1_ps(BOARD_LENGTH - 1.5f), _CMP_GT_OQ); + __mmask16 cond_1_right = _mm512_cmp_ps_mask(pos_x_i_vec, _mm512_set1_ps(BOARD_LENGTH_MINUS_ONE_POINT_FIVE), _CMP_GT_OQ); __mmask16 cond_1 = cond_1_left & cond_1_right; pos_x_i_vec = _mm512_mask_blend_ps(cond_1, pos_x_i_vec, _mm512_set1_ps(1.0f)); @@ -458,7 +561,7 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __mmask16 cond_2_right = _mm512_cmp_ps_mask(pos_x_i_vec, _mm512_set1_ps(1.5f), _CMP_LT_OQ); __mmask16 cond_2 = cond_2_left & cond_2_right; - pos_x_i_vec = _mm512_mask_blend_ps(cond_2, pos_x_i_vec, _mm512_set1_ps(BOARD_LENGTH - 1.0f)); + pos_x_i_vec = _mm512_mask_blend_ps(cond_2, pos_x_i_vec, _mm512_set1_ps(BOARD_LENGTH_MINUS_ONE)); destination_y_i_vec = _mm512_mask_blend_ps(cond_2, destination_y_i_vec, pos_y_i_vec); __m512 neg_desired_v0 = _mm512_xor_ps(desired_v0_i_vec, _mm512_set1_ps(-0.0f)); w_x_i_vec = _mm512_mask_blend_ps(cond_2, w_x_i_vec, neg_desired_v0); @@ -469,16 +572,30 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c pos_y_i_vec = _mm512_max_ps(pos_y_i_vec, _mm512_set1_ps(WALL_EPS)); pos_y_i_vec = _mm512_min_ps(pos_y_i_vec, _mm512_set1_ps(BOARD_WIDTH_MINUS_WALL_EPS)); + // # 32 ADDs __m512 ex_vec = _mm512_sub_ps(destination_x_i_vec, pos_x_i_vec); __m512 ey_vec = _mm512_sub_ps(destination_y_i_vec, pos_y_i_vec); + + // # 32 MULTs, 16 ADDs __m512 e_norm_sq = _mm512_fmadd_ps(ex_vec, ex_vec, _mm512_mul_ps(ey_vec, ey_vec)); + + // # 16 SQRTs __m512 e_norm = _mm512_sqrt_ps(e_norm_sq); + + // # 16 DIVs __m512 e_norm_inv = _mm512_div_ps(_mm512_set1_ps(1.0f), e_norm); + + // # 32 MULTs __m512 e_x_i_vec = _mm512_mul_ps(ex_vec, e_norm_inv); __m512 e_y_i_vec = _mm512_mul_ps(ey_vec, e_norm_inv); + // # 32 MULTs, 16 ADDs __m512 vel_norm_sq = _mm512_fmadd_ps(curr_vel_x_i_vec, curr_vel_x_i_vec, _mm512_mul_ps(curr_vel_y_i_vec, curr_vel_y_i_vec)); + + // # 16 MULTs __m512 sb_sq_i_vec = _mm512_mul_ps(vel_norm_sq, _mm512_set1_ps(delta_t_sq)); + + // # 16 SQRTs __m512 vel_norm_dt = _mm512_sqrt_ps(sb_sq_i_vec); _mm512_storeu_ps(&curr_vel_x[i], curr_vel_x_i_vec); @@ -491,11 +608,12 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c _mm512_storeu_ps(&e_y[i], e_y_i_vec); _mm512_storeu_ps(&destination_y[i], destination_y_i_vec); _mm512_storeu_ps(&sb_sq[i], sb_sq_i_vec); + + // # 32 MULTs _mm512_storeu_ps(&sb_e_x[i], _mm512_mul_ps(e_x_i_vec, vel_norm_dt)); _mm512_storeu_ps(&sb_e_y[i], _mm512_mul_ps(e_y_i_vec, vel_norm_dt)); } - #if !BENCHMARK for (int i = 0; i < n_p; i++) { if (dump_path && (t % dump_interval == 0)) { diff --git a/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp.cpp b/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp.cpp index 80d9b8f..25a468c 100644 --- a/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp.cpp +++ b/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_moreilp.cpp @@ -13,6 +13,8 @@ #define SEED 42 #define BOARD_WIDTH 10.0f #define BOARD_LENGTH 50.0f +#define BOARD_LENGTH_MINUS_ONE BOARD_LENGTH - 1.0f +#define BOARD_LENGTH_MINUS_ONE_POINT_FIVE BOARD_LENGTH - 1.5f #define WALL_EPS 1e-3f #define BOARD_WIDTH_MINUS_WALL_EPS 9.999f @@ -160,21 +162,46 @@ Pedestrian *init_pedestrians(int n_p) { Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } +// # 256 MULTs, 224 ADDs static inline __m512 _avx512_exp_ps(__m512 x) { + const __m512 log2e = _mm512_set1_ps(1.4426950408889634f); + + // # 16 MULTs __m512 nf = _mm512_roundscale_ps(_mm512_mul_ps(x, log2e), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); const __m512 ln2 = _mm512_set1_ps(0.6931471805599453f); + + // # 16 MULTs, 16 ADDs __m512 r = _mm512_fnmadd_ps(nf, ln2, x); - const __m512 c5 = _mm512_set1_ps(1.0f / 120.0f); - const __m512 c4 = _mm512_set1_ps(1.0f / 24.0f); - const __m512 c3 = _mm512_set1_ps(1.0f / 6.0f); - const __m512 c2 = _mm512_set1_ps(0.5f); - const __m512 c1 = _mm512_set1_ps(1.0f); - const __m512 c0 = _mm512_set1_ps(1.0f); + const __m512 c13 = _mm512_set1_ps(c13_scalar); + const __m512 c12 = _mm512_set1_ps(c12_scalar); + const __m512 c11 = _mm512_set1_ps(c11_scalar); + const __m512 c10 = _mm512_set1_ps(c10_scalar); + const __m512 c9 = _mm512_set1_ps(c9_scalar); + const __m512 c8 = _mm512_set1_ps(c8_scalar); + const __m512 c7 = _mm512_set1_ps(c7_scalar); + const __m512 c6 = _mm512_set1_ps(c6_scalar); + const __m512 c5 = _mm512_set1_ps(c5_scalar); + const __m512 c4 = _mm512_set1_ps(c4_scalar); + const __m512 c3 = _mm512_set1_ps(c3_scalar); + const __m512 c2 = _mm512_set1_ps(c2_scalar); + const __m512 c1 = _mm512_set1_ps(c1_scalar); + const __m512 c0 = _mm512_set1_ps(c0_scalar); - __m512 p = c5; + __m512 p = c13; + + // # 13 * (16 MULTs, 16 ADDs) + // # = 208 MULTs, 208 ADDs + p = _mm512_fmadd_ps(p, r, c12); + p = _mm512_fmadd_ps(p, r, c11); + p = _mm512_fmadd_ps(p, r, c10); + p = _mm512_fmadd_ps(p, r, c9); + p = _mm512_fmadd_ps(p, r, c8); + p = _mm512_fmadd_ps(p, r, c7); + p = _mm512_fmadd_ps(p, r, c6); + p = _mm512_fmadd_ps(p, r, c5); p = _mm512_fmadd_ps(p, r, c4); p = _mm512_fmadd_ps(p, r, c3); p = _mm512_fmadd_ps(p, r, c2); @@ -186,6 +213,7 @@ static inline __m512 _avx512_exp_ps(__m512 x) { __m512i scaled = _mm512_slli_epi32(biased, 23); __m512 pow2n = _mm512_castsi512_ps(scaled); + // # 16 MULTs return _mm512_mul_ps(p, pow2n); } @@ -224,11 +252,42 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c const __m512 v_np = _mm512_set1_ps((float)n_p); const __m512 v_exp_min = _mm512_set1_ps(-87.0f); + // # ADDs: n_iter * ( + // # n_p * 68 + + // # n_p * n_p_pad * 29 + + // # n_p * board.n_obstacles * 10 + + // # n_p_pad * 7 + // # ) + + // # MULTs: n_iter * ( + // # n_p * 4 + + // # n_p * n_p_pad * 40 + + // # n_p * board.n_obstacles * 13 + + // # n_p_pad * 15 + // # ) + + // # DIVs: n_iter * ( + // # n_p * n_p_pad + + // # n_p * board.n_obstacles + + // # n_p_pad * 2 + // # ) + + // # SQRTs: n_iter * ( + // # n_p * n_p_pad * 3 + + // # n_p * board.n_obstacles + + // # n_p_pad * 3 + // # ) + + // # EXPs: n_iter * n_p * board.n_obstacles + for (int t = 0; t < n_iter; t++) { for (int i = 0; i < n_p; i++) { + + // # 2 MULTs float desired_velocity_x = e_x[i] * desired_v0[i]; float desired_velocity_y = e_y[i] * desired_v0[i]; + // # 2 ADDs, 2 MULTs float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; @@ -244,6 +303,8 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 acc_y_1 = _mm512_setzero_ps(); for (int j = 0; j < n_p_pad; j += 32) { + + // # 32 ADDs __m512 j_idx_0 = _mm512_add_ps(_mm512_set1_ps((float)j), lane_off); __m512 j_idx_1 = _mm512_add_ps(_mm512_set1_ps((float)j + 16), lane_off); @@ -271,81 +332,105 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 sb_jsq_0 = _mm512_loadu_ps(&sb_sq[j]); __m512 sb_jsq_1 = _mm512_loadu_ps(&sb_sq[j + 16]); + // # 32 ADDs __m512 r_ab_x_0 = _mm512_sub_ps(pix, pjx_0); __m512 r_ab_x_1 = _mm512_sub_ps(pix, pjx_1); + // # 32 ADDs __m512 r_ab_y_0 = _mm512_sub_ps(piy, pjy_0); __m512 r_ab_y_1 = _mm512_sub_ps(piy, pjy_1); + // # 64 MULTs, 32 ADDs __m512 r_ab_n2_0 = _mm512_fmadd_ps(r_ab_x_0, r_ab_x_0, _mm512_mul_ps(r_ab_y_0, r_ab_y_0)); __m512 r_ab_n2_1 = _mm512_fmadd_ps(r_ab_x_1, r_ab_x_1, _mm512_mul_ps(r_ab_y_1, r_ab_y_1)); + // # 32 SQRTs __m512 r_ab_n_0 = _mm512_sqrt_ps(r_ab_n2_0); __m512 r_ab_n_1 = _mm512_sqrt_ps(r_ab_n2_1); + // # 32 ADDs __m512 r_ab2_x_0 = _mm512_sub_ps(r_ab_x_0, sbe_jx_0); __m512 r_ab2_x_1 = _mm512_sub_ps(r_ab_x_1, sbe_jx_1); + // # 32 ADDs __m512 r_ab2_y_0 = _mm512_sub_ps(r_ab_y_0, sbe_jy_0); __m512 r_ab2_y_1 = _mm512_sub_ps(r_ab_y_1, sbe_jy_1); + // # 64 MULTs, 32 ADDs __m512 r_ab2_n2_0 = _mm512_fmadd_ps(r_ab2_x_0, r_ab2_x_0, _mm512_mul_ps(r_ab2_y_0, r_ab2_y_0)); __m512 r_ab2_n2_1 = _mm512_fmadd_ps(r_ab2_x_1, r_ab2_x_1, _mm512_mul_ps(r_ab2_y_1, r_ab2_y_1)); + // # 32 SQRTs __m512 r_ab2_n_0 = _mm512_sqrt_ps(r_ab2_n2_0); __m512 r_ab2_n_1 = _mm512_sqrt_ps(r_ab2_n2_1); + // # 32 ADDs __m512 r_sum_0 = _mm512_add_ps(r_ab_n_0, r_ab2_n_0); __m512 r_sum_1 = _mm512_add_ps(r_ab_n_1, r_ab2_n_1); + // # 32 MULTs, 32 ADDs __m512 two_b_sq_0 = _mm512_fmsub_ps(r_sum_0, r_sum_0, sb_jsq_0); __m512 two_b_sq_1 = _mm512_fmsub_ps(r_sum_1, r_sum_1, sb_jsq_1); + // # 32 SQRTs __m512 two_b_0 = _mm512_sqrt_ps(two_b_sq_0); __m512 two_b_1 = _mm512_sqrt_ps(two_b_sq_1); + // # 32 MULTs __m512 e_arg_0 = _mm512_mul_ps(two_b_0, v_neg_2s_inv); __m512 e_arg_1 = _mm512_mul_ps(two_b_1, v_neg_2s_inv); e_arg_0 = _mm512_max_ps(e_arg_0, v_exp_min); e_arg_1 = _mm512_max_ps(e_arg_1, v_exp_min); + // # 512 MULTs, 448 ADDs __m512 e_val_0 = _avx512_exp_ps(e_arg_0); __m512 e_val_1 = _avx512_exp_ps(e_arg_1); + // # 64 MULTs __m512 numer_0 = _mm512_mul_ps(_mm512_mul_ps(r_sum_0, v_neg_v0_div_2s), e_val_0); __m512 numer_1 = _mm512_mul_ps(_mm512_mul_ps(r_sum_1, v_neg_v0_div_2s), e_val_1); + // # 64 MULTs __m512 denom_0 = _mm512_mul_ps(_mm512_mul_ps(two_b_0, r_ab_n_0), r_ab2_n_0); __m512 denom_1 = _mm512_mul_ps(_mm512_mul_ps(two_b_1, r_ab_n_1), r_ab2_n_1); __m512 denom_safe_0 = _mm512_mask_blend_ps(active_0, v_one, denom_0); __m512 denom_safe_1 = _mm512_mask_blend_ps(active_1, v_one, denom_1); + // # 32 DIVs __m512 smc_0 = _mm512_div_ps(numer_0, denom_safe_0); __m512 smc_1 = _mm512_div_ps(numer_1, denom_safe_1); + // # 32 MULTs __m512 sm_r_ab_0 = _mm512_mul_ps(smc_0, r_ab2_n_0); __m512 sm_r_ab_1 = _mm512_mul_ps(smc_1, r_ab2_n_1); + // # 32 MULTs __m512 sm_r_ab2_0 = _mm512_mul_ps(smc_0, r_ab_n_0); __m512 sm_r_ab2_1 = _mm512_mul_ps(smc_1, r_ab_n_1); + // # 64 MULTs, 32 ADDs __m512 f_x_0 = _mm512_fmadd_ps(r_ab2_x_0, sm_r_ab2_0, _mm512_mul_ps(r_ab_x_0, sm_r_ab_0)); __m512 f_x_1 = _mm512_fmadd_ps(r_ab2_x_1, sm_r_ab2_1, _mm512_mul_ps(r_ab_x_1, sm_r_ab_1)); + // # 64 MULTs, 32 ADDs __m512 f_y_0 = _mm512_fmadd_ps(r_ab2_y_0, sm_r_ab2_0, _mm512_mul_ps(r_ab_y_0, sm_r_ab_0)); __m512 f_y_1 = _mm512_fmadd_ps(r_ab2_y_1, sm_r_ab2_1, _mm512_mul_ps(r_ab_y_1, sm_r_ab_1)); + // # 64 MULTs, 32 ADDs __m512 f_norm_sq_0 = _mm512_fmadd_ps(f_x_0, f_x_0, _mm512_mul_ps(f_y_0, f_y_0)); __m512 f_norm_sq_1 = _mm512_fmadd_ps(f_x_1, f_x_1, _mm512_mul_ps(f_y_1, f_y_1)); + // # 32 MULTs __m512 rhs_0 = _mm512_mul_ps(f_norm_sq_0, v_cos_phi_sq); __m512 rhs_1 = _mm512_mul_ps(f_norm_sq_1, v_cos_phi_sq); + // # 64 MULTs, 32 ADDs __m512 e_dot_f_0 = _mm512_fmadd_ps(eix, f_x_0, _mm512_mul_ps(eiy, f_y_0)); __m512 e_dot_f_1 = _mm512_fmadd_ps(eix, f_x_1, _mm512_mul_ps(eiy, f_y_1)); + // # 32 MULTs __m512 e_dot_f_sq_0 = _mm512_mul_ps(e_dot_f_0, e_dot_f_0); __m512 e_dot_f_sq_1 = _mm512_mul_ps(e_dot_f_1, e_dot_f_1); @@ -367,22 +452,28 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 f_y_safe_0 = _mm512_maskz_mov_ps(active_0, f_y_0); __m512 f_y_safe_1 = _mm512_maskz_mov_ps(active_1, f_y_1); + // # 32 MULTs, 32 ADDs acc_x_0 = _mm512_fmadd_ps(f_x_safe_0, w_val_0, acc_x_0); acc_x_1 = _mm512_fmadd_ps(f_x_safe_1, w_val_1, acc_x_1); + // # 32 MULTs, 32 ADDs acc_y_0 = _mm512_fmadd_ps(f_y_safe_0, w_val_0, acc_y_0); acc_y_1 = _mm512_fmadd_ps(f_y_safe_1, w_val_1, acc_y_1); } + // # 64 ADDs f_alpha_dt_x += _mm512_reduce_add_ps(_mm512_add_ps(acc_x_0, acc_x_1)); f_alpha_dt_y += _mm512_reduce_add_ps(_mm512_add_ps(acc_y_0, acc_y_1)); for (int k = 0; k < board.n_obstacles; k++) { + + // # 2 ADDs float v1_x = pos_x[i] - board.obstacles[k].start_x; float v1_y = pos_y[i] - board.obstacles[k].start_y; float v2_x = board.obstacles[k].obstacle_v_x; float v2_y = board.obstacles[k].obstacle_v_y; + // # 3 MULTs, 1 ADD float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; if (projection < 0.0f) @@ -390,12 +481,15 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c else if (projection > 1.0f) projection = 1.0f; + // # 4 ADDs, 2 MULTs float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); + // # 1 SQRT, 2 MULTs, 1 ADD float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; + // # 4 MULTs, 1 EXP, 1 DIV float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; float f_alpha_B_neg_x = r_aB_x * scalar_mult; float f_alpha_B_neg_y = r_aB_y * scalar_mult; @@ -406,13 +500,16 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c if (e_dot_f < cos_phi) w_val = c_neg_times_dt; + // # 2 MULTS float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; + // # 2 ADDs f_alpha_dt_x += f_alpha_B_dt_x; f_alpha_dt_y += f_alpha_B_dt_y; } + // # 2 ADDs w_x[i] += f_alpha_dt_x; w_y[i] += f_alpha_dt_y; } @@ -446,34 +543,41 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512i color_i_vec_0 = _mm512_loadu_si512((__m512i *)&color[i]); __m512i color_i_vec_1 = _mm512_loadu_si512((__m512i *)&color[i + 16]); + // # 64 MULTs, 32 ADDs __m512 w_norm_sq_0 = _mm512_fmadd_ps(w_x_i_vec_0, w_x_i_vec_0, _mm512_mul_ps(w_y_i_vec_0, w_y_i_vec_0)); __m512 w_norm_sq_1 = _mm512_fmadd_ps(w_x_i_vec_1, w_x_i_vec_1, _mm512_mul_ps(w_y_i_vec_1, w_y_i_vec_1)); + // # 32 SQRTs __m512 w_norm_0 = _mm512_sqrt_ps(w_norm_sq_0); __m512 w_norm_1 = _mm512_sqrt_ps(w_norm_sq_1); + // # 32 DIVs __m512 correction_factor_0 = _mm512_min_ps(_mm512_set1_ps(1.0f), _mm512_div_ps(v_max_i_vec_0, w_norm_0)); __m512 correction_factor_1 = _mm512_min_ps(_mm512_set1_ps(1.0f), _mm512_div_ps(v_max_i_vec_1, w_norm_1)); + // # 32 MULTs __m512 curr_vel_x_i_vec_0 = _mm512_mul_ps(w_x_i_vec_0, correction_factor_0); __m512 curr_vel_x_i_vec_1 = _mm512_mul_ps(w_x_i_vec_1, correction_factor_1); + // # 32 MULTs __m512 curr_vel_y_i_vec_0 = _mm512_mul_ps(w_y_i_vec_0, correction_factor_0); __m512 curr_vel_y_i_vec_1 = _mm512_mul_ps(w_y_i_vec_1, correction_factor_1); __m512 dt_vec = _mm512_set1_ps(dt); + // # 32 MULTs, 32 ADDs pos_x_i_vec_0 = _mm512_fmadd_ps(curr_vel_x_i_vec_0, dt_vec, pos_x_i_vec_0); pos_x_i_vec_1 = _mm512_fmadd_ps(curr_vel_x_i_vec_1, dt_vec, pos_x_i_vec_1); + // # 32 MULTs, 32 ADDs pos_y_i_vec_0 = _mm512_fmadd_ps(curr_vel_y_i_vec_0, dt_vec, pos_y_i_vec_0); pos_y_i_vec_1 = _mm512_fmadd_ps(curr_vel_y_i_vec_1, dt_vec, pos_y_i_vec_1); __mmask16 cond_1_left_0 = _mm512_cmpeq_epi32_mask(color_i_vec_0, _mm512_setzero_si512()); __mmask16 cond_1_left_1 = _mm512_cmpeq_epi32_mask(color_i_vec_1, _mm512_setzero_si512()); - __mmask16 cond_1_right_0 = _mm512_cmp_ps_mask(pos_x_i_vec_0, _mm512_set1_ps(BOARD_LENGTH - 1.5f), _CMP_GT_OQ); - __mmask16 cond_1_right_1 = _mm512_cmp_ps_mask(pos_x_i_vec_1, _mm512_set1_ps(BOARD_LENGTH - 1.5f), _CMP_GT_OQ); + __mmask16 cond_1_right_0 = _mm512_cmp_ps_mask(pos_x_i_vec_0, _mm512_set1_ps(BOARD_LENGTH_MINUS_ONE_POINT_FIVE), _CMP_GT_OQ); + __mmask16 cond_1_right_1 = _mm512_cmp_ps_mask(pos_x_i_vec_1, _mm512_set1_ps(BOARD_LENGTH_MINUS_ONE_POINT_FIVE), _CMP_GT_OQ); __mmask16 cond_1_0 = cond_1_left_0 & cond_1_right_0; __mmask16 cond_1_1 = cond_1_left_1 & cond_1_right_1; @@ -529,33 +633,43 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c pos_y_i_vec_0 = _mm512_min_ps(pos_y_i_vec_0, _mm512_set1_ps(BOARD_WIDTH_MINUS_WALL_EPS)); pos_y_i_vec_1 = _mm512_min_ps(pos_y_i_vec_1, _mm512_set1_ps(BOARD_WIDTH_MINUS_WALL_EPS)); + // # 32 ADDs __m512 ex_vec_0 = _mm512_sub_ps(destination_x_i_vec_0, pos_x_i_vec_0); __m512 ex_vec_1 = _mm512_sub_ps(destination_x_i_vec_1, pos_x_i_vec_1); + // # 32 ADDs __m512 ey_vec_0 = _mm512_sub_ps(destination_y_i_vec_0, pos_y_i_vec_0); __m512 ey_vec_1 = _mm512_sub_ps(destination_y_i_vec_1, pos_y_i_vec_1); + // # 64 MULTs, 32 ADDs __m512 e_norm_sq_0 = _mm512_fmadd_ps(ex_vec_0, ex_vec_0, _mm512_mul_ps(ey_vec_0, ey_vec_0)); __m512 e_norm_sq_1 = _mm512_fmadd_ps(ex_vec_1, ex_vec_1, _mm512_mul_ps(ey_vec_1, ey_vec_1)); + // # 32 SQRTs __m512 e_norm_0 = _mm512_sqrt_ps(e_norm_sq_0); __m512 e_norm_1 = _mm512_sqrt_ps(e_norm_sq_1); + // # 32 DIVs __m512 e_norm_inv_0 = _mm512_div_ps(_mm512_set1_ps(1.0f), e_norm_0); __m512 e_norm_inv_1 = _mm512_div_ps(_mm512_set1_ps(1.0f), e_norm_1); + // # 32 MULTs __m512 e_x_i_vec_0 = _mm512_mul_ps(ex_vec_0, e_norm_inv_0); __m512 e_x_i_vec_1 = _mm512_mul_ps(ex_vec_1, e_norm_inv_1); + // # 32 MULTs __m512 e_y_i_vec_0 = _mm512_mul_ps(ey_vec_0, e_norm_inv_0); __m512 e_y_i_vec_1 = _mm512_mul_ps(ey_vec_1, e_norm_inv_1); + // # 64 MULTs, 32 ADDs __m512 vel_norm_sq_0 = _mm512_fmadd_ps(curr_vel_x_i_vec_0, curr_vel_x_i_vec_0, _mm512_mul_ps(curr_vel_y_i_vec_0, curr_vel_y_i_vec_0)); __m512 vel_norm_sq_1 = _mm512_fmadd_ps(curr_vel_x_i_vec_1, curr_vel_x_i_vec_1, _mm512_mul_ps(curr_vel_y_i_vec_1, curr_vel_y_i_vec_1)); + // # 32 MULTs __m512 sb_sq_i_vec_0 = _mm512_mul_ps(vel_norm_sq_0, _mm512_set1_ps(delta_t_sq)); __m512 sb_sq_i_vec_1 = _mm512_mul_ps(vel_norm_sq_1, _mm512_set1_ps(delta_t_sq)); + // # 32 SQRTs __m512 vel_norm_dt_0 = _mm512_sqrt_ps(sb_sq_i_vec_0); __m512 vel_norm_dt_1 = _mm512_sqrt_ps(sb_sq_i_vec_1); @@ -589,9 +703,11 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c _mm512_storeu_ps(&sb_sq[i], sb_sq_i_vec_0); _mm512_storeu_ps(&sb_sq[i + 16], sb_sq_i_vec_1); + // # 32 MULTs _mm512_storeu_ps(&sb_e_x[i], _mm512_mul_ps(e_x_i_vec_0, vel_norm_dt_0)); _mm512_storeu_ps(&sb_e_x[i + 16], _mm512_mul_ps(e_x_i_vec_1, vel_norm_dt_1)); + // # 32 MULTs _mm512_storeu_ps(&sb_e_y[i], _mm512_mul_ps(e_y_i_vec_0, vel_norm_dt_0)); _mm512_storeu_ps(&sb_e_y[i + 16], _mm512_mul_ps(e_y_i_vec_1, vel_norm_dt_1)); } diff --git a/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt.cpp b/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt.cpp index 828a9b1..ec69800 100644 --- a/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt.cpp +++ b/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt.cpp @@ -13,6 +13,8 @@ #define SEED 42 #define BOARD_WIDTH 10.0f #define BOARD_LENGTH 50.0f +#define BOARD_LENGTH_MINUS_ONE BOARD_LENGTH - 1.0f +#define BOARD_LENGTH_MINUS_ONE_POINT_FIVE BOARD_LENGTH - 1.5f #define WALL_EPS 1e-3f #define BOARD_WIDTH_MINUS_WALL_EPS 9.999f @@ -160,21 +162,46 @@ Pedestrian *init_pedestrians(int n_p) { Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } +// # 256 MULTs, 224 ADDs static inline __m512 _avx512_exp_ps(__m512 x) { + const __m512 log2e = _mm512_set1_ps(1.4426950408889634f); + + // # 16 MULTs __m512 nf = _mm512_roundscale_ps(_mm512_mul_ps(x, log2e), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); const __m512 ln2 = _mm512_set1_ps(0.6931471805599453f); + + // # 16 MULTs, 16 ADDs __m512 r = _mm512_fnmadd_ps(nf, ln2, x); - const __m512 c5 = _mm512_set1_ps(1.0f / 120.0f); - const __m512 c4 = _mm512_set1_ps(1.0f / 24.0f); - const __m512 c3 = _mm512_set1_ps(1.0f / 6.0f); - const __m512 c2 = _mm512_set1_ps(0.5f); - const __m512 c1 = _mm512_set1_ps(1.0f); - const __m512 c0 = _mm512_set1_ps(1.0f); + const __m512 c13 = _mm512_set1_ps(c13_scalar); + const __m512 c12 = _mm512_set1_ps(c12_scalar); + const __m512 c11 = _mm512_set1_ps(c11_scalar); + const __m512 c10 = _mm512_set1_ps(c10_scalar); + const __m512 c9 = _mm512_set1_ps(c9_scalar); + const __m512 c8 = _mm512_set1_ps(c8_scalar); + const __m512 c7 = _mm512_set1_ps(c7_scalar); + const __m512 c6 = _mm512_set1_ps(c6_scalar); + const __m512 c5 = _mm512_set1_ps(c5_scalar); + const __m512 c4 = _mm512_set1_ps(c4_scalar); + const __m512 c3 = _mm512_set1_ps(c3_scalar); + const __m512 c2 = _mm512_set1_ps(c2_scalar); + const __m512 c1 = _mm512_set1_ps(c1_scalar); + const __m512 c0 = _mm512_set1_ps(c0_scalar); - __m512 p = c5; + __m512 p = c13; + + // # 13 * (16 MULTs, 16 ADDs) + // # = 208 MULTs, 208 ADDs + p = _mm512_fmadd_ps(p, r, c12); + p = _mm512_fmadd_ps(p, r, c11); + p = _mm512_fmadd_ps(p, r, c10); + p = _mm512_fmadd_ps(p, r, c9); + p = _mm512_fmadd_ps(p, r, c8); + p = _mm512_fmadd_ps(p, r, c7); + p = _mm512_fmadd_ps(p, r, c6); + p = _mm512_fmadd_ps(p, r, c5); p = _mm512_fmadd_ps(p, r, c4); p = _mm512_fmadd_ps(p, r, c3); p = _mm512_fmadd_ps(p, r, c2); @@ -186,6 +213,7 @@ static inline __m512 _avx512_exp_ps(__m512 x) { __m512i scaled = _mm512_slli_epi32(biased, 23); __m512 pow2n = _mm512_castsi512_ps(scaled); + // # 16 MULTs return _mm512_mul_ps(p, pow2n); } @@ -224,11 +252,42 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c const __m512 v_np = _mm512_set1_ps((float)n_p); const __m512 v_exp_min = _mm512_set1_ps(-87.0f); + // # ADDs: n_iter * ( + // # n_p * 68 + + // # n_p * n_p_pad * 29 + // # n_p * board.n_obstacles * 10 + // # n_p_pad * 9 + // # ) + + // # MULTs: n_iter * ( + // # n_p * 4 + + // # n_p * n_p_pad * 40 + // # n_p * board.n_obstacles * 13 + // # n_p_pad * 17 + // # ) + + // # DIVs: n_iter * ( + // # n_p * n_p_pad + // # n_p * board.n_obstacles + // # n_p_pad * 2 + // # ) + + // # SQRTs: n_iter * ( + // # n_p * n_p_pad * 3 + // # n_p * board.n_obstacles + // # n_p_pad * 3 + // # ) + + // # EXPs: n_iter * n_p * board.n_obstacles + for (int t = 0; t < n_iter; t++) { for (int i = 0; i < n_p; i++) { + + // # 2 MULTs float desired_velocity_x = e_x[i] * desired_v0[i]; float desired_velocity_y = e_y[i] * desired_v0[i]; + // # 2 ADDs, 2 MULTs float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; @@ -244,6 +303,8 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 acc_y_1 = _mm512_setzero_ps(); for (int j = 0; j < n_p_pad; j += 32) { + + // # 32 ADDs __m512 j_idx_0 = _mm512_add_ps(_mm512_set1_ps((float)j), lane_off); __m512 j_idx_1 = _mm512_add_ps(_mm512_set1_ps((float)j + 16), lane_off); @@ -271,81 +332,105 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 sb_jsq_0 = _mm512_loadu_ps(&sb_sq[j]); __m512 sb_jsq_1 = _mm512_loadu_ps(&sb_sq[j + 16]); + // # 32 ADDs __m512 r_ab_x_0 = _mm512_sub_ps(pix, pjx_0); __m512 r_ab_x_1 = _mm512_sub_ps(pix, pjx_1); + // # 32 ADDs __m512 r_ab_y_0 = _mm512_sub_ps(piy, pjy_0); __m512 r_ab_y_1 = _mm512_sub_ps(piy, pjy_1); + // # 64 MULTs, 32 ADDs __m512 r_ab_n2_0 = _mm512_fmadd_ps(r_ab_x_0, r_ab_x_0, _mm512_mul_ps(r_ab_y_0, r_ab_y_0)); __m512 r_ab_n2_1 = _mm512_fmadd_ps(r_ab_x_1, r_ab_x_1, _mm512_mul_ps(r_ab_y_1, r_ab_y_1)); + // # 32 SQRTs __m512 r_ab_n_0 = _mm512_sqrt_ps(r_ab_n2_0); __m512 r_ab_n_1 = _mm512_sqrt_ps(r_ab_n2_1); + // # 32 ADDs __m512 r_ab2_x_0 = _mm512_sub_ps(r_ab_x_0, sbe_jx_0); __m512 r_ab2_x_1 = _mm512_sub_ps(r_ab_x_1, sbe_jx_1); + // # 32 ADDs __m512 r_ab2_y_0 = _mm512_sub_ps(r_ab_y_0, sbe_jy_0); __m512 r_ab2_y_1 = _mm512_sub_ps(r_ab_y_1, sbe_jy_1); + // # 64 MULTs, 32 ADDs __m512 r_ab2_n2_0 = _mm512_fmadd_ps(r_ab2_x_0, r_ab2_x_0, _mm512_mul_ps(r_ab2_y_0, r_ab2_y_0)); __m512 r_ab2_n2_1 = _mm512_fmadd_ps(r_ab2_x_1, r_ab2_x_1, _mm512_mul_ps(r_ab2_y_1, r_ab2_y_1)); + // # 32 SQRTs __m512 r_ab2_n_0 = _mm512_sqrt_ps(r_ab2_n2_0); __m512 r_ab2_n_1 = _mm512_sqrt_ps(r_ab2_n2_1); + // # 32 ADDs __m512 r_sum_0 = _mm512_add_ps(r_ab_n_0, r_ab2_n_0); __m512 r_sum_1 = _mm512_add_ps(r_ab_n_1, r_ab2_n_1); + // # 32 MULTs, 32 ADDs __m512 two_b_sq_0 = _mm512_fmsub_ps(r_sum_0, r_sum_0, sb_jsq_0); __m512 two_b_sq_1 = _mm512_fmsub_ps(r_sum_1, r_sum_1, sb_jsq_1); + // # 32 SQRTs __m512 two_b_0 = _mm512_sqrt_ps(two_b_sq_0); __m512 two_b_1 = _mm512_sqrt_ps(two_b_sq_1); + // # 32 MULTs __m512 e_arg_0 = _mm512_mul_ps(two_b_0, v_neg_2s_inv); __m512 e_arg_1 = _mm512_mul_ps(two_b_1, v_neg_2s_inv); e_arg_0 = _mm512_max_ps(e_arg_0, v_exp_min); e_arg_1 = _mm512_max_ps(e_arg_1, v_exp_min); + // # 512 MULTs, 448 ADDs __m512 e_val_0 = _avx512_exp_ps(e_arg_0); __m512 e_val_1 = _avx512_exp_ps(e_arg_1); + // # 64 MULTs __m512 numer_0 = _mm512_mul_ps(_mm512_mul_ps(r_sum_0, v_neg_v0_div_2s), e_val_0); __m512 numer_1 = _mm512_mul_ps(_mm512_mul_ps(r_sum_1, v_neg_v0_div_2s), e_val_1); + // # 64 MULTs __m512 denom_0 = _mm512_mul_ps(_mm512_mul_ps(two_b_0, r_ab_n_0), r_ab2_n_0); __m512 denom_1 = _mm512_mul_ps(_mm512_mul_ps(two_b_1, r_ab_n_1), r_ab2_n_1); __m512 denom_safe_0 = _mm512_mask_blend_ps(active_0, v_one, denom_0); __m512 denom_safe_1 = _mm512_mask_blend_ps(active_1, v_one, denom_1); + // # 32 DIVs __m512 smc_0 = _mm512_div_ps(numer_0, denom_safe_0); __m512 smc_1 = _mm512_div_ps(numer_1, denom_safe_1); + // # 32 MULTs __m512 sm_r_ab_0 = _mm512_mul_ps(smc_0, r_ab2_n_0); __m512 sm_r_ab_1 = _mm512_mul_ps(smc_1, r_ab2_n_1); + // # 32 MULTs __m512 sm_r_ab2_0 = _mm512_mul_ps(smc_0, r_ab_n_0); __m512 sm_r_ab2_1 = _mm512_mul_ps(smc_1, r_ab_n_1); + // # 64 MULTs, 32 ADDs __m512 f_x_0 = _mm512_fmadd_ps(r_ab2_x_0, sm_r_ab2_0, _mm512_mul_ps(r_ab_x_0, sm_r_ab_0)); __m512 f_x_1 = _mm512_fmadd_ps(r_ab2_x_1, sm_r_ab2_1, _mm512_mul_ps(r_ab_x_1, sm_r_ab_1)); + // # 64 MULTs, 32 ADDs __m512 f_y_0 = _mm512_fmadd_ps(r_ab2_y_0, sm_r_ab2_0, _mm512_mul_ps(r_ab_y_0, sm_r_ab_0)); __m512 f_y_1 = _mm512_fmadd_ps(r_ab2_y_1, sm_r_ab2_1, _mm512_mul_ps(r_ab_y_1, sm_r_ab_1)); + // # 64 MULTs, 32 ADDs __m512 f_norm_sq_0 = _mm512_fmadd_ps(f_x_0, f_x_0, _mm512_mul_ps(f_y_0, f_y_0)); __m512 f_norm_sq_1 = _mm512_fmadd_ps(f_x_1, f_x_1, _mm512_mul_ps(f_y_1, f_y_1)); + // # 32 MULTs __m512 rhs_0 = _mm512_mul_ps(f_norm_sq_0, v_cos_phi_sq); __m512 rhs_1 = _mm512_mul_ps(f_norm_sq_1, v_cos_phi_sq); + // # 64 MULTs, 32 ADDs __m512 e_dot_f_0 = _mm512_fmadd_ps(eix, f_x_0, _mm512_mul_ps(eiy, f_y_0)); __m512 e_dot_f_1 = _mm512_fmadd_ps(eix, f_x_1, _mm512_mul_ps(eiy, f_y_1)); + // # 32 MULTs __m512 e_dot_f_sq_0 = _mm512_mul_ps(e_dot_f_0, e_dot_f_0); __m512 e_dot_f_sq_1 = _mm512_mul_ps(e_dot_f_1, e_dot_f_1); @@ -367,22 +452,28 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 f_y_safe_0 = _mm512_maskz_mov_ps(active_0, f_y_0); __m512 f_y_safe_1 = _mm512_maskz_mov_ps(active_1, f_y_1); + // # 32 MULTs, 32 ADDs acc_x_0 = _mm512_fmadd_ps(f_x_safe_0, w_val_0, acc_x_0); acc_x_1 = _mm512_fmadd_ps(f_x_safe_1, w_val_1, acc_x_1); + // # 32 MULTs, 32 ADDs acc_y_0 = _mm512_fmadd_ps(f_y_safe_0, w_val_0, acc_y_0); acc_y_1 = _mm512_fmadd_ps(f_y_safe_1, w_val_1, acc_y_1); } + // # 64 ADDs f_alpha_dt_x += _mm512_reduce_add_ps(_mm512_add_ps(acc_x_0, acc_x_1)); f_alpha_dt_y += _mm512_reduce_add_ps(_mm512_add_ps(acc_y_0, acc_y_1)); for (int k = 0; k < board.n_obstacles; k++) { + + // # 2 ADDs float v1_x = pos_x[i] - board.obstacles[k].start_x; float v1_y = pos_y[i] - board.obstacles[k].start_y; float v2_x = board.obstacles[k].obstacle_v_x; float v2_y = board.obstacles[k].obstacle_v_y; + // # 3 MULTs, 1 ADD float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; if (projection < 0.0f) @@ -390,12 +481,15 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c else if (projection > 1.0f) projection = 1.0f; + // # 4 ADDs, 2 MULTs float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); + // # 1 SQRT, 2 MULTs, 1 ADD float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; + // # 4 MULTs, 1 EXP, 1 DIV float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; float f_alpha_B_neg_x = r_aB_x * scalar_mult; float f_alpha_B_neg_y = r_aB_y * scalar_mult; @@ -406,13 +500,16 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c if (e_dot_f < cos_phi) w_val = c_neg_times_dt; + // # 2 MULTS float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; + // # 2 ADDs f_alpha_dt_x += f_alpha_B_dt_x; f_alpha_dt_y += f_alpha_B_dt_y; } + // # 2 ADDs w_x[i] += f_alpha_dt_x; w_y[i] += f_alpha_dt_y; } @@ -430,19 +527,27 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512i color_i_vec = _mm512_loadu_si512((__m512i *)&color[i]); + // # 32 MULTs, 16 ADDs __m512 w_norm_sq = _mm512_fmadd_ps(w_x_i_vec, w_x_i_vec, _mm512_mul_ps(w_y_i_vec, w_y_i_vec)); + + // # 16 SQRTs, 16 DIVs __m512 w_norm_inv = _mm512_rsqrt14_ps(w_norm_sq); + + // # 16 MULTs __m512 correction_factor = _mm512_min_ps(_mm512_set1_ps(1.0f), _mm512_mul_ps(v_max_i_vec, w_norm_inv)); + // # 32 MULTs __m512 curr_vel_x_i_vec = _mm512_mul_ps(w_x_i_vec, correction_factor); __m512 curr_vel_y_i_vec = _mm512_mul_ps(w_y_i_vec, correction_factor); __m512 dt_vec = _mm512_set1_ps(dt); + + // # 32 MULTs, 32 ADDs pos_x_i_vec = _mm512_fmadd_ps(curr_vel_x_i_vec, dt_vec, pos_x_i_vec); pos_y_i_vec = _mm512_fmadd_ps(curr_vel_y_i_vec, dt_vec, pos_y_i_vec); __mmask16 cond_1_left = _mm512_cmpeq_epi32_mask(color_i_vec, _mm512_setzero_si512()); - __mmask16 cond_1_right = _mm512_cmp_ps_mask(pos_x_i_vec, _mm512_set1_ps(BOARD_LENGTH - 1.5f), _CMP_GT_OQ); + __mmask16 cond_1_right = _mm512_cmp_ps_mask(pos_x_i_vec, _mm512_set1_ps(BOARD_LENGTH_MINUS_ONE_POINT_FIVE), _CMP_GT_OQ); __mmask16 cond_1 = cond_1_left & cond_1_right; pos_x_i_vec = _mm512_mask_blend_ps(cond_1, pos_x_i_vec, _mm512_set1_ps(1.0f)); @@ -456,7 +561,7 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __mmask16 cond_2_right = _mm512_cmp_ps_mask(pos_x_i_vec, _mm512_set1_ps(1.5f), _CMP_LT_OQ); __mmask16 cond_2 = cond_2_left & cond_2_right; - pos_x_i_vec = _mm512_mask_blend_ps(cond_2, pos_x_i_vec, _mm512_set1_ps(BOARD_LENGTH - 1.0f)); + pos_x_i_vec = _mm512_mask_blend_ps(cond_2, pos_x_i_vec, _mm512_set1_ps(BOARD_LENGTH_MINUS_ONE)); destination_y_i_vec = _mm512_mask_blend_ps(cond_2, destination_y_i_vec, pos_y_i_vec); __m512 neg_desired_v0 = _mm512_xor_ps(desired_v0_i_vec, _mm512_set1_ps(-0.0f)); w_x_i_vec = _mm512_mask_blend_ps(cond_2, w_x_i_vec, neg_desired_v0); @@ -467,15 +572,27 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c pos_y_i_vec = _mm512_max_ps(pos_y_i_vec, _mm512_set1_ps(WALL_EPS)); pos_y_i_vec = _mm512_min_ps(pos_y_i_vec, _mm512_set1_ps(BOARD_WIDTH_MINUS_WALL_EPS)); + // # 32 ADDs __m512 ex_vec = _mm512_sub_ps(destination_x_i_vec, pos_x_i_vec); __m512 ey_vec = _mm512_sub_ps(destination_y_i_vec, pos_y_i_vec); + + // # 32 MULTs, 16 ADDs __m512 e_norm_sq = _mm512_fmadd_ps(ex_vec, ex_vec, _mm512_mul_ps(ey_vec, ey_vec)); + + // # 16 DIVs, 16 SQRTs __m512 e_norm_inv = _mm512_rsqrt14_ps(e_norm_sq); + + // # 32 MULTs __m512 e_x_i_vec = _mm512_mul_ps(ex_vec, e_norm_inv); __m512 e_y_i_vec = _mm512_mul_ps(ey_vec, e_norm_inv); + // # 32 MULTs, 16 ADDs __m512 vel_norm_sq = _mm512_fmadd_ps(curr_vel_x_i_vec, curr_vel_x_i_vec, _mm512_mul_ps(curr_vel_y_i_vec, curr_vel_y_i_vec)); + + // # 16 MULTs __m512 sb_sq_i_vec = _mm512_mul_ps(vel_norm_sq, _mm512_set1_ps(delta_t_sq)); + + // # 16 SQRTs __m512 vel_norm_dt = _mm512_sqrt_ps(sb_sq_i_vec); _mm512_storeu_ps(&curr_vel_x[i], curr_vel_x_i_vec); @@ -488,6 +605,8 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c _mm512_storeu_ps(&e_y[i], e_y_i_vec); _mm512_storeu_ps(&destination_y[i], destination_y_i_vec); _mm512_storeu_ps(&sb_sq[i], sb_sq_i_vec); + + // # 32 MULTs _mm512_storeu_ps(&sb_e_x[i], _mm512_mul_ps(e_x_i_vec, vel_norm_dt)); _mm512_storeu_ps(&sb_e_y[i], _mm512_mul_ps(e_y_i_vec, vel_norm_dt)); } diff --git a/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt.cpp b/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt.cpp index 9e4233c..d4253cf 100644 --- a/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt.cpp +++ b/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt.cpp @@ -13,6 +13,8 @@ #define SEED 42 #define BOARD_WIDTH 10.0f #define BOARD_LENGTH 50.0f +#define BOARD_LENGTH_MINUS_ONE BOARD_LENGTH - 1.0f +#define BOARD_LENGTH_MINUS_ONE_POINT_FIVE BOARD_LENGTH - 1.5f #define WALL_EPS 1e-3f #define BOARD_WIDTH_MINUS_WALL_EPS 9.999f @@ -160,41 +162,58 @@ Pedestrian *init_pedestrians(int n_p) { Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } +// # 256 MULTs, 224 ADDs static inline __m512 _avx512_exp_ps(__m512 x) { - // define own inlined intrinsic function for approximating the exponent function - // e^x = 2^n * e^r --> x = n * ln(2) + r const __m512 log2e = _mm512_set1_ps(1.4426950408889634f); + + // # 16 MULTs __m512 nf = _mm512_roundscale_ps(_mm512_mul_ps(x, log2e), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); const __m512 ln2 = _mm512_set1_ps(0.6931471805599453f); - // r = x - n * ln(2) + + // # 16 MULTs, 16 ADDs __m512 r = _mm512_fnmadd_ps(nf, ln2, x); - // approximation of e^r using taylor polynomial - // cNUM --> coefficients - const __m512 c5 = _mm512_set1_ps(1.0f / 120.0f); - const __m512 c4 = _mm512_set1_ps(1.0f / 24.0f); - const __m512 c3 = _mm512_set1_ps(1.0f / 6.0f); - const __m512 c2 = _mm512_set1_ps(0.5f); - const __m512 c1 = _mm512_set1_ps(1.0f); - const __m512 c0 = _mm512_set1_ps(1.0f); + const __m512 c13 = _mm512_set1_ps(c13_scalar); + const __m512 c12 = _mm512_set1_ps(c12_scalar); + const __m512 c11 = _mm512_set1_ps(c11_scalar); + const __m512 c10 = _mm512_set1_ps(c10_scalar); + const __m512 c9 = _mm512_set1_ps(c9_scalar); + const __m512 c8 = _mm512_set1_ps(c8_scalar); + const __m512 c7 = _mm512_set1_ps(c7_scalar); + const __m512 c6 = _mm512_set1_ps(c6_scalar); + const __m512 c5 = _mm512_set1_ps(c5_scalar); + const __m512 c4 = _mm512_set1_ps(c4_scalar); + const __m512 c3 = _mm512_set1_ps(c3_scalar); + const __m512 c2 = _mm512_set1_ps(c2_scalar); + const __m512 c1 = _mm512_set1_ps(c1_scalar); + const __m512 c0 = _mm512_set1_ps(c0_scalar); - // apply coefficients - __m512 p = c5; + __m512 p = c13; + + // # 13 * (16 MULTs, 16 ADDs) + // # = 208 MULTs, 208 ADDs + p = _mm512_fmadd_ps(p, r, c12); + p = _mm512_fmadd_ps(p, r, c11); + p = _mm512_fmadd_ps(p, r, c10); + p = _mm512_fmadd_ps(p, r, c9); + p = _mm512_fmadd_ps(p, r, c8); + p = _mm512_fmadd_ps(p, r, c7); + p = _mm512_fmadd_ps(p, r, c6); + p = _mm512_fmadd_ps(p, r, c5); p = _mm512_fmadd_ps(p, r, c4); p = _mm512_fmadd_ps(p, r, c3); p = _mm512_fmadd_ps(p, r, c2); p = _mm512_fmadd_ps(p, r, c1); p = _mm512_fmadd_ps(p, r, c0); - // use bit shifting for 2^n and bias because float have 23 bit mantissa __m512i ni = _mm512_cvtps_epi32(nf); __m512i biased = _mm512_add_epi32(ni, _mm512_set1_epi32(127)); __m512i scaled = _mm512_slli_epi32(biased, 23); __m512 pow2n = _mm512_castsi512_ps(scaled); - // e^x + // # 16 MULTs return _mm512_mul_ps(p, pow2n); } @@ -233,254 +252,227 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c const __m512 v_np = _mm512_set1_ps((float)n_p); const __m512 v_exp_min = _mm512_set1_ps(-87.0f); + // # ADDs: n_iter * ( + // # n_p * 68 + + // # n_p * n_p_pad * 29 + + // # n_p * board.n_obstacles * 10 + + // # n_p_pad * 7 + // # ) + + // # MULTs: n_iter * ( + // # n_p * 4 + + // # n_p * n_p_pad * 42 + + // # n_p * board.n_obstacles * 13 + + // # n_p_pad * 16 + // # ) + + // # DIVs: n_iter * ( + // # n_p * n_p_pad * 3 + + // # n_p * board.n_obstacles + + // # n_p_pad * 2 + // # ) + + // # SQRTs: n_iter * ( + // # n_p * n_p_pad * 3 + + // # n_p * board.n_obstacles + + // # n_p_pad * 3 + // # ) + + // # EXPs: n_iter * n_p * board.n_obstacles + for (int t = 0; t < n_iter; t++) { for (int i = 0; i < n_p; i++) { - // set the vector for the current pedestrian - // get desired velocity + // # 2 MULTs float desired_velocity_x = e_x[i] * desired_v0[i]; float desired_velocity_y = e_y[i] * desired_v0[i]; - // velocity change accumulator + // # 2 ADDs, 2 MULTs float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; - // pos const __m512 pix = _mm512_set1_ps(pos_x[i]); const __m512 piy = _mm512_set1_ps(pos_y[i]); - // desired direction const __m512 eix = _mm512_set1_ps(e_x[i]); const __m512 eiy = _mm512_set1_ps(e_y[i]); - // broadcast index used by mask to prevent situation pedestrian[i] == pedestrian[j], see m_neq_i_0 and m_neq_i_1 const __m512 v_i = _mm512_set1_ps((float)i); - // accumulators --> 16 pedestrians per accumulator __m512 acc_x_0 = _mm512_setzero_ps(); __m512 acc_y_0 = _mm512_setzero_ps(); __m512 acc_x_1 = _mm512_setzero_ps(); __m512 acc_y_1 = _mm512_setzero_ps(); - // force between pedestrians - // loop unroll factor 32 with 2 vectors - // --> each vector has 16 lanes for (int j = 0; j < n_p_pad; j += 32) { - - // [j, j+1, j+2, ..., j+15] and [j+16, j+17, j+18, ..., j+31] + + // # 32 ADDs __m512 j_idx_0 = _mm512_add_ps(_mm512_set1_ps((float)j), lane_off); __m512 j_idx_1 = _mm512_add_ps(_mm512_set1_ps((float)j + 16), lane_off); - // lane is active if j != i - // [1,1,1,0,1,1,1,...] 0 --> i == j, 1 --> i != j __mmask16 m_neq_i_0 = _mm512_cmp_ps_mask(j_idx_0, v_i, _CMP_NEQ_OQ); __mmask16 m_neq_i_1 = _mm512_cmp_ps_mask(j_idx_1, v_i, _CMP_NEQ_OQ); - - // lane is active if j < n_p --> valid range - // [1,1,1,0,1,1,1,...] 0 --> j >= n_p, 1 --> j < n_p + __mmask16 m_in_range_0 = _mm512_cmp_ps_mask(j_idx_0, v_np, _CMP_LT_OQ); __mmask16 m_in_range_1 = _mm512_cmp_ps_mask(j_idx_1, v_np, _CMP_LT_OQ); - // bitwise comparison if not valid --> 0 - // finally check if lane is valid or not --> prevents i == j, and - // j >= n_p because of loop unrolling --> we can therefore omit a remainings for loop __mmask16 active_0 = m_neq_i_0 & m_in_range_0; __mmask16 active_1 = m_neq_i_1 & m_in_range_1; - // --- - - // load the positions of the other pedestrians x value - // [pos[j], pos[j+1], ..., pos[j+15]] and [pos[16], pos[j+17], ..., pos[j+31]] for x and y __m512 pjx_0 = _mm512_loadu_ps(&pos_x[j]); __m512 pjx_1 = _mm512_loadu_ps(&pos_x[j + 16]); __m512 pjy_0 = _mm512_loadu_ps(&pos_y[j]); __m512 pjy_1 = _mm512_loadu_ps(&pos_y[j + 16]); - // --- - - // step vector of j - // [(v_j * delta_t * e_j).x, (v_j+1 * delta_t * e_j+1).x, ...] __m512 sbe_jx_0 = _mm512_loadu_ps(&sb_e_x[j]); __m512 sbe_jx_1 = _mm512_loadu_ps(&sb_e_x[j + 16]); __m512 sbe_jy_0 = _mm512_loadu_ps(&sb_e_y[j]); __m512 sbe_jy_1 = _mm512_loadu_ps(&sb_e_y[j + 16]); - // --- - - // squared step length - // [j, j+1, ...] __m512 sb_jsq_0 = _mm512_loadu_ps(&sb_sq[j]); __m512 sb_jsq_1 = _mm512_loadu_ps(&sb_sq[j + 16]); - // --- - - // distance vector - // [j, j+1, ...] + // # 64 ADDs __m512 r_ab_x_0 = _mm512_sub_ps(pix, pjx_0); __m512 r_ab_x_1 = _mm512_sub_ps(pix, pjx_1); __m512 r_ab_y_0 = _mm512_sub_ps(piy, pjy_0); __m512 r_ab_y_1 = _mm512_sub_ps(piy, pjy_1); - // |r_ab|^2 needed for rsqrt to prevent 0 values --> x^2 + y^2 + // # 64 MULTs, 32 ADDs __m512 r_ab_n2_0 = _mm512_fmadd_ps(r_ab_x_0, r_ab_x_0, _mm512_mul_ps(r_ab_y_0, r_ab_y_0)); __m512 r_ab_n2_1 = _mm512_fmadd_ps(r_ab_x_1, r_ab_x_1, _mm512_mul_ps(r_ab_y_1, r_ab_y_1)); - // prevent cases where distance = 0 (=pedestrian on top of each other) - // [dist_i_j, dist_i_j+1, ...] r_ab_n2_0 = _mm512_max_ps(r_ab_n2_0, v_eps_sq); r_ab_n2_1 = _mm512_max_ps(r_ab_n2_1, v_eps_sq); - - // --- - - // 1 / |r_ab| --> 14 bit rsqrt approx. rsqrt --> 1 / x^2 --> rsqrt(x^2) = 1/x - // [1 / dist_i_j, 1 / dist_i_j+1, ...] + + // # 32 DIVs, 32 SQRTs __m512 inv_r_ab_n_0 = _mm512_rsqrt14_ps(r_ab_n2_0); __m512 inv_r_ab_n_1 = _mm512_rsqrt14_ps(r_ab_n2_1); - // r_ab^2 * 1 / r_ab = |r_ab| --> normed - // [r_i_j, r_i_j+1, ...] + // # 32 MULTs __m512 r_ab_n_0 = _mm512_mul_ps(r_ab_n2_0, inv_r_ab_n_0); __m512 r_ab_n_1 = _mm512_mul_ps(r_ab_n2_1, inv_r_ab_n_1); - // r_ab - step[j] - // j next pos + // # 64 ADDs __m512 r_ab2_x_0 = _mm512_sub_ps(r_ab_x_0, sbe_jx_0); __m512 r_ab2_x_1 = _mm512_sub_ps(r_ab_x_1, sbe_jx_1); __m512 r_ab2_y_0 = _mm512_sub_ps(r_ab_y_0, sbe_jy_0); __m512 r_ab2_y_1 = _mm512_sub_ps(r_ab_y_1, sbe_jy_1); - // |r_ab_2| --> needed for rsqrt trick (r_ab - step) + // # 64 MULTs, 32 ADDs __m512 r_ab2_n2_0 = _mm512_fmadd_ps(r_ab2_x_0, r_ab2_x_0, _mm512_mul_ps(r_ab2_y_0, r_ab2_y_0)); __m512 r_ab2_n2_1 = _mm512_fmadd_ps(r_ab2_x_1, r_ab2_x_1, _mm512_mul_ps(r_ab2_y_1, r_ab2_y_1)); - // prevent 0 case --> infinity r_ab2_n2_0 = _mm512_max_ps(r_ab2_n2_0, v_eps_sq); r_ab2_n2_1 = _mm512_max_ps(r_ab2_n2_1, v_eps_sq); - // same as before use rsqrt with 14bit approx - // [1 / |r_ab_2|, 1 / |r_ab_2|, ...] + // # 32 DIVs, 32 SQRTs __m512 inv_r_ab2_n_0 = _mm512_rsqrt14_ps(r_ab2_n2_0); __m512 inv_r_ab2_n_1 = _mm512_rsqrt14_ps(r_ab2_n2_1); - // |r_ab_2_second_distance_vector| * 1 / |r_ab_2_first_distance_vector| + // # 32 MULTs __m512 r_ab2_n_0 = _mm512_mul_ps(r_ab2_n2_0, inv_r_ab2_n_0); __m512 r_ab2_n_1 = _mm512_mul_ps(r_ab2_n2_1, inv_r_ab2_n_1); - // r_sum = |r_ab| + |r_ab - step[j]| --> [w_0, w_1, w_2, ..., w_15] and [w_16, ..., w_31] + // # 32 ADDs __m512 r_sum_0 = _mm512_add_ps(r_ab_n_0, r_ab2_n_0); __m512 r_sum_1 = _mm512_add_ps(r_ab_n_1, r_ab2_n_1); - // 2_b^2 = r_sum^2 - step[j]^2 + // # 32 MULTs, 32 ADDs __m512 two_b_sq_0 = _mm512_fmsub_ps(r_sum_0, r_sum_0, sb_jsq_0); __m512 two_b_sq_1 = _mm512_fmsub_ps(r_sum_1, r_sum_1, sb_jsq_1); - // prevent 0 case two_b_sq_0 = _mm512_max_ps(two_b_sq_0, v_eps_sq); two_b_sq_1 = _mm512_max_ps(two_b_sq_1, v_eps_sq); - // 2_b - // 1 / 2_b^(2*0.5) --> 1 / 2_b + // # 32 DIVs, 32 SQRTs __m512 inv_two_b_0 = _mm512_rsqrt14_ps(two_b_sq_0); __m512 inv_two_b_1 = _mm512_rsqrt14_ps(two_b_sq_1); - // 2_b = 2_b^2 * 1 / 2_b + // # 32 MULTs __m512 two_b_0 = _mm512_mul_ps(two_b_sq_0, inv_two_b_0); __m512 two_b_1 = _mm512_mul_ps(two_b_sq_1, inv_two_b_1); - // --- - - // two_b * -1 / (2*sigma) --> exp + // # 32 MULTs __m512 e_arg_0 = _mm512_mul_ps(two_b_0, v_neg_2s_inv); __m512 e_arg_1 = _mm512_mul_ps(two_b_1, v_neg_2s_inv); - // exp(x) - // when x is small just assume constant value --> faster exp e_arg_0 = _mm512_max_ps(e_arg_0, v_exp_min); e_arg_1 = _mm512_max_ps(e_arg_1, v_exp_min); - // custom fast exponent intrinsic using polynomial approximations and some precomputed constants + // # 512 MULTs, 448 ADDs __m512 e_val_0 = _avx512_exp_ps(e_arg_0); __m512 e_val_1 = _avx512_exp_ps(e_arg_1); - // [−(V0/σ) * e^(−b/σ) * w/(4b), ...] --> scalar + // # 96 MULTs __m512 numer_inv_two_b_0 = _mm512_mul_ps(_mm512_mul_ps(r_sum_0, v_neg_v0_div_2s), _mm512_mul_ps(e_val_0, inv_two_b_0)); __m512 numer_inv_two_b_1 = _mm512_mul_ps(_mm512_mul_ps(r_sum_1, v_neg_v0_div_2s), _mm512_mul_ps(e_val_1, inv_two_b_1)); - // scalar * 1 / |r_ab| + // # 32 MULTs __m512 sm_r_ab_0 = _mm512_mul_ps(numer_inv_two_b_0, inv_r_ab_n_0); __m512 sm_r_ab_1 = _mm512_mul_ps(numer_inv_two_b_1, inv_r_ab_n_1); - // scalar * 1 / |r_ab_2| + // # 32 MULTs __m512 sm_r_ab2_0 = _mm512_mul_ps(numer_inv_two_b_0, inv_r_ab2_n_0); __m512 sm_r_ab2_1 = _mm512_mul_ps(numer_inv_two_b_1, inv_r_ab2_n_1); - // summed force + // # 128 MULTs, 64 ADDs __m512 f_x_0 = _mm512_fmadd_ps(r_ab2_x_0, sm_r_ab2_0, _mm512_mul_ps(r_ab_x_0, sm_r_ab_0)); __m512 f_x_1 = _mm512_fmadd_ps(r_ab2_x_1, sm_r_ab2_1, _mm512_mul_ps(r_ab_x_1, sm_r_ab_1)); __m512 f_y_0 = _mm512_fmadd_ps(r_ab2_y_0, sm_r_ab2_0, _mm512_mul_ps(r_ab_y_0, sm_r_ab_0)); __m512 f_y_1 = _mm512_fmadd_ps(r_ab2_y_1, sm_r_ab2_1, _mm512_mul_ps(r_ab_y_1, sm_r_ab_1)); - // using masking to perform --> field of view formula - // if (e_dot_f >= 0.0 || e_dot_f_sq <= rhs) - // return dt_neg; - // else - // return c_neg_times_dt; - // + // # 64 MULTs, 32 ADDs __m512 f_norm_sq_0 = _mm512_fmadd_ps(f_x_0, f_x_0, _mm512_mul_ps(f_y_0, f_y_0)); __m512 f_norm_sq_1 = _mm512_fmadd_ps(f_x_1, f_x_1, _mm512_mul_ps(f_y_1, f_y_1)); + // # 32 MULTs __m512 rhs_0 = _mm512_mul_ps(f_norm_sq_0, v_cos_phi_sq); __m512 rhs_1 = _mm512_mul_ps(f_norm_sq_1, v_cos_phi_sq); + // # 64 MULTs, 32 ADDs __m512 e_dot_f_0 = _mm512_fmadd_ps(eix, f_x_0, _mm512_mul_ps(eiy, f_y_0)); __m512 e_dot_f_1 = _mm512_fmadd_ps(eix, f_x_1, _mm512_mul_ps(eiy, f_y_1)); + // # 32 MULTs __m512 e_dot_f_sq_0 = _mm512_mul_ps(e_dot_f_0, e_dot_f_0); __m512 e_dot_f_sq_1 = _mm512_mul_ps(e_dot_f_1, e_dot_f_1); - // e_i * f < 0 --> behind __mmask16 c1_0 = _mm512_cmp_ps_mask(e_dot_f_0, v_zero, _CMP_LT_OQ); __mmask16 c1_1 = _mm512_cmp_ps_mask(e_dot_f_1, v_zero, _CMP_LT_OQ); - // (e_i * f)^2 > cos(phi) --> out of view __mmask16 c2_0 = _mm512_cmp_ps_mask(e_dot_f_sq_0, rhs_0, _CMP_GT_OQ); __mmask16 c2_1 = _mm512_cmp_ps_mask(e_dot_f_sq_1, rhs_1, _CMP_GT_OQ); - // get the case (in field of view or not) - // 1 = reduced weight, 0 = regular __mmask16 cond_0 = c1_0 & c2_0; __mmask16 cond_1 = c1_1 & c2_1; - // apply the correct weight __m512 w_val_0 = _mm512_mask_blend_ps(cond_0, v_dt_neg, v_c_neg_dt); __m512 w_val_1 = _mm512_mask_blend_ps(cond_1, v_dt_neg, v_c_neg_dt); - // take care of i == j case by zeroing it out - // see active_0 and active_1 at the beginning of this loop - // [f.x or 0, ...] __m512 f_x_safe_0 = _mm512_maskz_mov_ps(active_0, f_x_0); __m512 f_x_safe_1 = _mm512_maskz_mov_ps(active_1, f_x_1); __m512 f_y_safe_0 = _mm512_maskz_mov_ps(active_0, f_y_0); __m512 f_y_safe_1 = _mm512_maskz_mov_ps(active_1, f_y_1); - // accumulate force with weight - // force_P_total += weight * force_P_other + // # 64 MULTs, 64 ADDs acc_x_0 = _mm512_fmadd_ps(f_x_safe_0, w_val_0, acc_x_0); acc_x_1 = _mm512_fmadd_ps(f_x_safe_1, w_val_1, acc_x_1); acc_y_0 = _mm512_fmadd_ps(f_y_safe_0, w_val_0, acc_y_0); acc_y_1 = _mm512_fmadd_ps(f_y_safe_1, w_val_1, acc_y_1); } - // scalar force accumulator + // # 64 ADDs f_alpha_dt_x += _mm512_reduce_add_ps(_mm512_add_ps(acc_x_0, acc_x_1)); f_alpha_dt_y += _mm512_reduce_add_ps(_mm512_add_ps(acc_y_0, acc_y_1)); - // force between pedestrian and obstacles - // no optimizations, because force between pedestrian is the bottleneck of the computation for (int k = 0; k < board.n_obstacles; k++) { + + // # 2 ADDs float v1_x = pos_x[i] - board.obstacles[k].start_x; float v1_y = pos_y[i] - board.obstacles[k].start_y; float v2_x = board.obstacles[k].obstacle_v_x; float v2_y = board.obstacles[k].obstacle_v_y; + // # 3 MULTs, 1 ADD float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; if (projection < 0.0f) @@ -488,12 +480,15 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c else if (projection > 1.0f) projection = 1.0f; + // # 4 ADDs, 2 MULTs float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); + // # 1 SQRT, 2 MULTs, 1 ADD float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; + // # 4 MULTs, 1 EXP, 1 DIV float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; float f_alpha_B_neg_x = r_aB_x * scalar_mult; float f_alpha_B_neg_y = r_aB_y * scalar_mult; @@ -504,21 +499,21 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c if (e_dot_f < cos_phi) w_val = c_neg_times_dt; + // # 2 MULTS float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; + // # 2 ADDs f_alpha_dt_x += f_alpha_B_dt_x; f_alpha_dt_y += f_alpha_B_dt_y; } + // # 2 ADDs w_x[i] += f_alpha_dt_x; w_y[i] += f_alpha_dt_y; } - // update each pedestrian for (int i = 0; i < n_p_pad; i += 16) { - // load 16 pedestrians per iteration with their data - // SoA in vectors __m512 w_x_i_vec = _mm512_loadu_ps(&w_x[i]); __m512 w_y_i_vec = _mm512_loadu_ps(&w_y[i]); __m512 v_max_i_vec = _mm512_loadu_ps(&v_max[i]); @@ -530,20 +525,27 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512i color_i_vec = _mm512_loadu_si512((__m512i *)&color[i]); + // # 32 MULTs, 16 ADDs __m512 w_norm_sq = _mm512_fmadd_ps(w_x_i_vec, w_x_i_vec, _mm512_mul_ps(w_y_i_vec, w_y_i_vec)); + + // # 16 SQRTs, 16 DIVs __m512 w_norm_inv = _mm512_rsqrt14_ps(w_norm_sq); + + // # 16 MULTs __m512 correction_factor = _mm512_min_ps(_mm512_set1_ps(1.0f), _mm512_mul_ps(v_max_i_vec, w_norm_inv)); + // # 32 MULTs __m512 curr_vel_x_i_vec = _mm512_mul_ps(w_x_i_vec, correction_factor); __m512 curr_vel_y_i_vec = _mm512_mul_ps(w_y_i_vec, correction_factor); __m512 dt_vec = _mm512_set1_ps(dt); + + // # 32 MULTs, 32 ADDs pos_x_i_vec = _mm512_fmadd_ps(curr_vel_x_i_vec, dt_vec, pos_x_i_vec); pos_y_i_vec = _mm512_fmadd_ps(curr_vel_y_i_vec, dt_vec, pos_y_i_vec); - // differentiate whether pedestrian came from left or right using masking __mmask16 cond_1_left = _mm512_cmpeq_epi32_mask(color_i_vec, _mm512_setzero_si512()); - __mmask16 cond_1_right = _mm512_cmp_ps_mask(pos_x_i_vec, _mm512_set1_ps(BOARD_LENGTH - 1.5f), _CMP_GT_OQ); + __mmask16 cond_1_right = _mm512_cmp_ps_mask(pos_x_i_vec, _mm512_set1_ps(BOARD_LENGTH_MINUS_ONE_POINT_FIVE), _CMP_GT_OQ); __mmask16 cond_1 = cond_1_left & cond_1_right; pos_x_i_vec = _mm512_mask_blend_ps(cond_1, pos_x_i_vec, _mm512_set1_ps(1.0f)); @@ -557,7 +559,7 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __mmask16 cond_2_right = _mm512_cmp_ps_mask(pos_x_i_vec, _mm512_set1_ps(1.5f), _CMP_LT_OQ); __mmask16 cond_2 = cond_2_left & cond_2_right; - pos_x_i_vec = _mm512_mask_blend_ps(cond_2, pos_x_i_vec, _mm512_set1_ps(BOARD_LENGTH - 1.0f)); + pos_x_i_vec = _mm512_mask_blend_ps(cond_2, pos_x_i_vec, _mm512_set1_ps(BOARD_LENGTH_MINUS_ONE)); destination_y_i_vec = _mm512_mask_blend_ps(cond_2, destination_y_i_vec, pos_y_i_vec); __m512 neg_desired_v0 = _mm512_xor_ps(desired_v0_i_vec, _mm512_set1_ps(-0.0f)); w_x_i_vec = _mm512_mask_blend_ps(cond_2, w_x_i_vec, neg_desired_v0); @@ -568,18 +570,29 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c pos_y_i_vec = _mm512_max_ps(pos_y_i_vec, _mm512_set1_ps(WALL_EPS)); pos_y_i_vec = _mm512_min_ps(pos_y_i_vec, _mm512_set1_ps(BOARD_WIDTH_MINUS_WALL_EPS)); + // # 32 ADDs __m512 ex_vec = _mm512_sub_ps(destination_x_i_vec, pos_x_i_vec); __m512 ey_vec = _mm512_sub_ps(destination_y_i_vec, pos_y_i_vec); + + // # 32 MULTs, 16 ADDs __m512 e_norm_sq = _mm512_fmadd_ps(ex_vec, ex_vec, _mm512_mul_ps(ey_vec, ey_vec)); + + // # 16 SQRTs, 16 DIVs __m512 e_norm_inv = _mm512_rsqrt14_ps(e_norm_sq); + + // # 32 MULTs __m512 e_x_i_vec = _mm512_mul_ps(ex_vec, e_norm_inv); __m512 e_y_i_vec = _mm512_mul_ps(ey_vec, e_norm_inv); + // # 32 MULTs, 16 ADDs __m512 vel_norm_sq = _mm512_fmadd_ps(curr_vel_x_i_vec, curr_vel_x_i_vec, _mm512_mul_ps(curr_vel_y_i_vec, curr_vel_y_i_vec)); + + // # 16 MULTs __m512 sb_sq_i_vec = _mm512_mul_ps(vel_norm_sq, _mm512_set1_ps(delta_t_sq)); + + // # 16 SQRTs __m512 vel_norm_dt = _mm512_sqrt_ps(sb_sq_i_vec); - // write the data _mm512_storeu_ps(&curr_vel_x[i], curr_vel_x_i_vec); _mm512_storeu_ps(&curr_vel_y[i], curr_vel_y_i_vec); _mm512_storeu_ps(&w_x[i], w_x_i_vec); @@ -590,6 +603,8 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c _mm512_storeu_ps(&e_y[i], e_y_i_vec); _mm512_storeu_ps(&destination_y[i], destination_y_i_vec); _mm512_storeu_ps(&sb_sq[i], sb_sq_i_vec); + + // # 32 MULTs _mm512_storeu_ps(&sb_e_x[i], _mm512_mul_ps(e_x_i_vec, vel_norm_dt)); _mm512_storeu_ps(&sb_e_y[i], _mm512_mul_ps(e_y_i_vec, vel_norm_dt)); } diff --git a/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_expfix.cpp b/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_expfix.cpp deleted file mode 100644 index a9bbd5c..0000000 --- a/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_expfix.cpp +++ /dev/null @@ -1,632 +0,0 @@ -// # Changes: Added more correction rounds to _avx512_exp_ps to do 30 flops per scalar -// # Predecessor: variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt.cpp - -#include "../headers/board_reduced_float.hpp" -#include "../headers/constants_float.hpp" -#include "../headers/pedestrian_reduced_float.hpp" - -#include - -#include -#include - -#define SEED 42 -#define BOARD_WIDTH 10.0f -#define BOARD_LENGTH 50.0f -#define BOARD_LENGTH_MINUS_ONE BOARD_LENGTH - 1.0f -#define BOARD_LENGTH_MINUS_ONE_POINT_FIVE BOARD_LENGTH - 1.5f -#define WALL_EPS 1e-3f -#define BOARD_WIDTH_MINUS_WALL_EPS 9.999f - -#ifndef RANDOM_SEED -#define RANDOM_SEED 0 -#endif - -#ifndef BENCHMARK -#define BENCHMARK 0 -#endif - -using namespace std; -alignas(64) vector pos_x, pos_y; -alignas(64) vector sb_sq; -alignas(64) vector sb_e_x, sb_e_y; -alignas(64) vector e_x, e_y; -alignas(64) vector curr_vel_x, curr_vel_y; -alignas(64) vector w_x, w_y; -alignas(64) vector desired_v0; -alignas(64) vector v_max; -alignas(64) vector destination_x, destination_y; -alignas(64) vector color; - -Pedestrian *init_pedestrians(int n_p) { -#if RANDOM_SEED - random_device rd; - mt19937 gen(rd()); -#else - mt19937 gen(SEED); -#endif - - normal_distribution velocity_gen(v0_mean, v0_std_dev); - uniform_real_distribution y_gen(0.3, BOARD_WIDTH - 0.3); - uniform_real_distribution x_gen_left(2.0, BOARD_LENGTH / 2.0); - uniform_real_distribution x_gen_right(BOARD_LENGTH / 2.0, BOARD_LENGTH - 2.0); - - const int n_p_pad = (n_p + 31) & ~31; - - pos_x.resize(n_p_pad); - pos_y.resize(n_p_pad); - sb_sq.resize(n_p_pad); - sb_e_x.resize(n_p_pad); - sb_e_y.resize(n_p_pad); - e_x.resize(n_p_pad); - e_y.resize(n_p_pad); - curr_vel_x.resize(n_p_pad); - curr_vel_y.resize(n_p_pad); - w_x.resize(n_p_pad); - w_y.resize(n_p_pad); - desired_v0.resize(n_p_pad); - v_max.resize(n_p_pad); - destination_x.resize(n_p_pad); - destination_y.resize(n_p_pad); - color.resize(n_p_pad); - - int n_p_half = n_p / 2; - - for (int i = 0; i < n_p_half; i++) { - float x = x_gen_left(gen); - float y = y_gen(gen); - - float dest_x = BOARD_LENGTH + 30.0f; - float dest_y = y; - - float init_e_x = dest_x - x; - float init_e_y = dest_y - y; - float init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - float init_e_unit_x = init_e_x / init_e_norm; - float init_e_unit_y = init_e_y / init_e_norm; - - float d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1f); - - float v_m = 1.3f * d_v0; - - color[i] = 0; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - w_x[i] = 0.0f; - w_y[i] = 0.0f; - curr_vel_x[i] = 0.0f; - curr_vel_y[i] = 0.0f; - sb_sq[i] = 0.0f; - sb_e_x[i] = 0.0f; - sb_e_y[i] = 0.0f; - } - - for (int i = n_p_half; i < n_p; i++) { - float x = x_gen_right(gen); - float y = y_gen(gen); - - float dest_x = -30.0f; - float dest_y = y; - - float init_e_x = dest_x - x; - float init_e_y = dest_y - y; - float init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - float init_e_unit_x = init_e_x / init_e_norm; - float init_e_unit_y = init_e_y / init_e_norm; - - float d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1f); - - float v_m = 1.3f * d_v0; - - color[i] = 1; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - w_x[i] = 0.0f; - w_y[i] = 0.0f; - curr_vel_x[i] = 0.0f; - curr_vel_y[i] = 0.0f; - sb_sq[i] = 0.0f; - sb_e_x[i] = 0.0f; - sb_e_y[i] = 0.0f; - } - - for (int j = n_p; j < n_p_pad; j++) { - pos_x[j] = 1e9f; - pos_y[j] = 1e9f; - sb_sq[j] = 0.0f; - sb_e_x[j] = 0.0f; - sb_e_y[j] = 0.0f; - } - return nullptr; -} - -Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } - -// # 256 MULTs, 224 ADDs -static inline __m512 _avx512_exp_ps(__m512 x) { - - const __m512 log2e = _mm512_set1_ps(1.4426950408889634f); - - // # 16 MULTs - __m512 nf = _mm512_roundscale_ps(_mm512_mul_ps(x, log2e), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); - - const __m512 ln2 = _mm512_set1_ps(0.6931471805599453f); - - // # 16 MULTs, 16 ADDs - __m512 r = _mm512_fnmadd_ps(nf, ln2, x); - - const __m512 c13 = _mm512_set1_ps(c13_scalar); - const __m512 c12 = _mm512_set1_ps(c12_scalar); - const __m512 c11 = _mm512_set1_ps(c11_scalar); - const __m512 c10 = _mm512_set1_ps(c10_scalar); - const __m512 c9 = _mm512_set1_ps(c9_scalar); - const __m512 c8 = _mm512_set1_ps(c8_scalar); - const __m512 c7 = _mm512_set1_ps(c7_scalar); - const __m512 c6 = _mm512_set1_ps(c6_scalar); - const __m512 c5 = _mm512_set1_ps(c5_scalar); - const __m512 c4 = _mm512_set1_ps(c4_scalar); - const __m512 c3 = _mm512_set1_ps(c3_scalar); - const __m512 c2 = _mm512_set1_ps(c2_scalar); - const __m512 c1 = _mm512_set1_ps(c1_scalar); - const __m512 c0 = _mm512_set1_ps(c0_scalar); - - __m512 p = c13; - - // # 13 * (16 MULTs, 16 ADDs) - // # = 208 MULTs, 208 ADDs - p = _mm512_fmadd_ps(p, r, c12); - p = _mm512_fmadd_ps(p, r, c11); - p = _mm512_fmadd_ps(p, r, c10); - p = _mm512_fmadd_ps(p, r, c9); - p = _mm512_fmadd_ps(p, r, c8); - p = _mm512_fmadd_ps(p, r, c7); - p = _mm512_fmadd_ps(p, r, c6); - p = _mm512_fmadd_ps(p, r, c5); - p = _mm512_fmadd_ps(p, r, c4); - p = _mm512_fmadd_ps(p, r, c3); - p = _mm512_fmadd_ps(p, r, c2); - p = _mm512_fmadd_ps(p, r, c1); - p = _mm512_fmadd_ps(p, r, c0); - - __m512i ni = _mm512_cvtps_epi32(nf); - __m512i biased = _mm512_add_epi32(ni, _mm512_set1_epi32(127)); - __m512i scaled = _mm512_slli_epi32(biased, 23); - __m512 pow2n = _mm512_castsi512_ps(scaled); - - // # 16 MULTs - return _mm512_mul_ps(p, pow2n); -} - -int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { - (void)pedestrians; -#if BENCHMARK - (void)dump_path; -#endif - -#if !BENCHMARK - const int dump_interval = 1; - vector> samples; - - if (dump_path) { - samples.reserve(static_cast(n_iter / dump_interval + 1) * n_p); - for (int i = 0; i < n_p; i++) { - samples.emplace_back(0, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } - } -#endif - - const int n_p_pad = (n_p + 31) & ~31; - - alignas(64) const float lane_offset_arr[16] = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f, 13.0f, 14.0f, 15.0f}; - const __m512 lane_off = _mm512_load_ps(lane_offset_arr); - - const __m512 v_neg_v0_div_2s = _mm512_set1_ps(NEG_V0_AB_div_TWO_SIGMA); - const __m512 v_neg_2s_inv = _mm512_set1_ps(NEG_TWO_SIGMA_INV); - const __m512 v_cos_phi_sq = _mm512_set1_ps(cos_phi_sq); - const __m512 v_dt_neg = _mm512_set1_ps(dt_neg); - const __m512 v_c_neg_dt = _mm512_set1_ps(c_neg_times_dt); - const __m512 v_zero = _mm512_setzero_ps(); - const __m512 v_one = _mm512_set1_ps(1.0f); - const __m512 v_eps = _mm512_set1_ps(EPS); - const __m512 v_eps_sq = _mm512_set1_ps(EPS_SQ); - const __m512 v_np = _mm512_set1_ps((float)n_p); - const __m512 v_exp_min = _mm512_set1_ps(-87.0f); - - // # ADDs: n_iter * ( - // # n_p * 68 + - // # n_p * n_p_pad * 29 + - // # n_p * board.n_obstacles * 10 + - // # n_p_pad * 7 - // # ) - - // # MULTs: n_iter * ( - // # n_p * 4 + - // # n_p * n_p_pad * 42 + - // # n_p * board.n_obstacles * 13 + - // # n_p_pad * 16 - // # ) - - // # DIVs: n_iter * ( - // # n_p * n_p_pad * 3 + - // # n_p * board.n_obstacles + - // # n_p_pad * 2 - // # ) - - // # SQRTs: n_iter * ( - // # n_p * n_p_pad * 3 + - // # n_p * board.n_obstacles + - // # n_p_pad * 3 - // # ) - - // # EXPs: n_iter * n_p * board.n_obstacles - - for (int t = 0; t < n_iter; t++) { - for (int i = 0; i < n_p; i++) { - - // # 2 MULTs - float desired_velocity_x = e_x[i] * desired_v0[i]; - float desired_velocity_y = e_y[i] * desired_v0[i]; - - // # 2 ADDs, 2 MULTs - float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; - float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; - - const __m512 pix = _mm512_set1_ps(pos_x[i]); - const __m512 piy = _mm512_set1_ps(pos_y[i]); - const __m512 eix = _mm512_set1_ps(e_x[i]); - const __m512 eiy = _mm512_set1_ps(e_y[i]); - const __m512 v_i = _mm512_set1_ps((float)i); - - __m512 acc_x_0 = _mm512_setzero_ps(); - __m512 acc_y_0 = _mm512_setzero_ps(); - __m512 acc_x_1 = _mm512_setzero_ps(); - __m512 acc_y_1 = _mm512_setzero_ps(); - - for (int j = 0; j < n_p_pad; j += 32) { - - // # 32 ADDs - __m512 j_idx_0 = _mm512_add_ps(_mm512_set1_ps((float)j), lane_off); - __m512 j_idx_1 = _mm512_add_ps(_mm512_set1_ps((float)j + 16), lane_off); - - __mmask16 m_neq_i_0 = _mm512_cmp_ps_mask(j_idx_0, v_i, _CMP_NEQ_OQ); - __mmask16 m_neq_i_1 = _mm512_cmp_ps_mask(j_idx_1, v_i, _CMP_NEQ_OQ); - - __mmask16 m_in_range_0 = _mm512_cmp_ps_mask(j_idx_0, v_np, _CMP_LT_OQ); - __mmask16 m_in_range_1 = _mm512_cmp_ps_mask(j_idx_1, v_np, _CMP_LT_OQ); - - __mmask16 active_0 = m_neq_i_0 & m_in_range_0; - __mmask16 active_1 = m_neq_i_1 & m_in_range_1; - - __m512 pjx_0 = _mm512_loadu_ps(&pos_x[j]); - __m512 pjx_1 = _mm512_loadu_ps(&pos_x[j + 16]); - __m512 pjy_0 = _mm512_loadu_ps(&pos_y[j]); - __m512 pjy_1 = _mm512_loadu_ps(&pos_y[j + 16]); - - __m512 sbe_jx_0 = _mm512_loadu_ps(&sb_e_x[j]); - __m512 sbe_jx_1 = _mm512_loadu_ps(&sb_e_x[j + 16]); - __m512 sbe_jy_0 = _mm512_loadu_ps(&sb_e_y[j]); - __m512 sbe_jy_1 = _mm512_loadu_ps(&sb_e_y[j + 16]); - - __m512 sb_jsq_0 = _mm512_loadu_ps(&sb_sq[j]); - __m512 sb_jsq_1 = _mm512_loadu_ps(&sb_sq[j + 16]); - - // # 64 ADDs - __m512 r_ab_x_0 = _mm512_sub_ps(pix, pjx_0); - __m512 r_ab_x_1 = _mm512_sub_ps(pix, pjx_1); - __m512 r_ab_y_0 = _mm512_sub_ps(piy, pjy_0); - __m512 r_ab_y_1 = _mm512_sub_ps(piy, pjy_1); - - // # 64 MULTs, 32 ADDs - __m512 r_ab_n2_0 = _mm512_fmadd_ps(r_ab_x_0, r_ab_x_0, _mm512_mul_ps(r_ab_y_0, r_ab_y_0)); - __m512 r_ab_n2_1 = _mm512_fmadd_ps(r_ab_x_1, r_ab_x_1, _mm512_mul_ps(r_ab_y_1, r_ab_y_1)); - - r_ab_n2_0 = _mm512_max_ps(r_ab_n2_0, v_eps_sq); - r_ab_n2_1 = _mm512_max_ps(r_ab_n2_1, v_eps_sq); - - // # 32 DIVs, 32 SQRTs - __m512 inv_r_ab_n_0 = _mm512_rsqrt14_ps(r_ab_n2_0); - __m512 inv_r_ab_n_1 = _mm512_rsqrt14_ps(r_ab_n2_1); - - // # 32 MULTs - __m512 r_ab_n_0 = _mm512_mul_ps(r_ab_n2_0, inv_r_ab_n_0); - __m512 r_ab_n_1 = _mm512_mul_ps(r_ab_n2_1, inv_r_ab_n_1); - - // # 64 ADDs - __m512 r_ab2_x_0 = _mm512_sub_ps(r_ab_x_0, sbe_jx_0); - __m512 r_ab2_x_1 = _mm512_sub_ps(r_ab_x_1, sbe_jx_1); - __m512 r_ab2_y_0 = _mm512_sub_ps(r_ab_y_0, sbe_jy_0); - __m512 r_ab2_y_1 = _mm512_sub_ps(r_ab_y_1, sbe_jy_1); - - // # 64 MULTs, 32 ADDs - __m512 r_ab2_n2_0 = _mm512_fmadd_ps(r_ab2_x_0, r_ab2_x_0, _mm512_mul_ps(r_ab2_y_0, r_ab2_y_0)); - __m512 r_ab2_n2_1 = _mm512_fmadd_ps(r_ab2_x_1, r_ab2_x_1, _mm512_mul_ps(r_ab2_y_1, r_ab2_y_1)); - - r_ab2_n2_0 = _mm512_max_ps(r_ab2_n2_0, v_eps_sq); - r_ab2_n2_1 = _mm512_max_ps(r_ab2_n2_1, v_eps_sq); - - // # 32 DIVs, 32 SQRTs - __m512 inv_r_ab2_n_0 = _mm512_rsqrt14_ps(r_ab2_n2_0); - __m512 inv_r_ab2_n_1 = _mm512_rsqrt14_ps(r_ab2_n2_1); - - // # 32 MULTs - __m512 r_ab2_n_0 = _mm512_mul_ps(r_ab2_n2_0, inv_r_ab2_n_0); - __m512 r_ab2_n_1 = _mm512_mul_ps(r_ab2_n2_1, inv_r_ab2_n_1); - - // # 32 ADDs - __m512 r_sum_0 = _mm512_add_ps(r_ab_n_0, r_ab2_n_0); - __m512 r_sum_1 = _mm512_add_ps(r_ab_n_1, r_ab2_n_1); - - // # 32 MULTs, 32 ADDs - __m512 two_b_sq_0 = _mm512_fmsub_ps(r_sum_0, r_sum_0, sb_jsq_0); - __m512 two_b_sq_1 = _mm512_fmsub_ps(r_sum_1, r_sum_1, sb_jsq_1); - - two_b_sq_0 = _mm512_max_ps(two_b_sq_0, v_eps_sq); - two_b_sq_1 = _mm512_max_ps(two_b_sq_1, v_eps_sq); - - // # 32 DIVs, 32 SQRTs - __m512 inv_two_b_0 = _mm512_rsqrt14_ps(two_b_sq_0); - __m512 inv_two_b_1 = _mm512_rsqrt14_ps(two_b_sq_1); - - // # 32 MULTs - __m512 two_b_0 = _mm512_mul_ps(two_b_sq_0, inv_two_b_0); - __m512 two_b_1 = _mm512_mul_ps(two_b_sq_1, inv_two_b_1); - - // # 32 MULTs - __m512 e_arg_0 = _mm512_mul_ps(two_b_0, v_neg_2s_inv); - __m512 e_arg_1 = _mm512_mul_ps(two_b_1, v_neg_2s_inv); - - e_arg_0 = _mm512_max_ps(e_arg_0, v_exp_min); - e_arg_1 = _mm512_max_ps(e_arg_1, v_exp_min); - - // # 512 MULTs, 448 ADDs - __m512 e_val_0 = _avx512_exp_ps(e_arg_0); - __m512 e_val_1 = _avx512_exp_ps(e_arg_1); - - // # 96 MULTs - __m512 numer_inv_two_b_0 = _mm512_mul_ps(_mm512_mul_ps(r_sum_0, v_neg_v0_div_2s), _mm512_mul_ps(e_val_0, inv_two_b_0)); - __m512 numer_inv_two_b_1 = _mm512_mul_ps(_mm512_mul_ps(r_sum_1, v_neg_v0_div_2s), _mm512_mul_ps(e_val_1, inv_two_b_1)); - - // # 32 MULTs - __m512 sm_r_ab_0 = _mm512_mul_ps(numer_inv_two_b_0, inv_r_ab_n_0); - __m512 sm_r_ab_1 = _mm512_mul_ps(numer_inv_two_b_1, inv_r_ab_n_1); - - // # 32 MULTs - __m512 sm_r_ab2_0 = _mm512_mul_ps(numer_inv_two_b_0, inv_r_ab2_n_0); - __m512 sm_r_ab2_1 = _mm512_mul_ps(numer_inv_two_b_1, inv_r_ab2_n_1); - - // # 128 MULTs, 64 ADDs - __m512 f_x_0 = _mm512_fmadd_ps(r_ab2_x_0, sm_r_ab2_0, _mm512_mul_ps(r_ab_x_0, sm_r_ab_0)); - __m512 f_x_1 = _mm512_fmadd_ps(r_ab2_x_1, sm_r_ab2_1, _mm512_mul_ps(r_ab_x_1, sm_r_ab_1)); - __m512 f_y_0 = _mm512_fmadd_ps(r_ab2_y_0, sm_r_ab2_0, _mm512_mul_ps(r_ab_y_0, sm_r_ab_0)); - __m512 f_y_1 = _mm512_fmadd_ps(r_ab2_y_1, sm_r_ab2_1, _mm512_mul_ps(r_ab_y_1, sm_r_ab_1)); - - // # 64 MULTs, 32 ADDs - __m512 f_norm_sq_0 = _mm512_fmadd_ps(f_x_0, f_x_0, _mm512_mul_ps(f_y_0, f_y_0)); - __m512 f_norm_sq_1 = _mm512_fmadd_ps(f_x_1, f_x_1, _mm512_mul_ps(f_y_1, f_y_1)); - - // # 32 MULTs - __m512 rhs_0 = _mm512_mul_ps(f_norm_sq_0, v_cos_phi_sq); - __m512 rhs_1 = _mm512_mul_ps(f_norm_sq_1, v_cos_phi_sq); - - // # 64 MULTs, 32 ADDs - __m512 e_dot_f_0 = _mm512_fmadd_ps(eix, f_x_0, _mm512_mul_ps(eiy, f_y_0)); - __m512 e_dot_f_1 = _mm512_fmadd_ps(eix, f_x_1, _mm512_mul_ps(eiy, f_y_1)); - - // # 32 MULTs - __m512 e_dot_f_sq_0 = _mm512_mul_ps(e_dot_f_0, e_dot_f_0); - __m512 e_dot_f_sq_1 = _mm512_mul_ps(e_dot_f_1, e_dot_f_1); - - __mmask16 c1_0 = _mm512_cmp_ps_mask(e_dot_f_0, v_zero, _CMP_LT_OQ); - __mmask16 c1_1 = _mm512_cmp_ps_mask(e_dot_f_1, v_zero, _CMP_LT_OQ); - - __mmask16 c2_0 = _mm512_cmp_ps_mask(e_dot_f_sq_0, rhs_0, _CMP_GT_OQ); - __mmask16 c2_1 = _mm512_cmp_ps_mask(e_dot_f_sq_1, rhs_1, _CMP_GT_OQ); - - __mmask16 cond_0 = c1_0 & c2_0; - __mmask16 cond_1 = c1_1 & c2_1; - - __m512 w_val_0 = _mm512_mask_blend_ps(cond_0, v_dt_neg, v_c_neg_dt); - __m512 w_val_1 = _mm512_mask_blend_ps(cond_1, v_dt_neg, v_c_neg_dt); - - __m512 f_x_safe_0 = _mm512_maskz_mov_ps(active_0, f_x_0); - __m512 f_x_safe_1 = _mm512_maskz_mov_ps(active_1, f_x_1); - __m512 f_y_safe_0 = _mm512_maskz_mov_ps(active_0, f_y_0); - __m512 f_y_safe_1 = _mm512_maskz_mov_ps(active_1, f_y_1); - - // # 64 MULTs, 64 ADDs - acc_x_0 = _mm512_fmadd_ps(f_x_safe_0, w_val_0, acc_x_0); - acc_x_1 = _mm512_fmadd_ps(f_x_safe_1, w_val_1, acc_x_1); - acc_y_0 = _mm512_fmadd_ps(f_y_safe_0, w_val_0, acc_y_0); - acc_y_1 = _mm512_fmadd_ps(f_y_safe_1, w_val_1, acc_y_1); - } - - // # 64 ADDs - f_alpha_dt_x += _mm512_reduce_add_ps(_mm512_add_ps(acc_x_0, acc_x_1)); - f_alpha_dt_y += _mm512_reduce_add_ps(_mm512_add_ps(acc_y_0, acc_y_1)); - - for (int k = 0; k < board.n_obstacles; k++) { - - // # 2 ADDs - float v1_x = pos_x[i] - board.obstacles[k].start_x; - float v1_y = pos_y[i] - board.obstacles[k].start_y; - float v2_x = board.obstacles[k].obstacle_v_x; - float v2_y = board.obstacles[k].obstacle_v_y; - - // # 3 MULTs, 1 ADD - float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; - - if (projection < 0.0f) - projection = 0.0f; - else if (projection > 1.0f) - projection = 1.0f; - - // # 4 ADDs, 2 MULTs - float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); - float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); - - // # 1 SQRT, 2 MULTs, 1 ADD - float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); - r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; - - // # 4 MULTs, 1 EXP, 1 DIV - float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; - float f_alpha_B_neg_x = r_aB_x * scalar_mult; - float f_alpha_B_neg_y = r_aB_y * scalar_mult; - - float w_val = dt_neg; - float e_dot_f = (f_alpha_B_neg_y == 0) ? 0 : (f_alpha_B_neg_y < 0 ? -e_y[i] : e_y[i]); - - if (e_dot_f < cos_phi) - w_val = c_neg_times_dt; - - // # 2 MULTS - float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; - float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; - - // # 2 ADDs - f_alpha_dt_x += f_alpha_B_dt_x; - f_alpha_dt_y += f_alpha_B_dt_y; - } - - // # 2 ADDs - w_x[i] += f_alpha_dt_x; - w_y[i] += f_alpha_dt_y; - } - - for (int i = 0; i < n_p_pad; i += 16) { - __m512 w_x_i_vec = _mm512_loadu_ps(&w_x[i]); - __m512 w_y_i_vec = _mm512_loadu_ps(&w_y[i]); - __m512 v_max_i_vec = _mm512_loadu_ps(&v_max[i]); - __m512 pos_x_i_vec = _mm512_loadu_ps(&pos_x[i]); - __m512 pos_y_i_vec = _mm512_loadu_ps(&pos_y[i]); - __m512 destination_y_i_vec = _mm512_loadu_ps(&destination_y[i]); - __m512 destination_x_i_vec = _mm512_loadu_ps(&destination_x[i]); - __m512 desired_v0_i_vec = _mm512_loadu_ps(&desired_v0[i]); - - __m512i color_i_vec = _mm512_loadu_si512((__m512i *)&color[i]); - - // # 32 MULTs, 16 ADDs - __m512 w_norm_sq = _mm512_fmadd_ps(w_x_i_vec, w_x_i_vec, _mm512_mul_ps(w_y_i_vec, w_y_i_vec)); - - // # 16 SQRTs, 16 DIVs - __m512 w_norm_inv = _mm512_rsqrt14_ps(w_norm_sq); - - // # 16 MULTs - __m512 correction_factor = _mm512_min_ps(_mm512_set1_ps(1.0f), _mm512_mul_ps(v_max_i_vec, w_norm_inv)); - - // # 32 MULTs - __m512 curr_vel_x_i_vec = _mm512_mul_ps(w_x_i_vec, correction_factor); - __m512 curr_vel_y_i_vec = _mm512_mul_ps(w_y_i_vec, correction_factor); - - __m512 dt_vec = _mm512_set1_ps(dt); - - // # 32 MULTs, 32 ADDs - pos_x_i_vec = _mm512_fmadd_ps(curr_vel_x_i_vec, dt_vec, pos_x_i_vec); - pos_y_i_vec = _mm512_fmadd_ps(curr_vel_y_i_vec, dt_vec, pos_y_i_vec); - - __mmask16 cond_1_left = _mm512_cmpeq_epi32_mask(color_i_vec, _mm512_setzero_si512()); - __mmask16 cond_1_right = _mm512_cmp_ps_mask(pos_x_i_vec, _mm512_set1_ps(BOARD_LENGTH_MINUS_ONE_POINT_FIVE), _CMP_GT_OQ); - __mmask16 cond_1 = cond_1_left & cond_1_right; - - pos_x_i_vec = _mm512_mask_blend_ps(cond_1, pos_x_i_vec, _mm512_set1_ps(1.0f)); - destination_y_i_vec = _mm512_mask_blend_ps(cond_1, destination_y_i_vec, pos_y_i_vec); - w_x_i_vec = _mm512_mask_blend_ps(cond_1, w_x_i_vec, desired_v0_i_vec); - w_y_i_vec = _mm512_mask_blend_ps(cond_1, w_y_i_vec, _mm512_setzero_ps()); - curr_vel_x_i_vec = _mm512_mask_blend_ps(cond_1, curr_vel_x_i_vec, w_x_i_vec); - curr_vel_y_i_vec = _mm512_mask_blend_ps(cond_1, curr_vel_y_i_vec, w_y_i_vec); - - __mmask16 cond_2_left = _mm512_cmpeq_epi32_mask(color_i_vec, _mm512_set1_epi32(1)); - __mmask16 cond_2_right = _mm512_cmp_ps_mask(pos_x_i_vec, _mm512_set1_ps(1.5f), _CMP_LT_OQ); - __mmask16 cond_2 = cond_2_left & cond_2_right; - - pos_x_i_vec = _mm512_mask_blend_ps(cond_2, pos_x_i_vec, _mm512_set1_ps(BOARD_LENGTH_MINUS_ONE)); - destination_y_i_vec = _mm512_mask_blend_ps(cond_2, destination_y_i_vec, pos_y_i_vec); - __m512 neg_desired_v0 = _mm512_xor_ps(desired_v0_i_vec, _mm512_set1_ps(-0.0f)); - w_x_i_vec = _mm512_mask_blend_ps(cond_2, w_x_i_vec, neg_desired_v0); - w_y_i_vec = _mm512_mask_blend_ps(cond_2, w_y_i_vec, _mm512_setzero_ps()); - curr_vel_x_i_vec = _mm512_mask_blend_ps(cond_2, curr_vel_x_i_vec, w_x_i_vec); - curr_vel_y_i_vec = _mm512_mask_blend_ps(cond_2, curr_vel_y_i_vec, w_y_i_vec); - - pos_y_i_vec = _mm512_max_ps(pos_y_i_vec, _mm512_set1_ps(WALL_EPS)); - pos_y_i_vec = _mm512_min_ps(pos_y_i_vec, _mm512_set1_ps(BOARD_WIDTH_MINUS_WALL_EPS)); - - // # 32 ADDs - __m512 ex_vec = _mm512_sub_ps(destination_x_i_vec, pos_x_i_vec); - __m512 ey_vec = _mm512_sub_ps(destination_y_i_vec, pos_y_i_vec); - - // # 32 MULTs, 16 ADDs - __m512 e_norm_sq = _mm512_fmadd_ps(ex_vec, ex_vec, _mm512_mul_ps(ey_vec, ey_vec)); - - // # 16 SQRTs, 16 DIVs - __m512 e_norm_inv = _mm512_rsqrt14_ps(e_norm_sq); - - // # 32 MULTs - __m512 e_x_i_vec = _mm512_mul_ps(ex_vec, e_norm_inv); - __m512 e_y_i_vec = _mm512_mul_ps(ey_vec, e_norm_inv); - - // # 32 MULTs, 16 ADDs - __m512 vel_norm_sq = _mm512_fmadd_ps(curr_vel_x_i_vec, curr_vel_x_i_vec, _mm512_mul_ps(curr_vel_y_i_vec, curr_vel_y_i_vec)); - - // # 16 MULTs - __m512 sb_sq_i_vec = _mm512_mul_ps(vel_norm_sq, _mm512_set1_ps(delta_t_sq)); - - // # 16 SQRTs - __m512 vel_norm_dt = _mm512_sqrt_ps(sb_sq_i_vec); - - _mm512_storeu_ps(&curr_vel_x[i], curr_vel_x_i_vec); - _mm512_storeu_ps(&curr_vel_y[i], curr_vel_y_i_vec); - _mm512_storeu_ps(&w_x[i], w_x_i_vec); - _mm512_storeu_ps(&w_y[i], w_y_i_vec); - _mm512_storeu_ps(&pos_x[i], pos_x_i_vec); - _mm512_storeu_ps(&pos_y[i], pos_y_i_vec); - _mm512_storeu_ps(&e_x[i], e_x_i_vec); - _mm512_storeu_ps(&e_y[i], e_y_i_vec); - _mm512_storeu_ps(&destination_y[i], destination_y_i_vec); - _mm512_storeu_ps(&sb_sq[i], sb_sq_i_vec); - - // # 32 MULTs - _mm512_storeu_ps(&sb_e_x[i], _mm512_mul_ps(e_x_i_vec, vel_norm_dt)); - _mm512_storeu_ps(&sb_e_y[i], _mm512_mul_ps(e_y_i_vec, vel_norm_dt)); - } - -#if !BENCHMARK - for (int i = 0; i < n_p; i++) { - if (dump_path && (t % dump_interval == 0)) { - samples.emplace_back(t + 1, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } - } -#endif - } - -#if !BENCHMARK - if (dump_path) { - ofstream out(dump_path); - out << "time,id,x,y,p.e.x,p.e.y,color\n"; - for (auto &[t, id, x, y, e_x, e_y, c] : samples) { - out << t << ',' << id << ',' << x << ',' << y << ',' << e_x << ',' << e_y << ',' << c << '\n'; - } - } -#endif - - return 0; -} diff --git a/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_expfix_improved.cpp b/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved.cpp similarity index 99% rename from variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_expfix_improved.cpp rename to variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved.cpp index fa51a70..e01412e 100644 --- a/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_expfix_improved.cpp +++ b/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved.cpp @@ -1,5 +1,5 @@ // # Changes: - used _mm512_mask3_fmadd_ps, to save one masking instruction -// - avoid doing an expensive brodcast for index vectors update, update them through additions instead +// - avoid doing an expensive broadcast for index vectors update, update them through additions instead // - replace array allocation + load with a direct set for lane_off initialization // # Predecessor: variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_expfix.cpp diff --git a/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_expfix_improved_moreilp.cpp b/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved_moreilp.cpp similarity index 100% rename from variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_expfix_improved_moreilp.cpp rename to variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_2_rsqrt_morersqrt_improved_moreilp.cpp diff --git a/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4.cpp b/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4.cpp index 67b5f14..1548d65 100644 --- a/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4.cpp +++ b/variants/variant_float_inlining_SoA_AVX512_polyexp_moreavx_ilp_4.cpp @@ -13,6 +13,8 @@ #define SEED 42 #define BOARD_WIDTH 10.0f #define BOARD_LENGTH 50.0f +#define BOARD_LENGTH_MINUS_ONE BOARD_LENGTH - 1.0f +#define BOARD_LENGTH_MINUS_ONE_POINT_FIVE BOARD_LENGTH - 1.5f #define WALL_EPS 1e-3f #define BOARD_WIDTH_MINUS_WALL_EPS 9.999f @@ -160,21 +162,46 @@ Pedestrian *init_pedestrians(int n_p) { Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } +// # 256 MULTs, 224 ADDs static inline __m512 _avx512_exp_ps(__m512 x) { + const __m512 log2e = _mm512_set1_ps(1.4426950408889634f); + + // # 16 MULTs __m512 nf = _mm512_roundscale_ps(_mm512_mul_ps(x, log2e), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); const __m512 ln2 = _mm512_set1_ps(0.6931471805599453f); + + // # 16 MULTs, 16 ADDs __m512 r = _mm512_fnmadd_ps(nf, ln2, x); - const __m512 c5 = _mm512_set1_ps(1.0f / 120.0f); - const __m512 c4 = _mm512_set1_ps(1.0f / 24.0f); - const __m512 c3 = _mm512_set1_ps(1.0f / 6.0f); - const __m512 c2 = _mm512_set1_ps(0.5f); - const __m512 c1 = _mm512_set1_ps(1.0f); - const __m512 c0 = _mm512_set1_ps(1.0f); + const __m512 c13 = _mm512_set1_ps(c13_scalar); + const __m512 c12 = _mm512_set1_ps(c12_scalar); + const __m512 c11 = _mm512_set1_ps(c11_scalar); + const __m512 c10 = _mm512_set1_ps(c10_scalar); + const __m512 c9 = _mm512_set1_ps(c9_scalar); + const __m512 c8 = _mm512_set1_ps(c8_scalar); + const __m512 c7 = _mm512_set1_ps(c7_scalar); + const __m512 c6 = _mm512_set1_ps(c6_scalar); + const __m512 c5 = _mm512_set1_ps(c5_scalar); + const __m512 c4 = _mm512_set1_ps(c4_scalar); + const __m512 c3 = _mm512_set1_ps(c3_scalar); + const __m512 c2 = _mm512_set1_ps(c2_scalar); + const __m512 c1 = _mm512_set1_ps(c1_scalar); + const __m512 c0 = _mm512_set1_ps(c0_scalar); - __m512 p = c5; + __m512 p = c13; + + // # 13 * (16 MULTs, 16 ADDs) + // # = 208 MULTs, 208 ADDs + p = _mm512_fmadd_ps(p, r, c12); + p = _mm512_fmadd_ps(p, r, c11); + p = _mm512_fmadd_ps(p, r, c10); + p = _mm512_fmadd_ps(p, r, c9); + p = _mm512_fmadd_ps(p, r, c8); + p = _mm512_fmadd_ps(p, r, c7); + p = _mm512_fmadd_ps(p, r, c6); + p = _mm512_fmadd_ps(p, r, c5); p = _mm512_fmadd_ps(p, r, c4); p = _mm512_fmadd_ps(p, r, c3); p = _mm512_fmadd_ps(p, r, c2); @@ -186,6 +213,7 @@ static inline __m512 _avx512_exp_ps(__m512 x) { __m512i scaled = _mm512_slli_epi32(biased, 23); __m512 pow2n = _mm512_castsi512_ps(scaled); + // # 16 MULTs return _mm512_mul_ps(p, pow2n); } @@ -224,11 +252,42 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c const __m512 v_np = _mm512_set1_ps((float)n_p); const __m512 v_exp_min = _mm512_set1_ps(-87.0f); + // # ADDs: n_iter * ( + // # n_p * 132 + + // # n_p * n_p_pad * 29 + + // # n_p * board.n_obstacles * 10 + + // # n_p_pad * 7 + // # ) + + // # MULTs: n_iter * ( + // # n_p * 4 + + // # n_p * n_p_pad * 40 + + // # n_p * board.n_obstacles * 13 + + // # n_p_pad * 15 + // # ) + + // # DIVs: n_iter * ( + // # n_p * n_p_pad + + // # n_p * board.n_obstacles + + // # n_p_pad * 2 + // # ) + + // # SQRTs: n_iter * ( + // # n_p * n_p_pad * 3 + + // # n_p * board.n_obstacles + + // # n_p_pad * 3 + // # ) + + // # EXPs: n_iter * n_p * board.n_obstacles + for (int t = 0; t < n_iter; t++) { for (int i = 0; i < n_p; i++) { + + // # 2 MULTs float desired_velocity_x = e_x[i] * desired_v0[i]; float desired_velocity_y = e_y[i] * desired_v0[i]; + // # 2 ADDs, 2 MULTs float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; @@ -249,6 +308,8 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 acc_y_3 = _mm512_setzero_ps(); for (int j = 0; j < n_p_pad; j += 64) { + + // # 64 ADDs __m512 j_idx_0 = _mm512_add_ps(_mm512_set1_ps((float)j), lane_off); __m512 j_idx_1 = _mm512_add_ps(_mm512_set1_ps((float)j + 16), lane_off); __m512 j_idx_2 = _mm512_add_ps(_mm512_set1_ps((float)j + 32), lane_off); @@ -294,61 +355,73 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 sb_jsq_2 = _mm512_loadu_ps(&sb_sq[j + 32]); __m512 sb_jsq_3 = _mm512_loadu_ps(&sb_sq[j + 48]); + // # 64 ADDs __m512 r_ab_x_0 = _mm512_sub_ps(pix, pjx_0); __m512 r_ab_x_1 = _mm512_sub_ps(pix, pjx_1); __m512 r_ab_x_2 = _mm512_sub_ps(pix, pjx_2); __m512 r_ab_x_3 = _mm512_sub_ps(pix, pjx_3); + // # 64 ADDs __m512 r_ab_y_0 = _mm512_sub_ps(piy, pjy_0); __m512 r_ab_y_1 = _mm512_sub_ps(piy, pjy_1); __m512 r_ab_y_2 = _mm512_sub_ps(piy, pjy_2); __m512 r_ab_y_3 = _mm512_sub_ps(piy, pjy_3); + // # 128 MULTs, 64 ADDs __m512 r_ab_n2_0 = _mm512_fmadd_ps(r_ab_x_0, r_ab_x_0, _mm512_mul_ps(r_ab_y_0, r_ab_y_0)); __m512 r_ab_n2_1 = _mm512_fmadd_ps(r_ab_x_1, r_ab_x_1, _mm512_mul_ps(r_ab_y_1, r_ab_y_1)); __m512 r_ab_n2_2 = _mm512_fmadd_ps(r_ab_x_2, r_ab_x_2, _mm512_mul_ps(r_ab_y_2, r_ab_y_2)); __m512 r_ab_n2_3 = _mm512_fmadd_ps(r_ab_x_3, r_ab_x_3, _mm512_mul_ps(r_ab_y_3, r_ab_y_3)); + // # 64 SQRTs __m512 r_ab_n_0 = _mm512_sqrt_ps(r_ab_n2_0); __m512 r_ab_n_1 = _mm512_sqrt_ps(r_ab_n2_1); __m512 r_ab_n_2 = _mm512_sqrt_ps(r_ab_n2_2); __m512 r_ab_n_3 = _mm512_sqrt_ps(r_ab_n2_3); + // # 64 ADDs __m512 r_ab2_x_0 = _mm512_sub_ps(r_ab_x_0, sbe_jx_0); __m512 r_ab2_x_1 = _mm512_sub_ps(r_ab_x_1, sbe_jx_1); __m512 r_ab2_x_2 = _mm512_sub_ps(r_ab_x_2, sbe_jx_2); __m512 r_ab2_x_3 = _mm512_sub_ps(r_ab_x_3, sbe_jx_3); + // # 64 ADDs __m512 r_ab2_y_0 = _mm512_sub_ps(r_ab_y_0, sbe_jy_0); __m512 r_ab2_y_1 = _mm512_sub_ps(r_ab_y_1, sbe_jy_1); __m512 r_ab2_y_2 = _mm512_sub_ps(r_ab_y_2, sbe_jy_2); __m512 r_ab2_y_3 = _mm512_sub_ps(r_ab_y_3, sbe_jy_3); + // # 128 MULTs, 64 ADDs __m512 r_ab2_n2_0 = _mm512_fmadd_ps(r_ab2_x_0, r_ab2_x_0, _mm512_mul_ps(r_ab2_y_0, r_ab2_y_0)); __m512 r_ab2_n2_1 = _mm512_fmadd_ps(r_ab2_x_1, r_ab2_x_1, _mm512_mul_ps(r_ab2_y_1, r_ab2_y_1)); __m512 r_ab2_n2_2 = _mm512_fmadd_ps(r_ab2_x_2, r_ab2_x_2, _mm512_mul_ps(r_ab2_y_2, r_ab2_y_2)); __m512 r_ab2_n2_3 = _mm512_fmadd_ps(r_ab2_x_3, r_ab2_x_3, _mm512_mul_ps(r_ab2_y_3, r_ab2_y_3)); + // # 64 SQRTs __m512 r_ab2_n_0 = _mm512_sqrt_ps(r_ab2_n2_0); __m512 r_ab2_n_1 = _mm512_sqrt_ps(r_ab2_n2_1); __m512 r_ab2_n_2 = _mm512_sqrt_ps(r_ab2_n2_2); __m512 r_ab2_n_3 = _mm512_sqrt_ps(r_ab2_n2_3); + // # 64 ADDs __m512 r_sum_0 = _mm512_add_ps(r_ab_n_0, r_ab2_n_0); __m512 r_sum_1 = _mm512_add_ps(r_ab_n_1, r_ab2_n_1); __m512 r_sum_2 = _mm512_add_ps(r_ab_n_2, r_ab2_n_2); __m512 r_sum_3 = _mm512_add_ps(r_ab_n_3, r_ab2_n_3); + // # 64 MULTs, 64 ADDs __m512 two_b_sq_0 = _mm512_fmsub_ps(r_sum_0, r_sum_0, sb_jsq_0); __m512 two_b_sq_1 = _mm512_fmsub_ps(r_sum_1, r_sum_1, sb_jsq_1); __m512 two_b_sq_2 = _mm512_fmsub_ps(r_sum_2, r_sum_2, sb_jsq_2); __m512 two_b_sq_3 = _mm512_fmsub_ps(r_sum_3, r_sum_3, sb_jsq_3); + // # 64 SQRTs __m512 two_b_0 = _mm512_sqrt_ps(two_b_sq_0); __m512 two_b_1 = _mm512_sqrt_ps(two_b_sq_1); __m512 two_b_2 = _mm512_sqrt_ps(two_b_sq_2); __m512 two_b_3 = _mm512_sqrt_ps(two_b_sq_3); + // # 64 MULTs __m512 e_arg_0 = _mm512_mul_ps(two_b_0, v_neg_2s_inv); __m512 e_arg_1 = _mm512_mul_ps(two_b_1, v_neg_2s_inv); __m512 e_arg_2 = _mm512_mul_ps(two_b_2, v_neg_2s_inv); @@ -359,16 +432,19 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c e_arg_2 = _mm512_max_ps(e_arg_2, v_exp_min); e_arg_3 = _mm512_max_ps(e_arg_3, v_exp_min); + // # 1024 MULTs, 896 ADDs __m512 e_val_0 = _avx512_exp_ps(e_arg_0); __m512 e_val_1 = _avx512_exp_ps(e_arg_1); __m512 e_val_2 = _avx512_exp_ps(e_arg_2); __m512 e_val_3 = _avx512_exp_ps(e_arg_3); + // # 128 MULTs __m512 numer_0 = _mm512_mul_ps(_mm512_mul_ps(r_sum_0, v_neg_v0_div_2s), e_val_0); __m512 numer_1 = _mm512_mul_ps(_mm512_mul_ps(r_sum_1, v_neg_v0_div_2s), e_val_1); __m512 numer_2 = _mm512_mul_ps(_mm512_mul_ps(r_sum_2, v_neg_v0_div_2s), e_val_2); __m512 numer_3 = _mm512_mul_ps(_mm512_mul_ps(r_sum_3, v_neg_v0_div_2s), e_val_3); + // # 128 MULTs __m512 denom_0 = _mm512_mul_ps(_mm512_mul_ps(two_b_0, r_ab_n_0), r_ab2_n_0); __m512 denom_1 = _mm512_mul_ps(_mm512_mul_ps(two_b_1, r_ab_n_1), r_ab2_n_1); __m512 denom_2 = _mm512_mul_ps(_mm512_mul_ps(two_b_2, r_ab_n_2), r_ab2_n_2); @@ -379,46 +455,55 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 denom_safe_2 = _mm512_mask_blend_ps(active_2, v_one, denom_2); __m512 denom_safe_3 = _mm512_mask_blend_ps(active_3, v_one, denom_3); + // # 64 DIVs __m512 smc_0 = _mm512_div_ps(numer_0, denom_safe_0); __m512 smc_1 = _mm512_div_ps(numer_1, denom_safe_1); __m512 smc_2 = _mm512_div_ps(numer_2, denom_safe_2); __m512 smc_3 = _mm512_div_ps(numer_3, denom_safe_3); + // # 64 MULTs __m512 sm_r_ab_0 = _mm512_mul_ps(smc_0, r_ab2_n_0); __m512 sm_r_ab_1 = _mm512_mul_ps(smc_1, r_ab2_n_1); __m512 sm_r_ab_2 = _mm512_mul_ps(smc_2, r_ab2_n_2); __m512 sm_r_ab_3 = _mm512_mul_ps(smc_3, r_ab2_n_3); + // # 64 MULTs __m512 sm_r_ab2_0 = _mm512_mul_ps(smc_0, r_ab_n_0); __m512 sm_r_ab2_1 = _mm512_mul_ps(smc_1, r_ab_n_1); __m512 sm_r_ab2_2 = _mm512_mul_ps(smc_2, r_ab_n_2); __m512 sm_r_ab2_3 = _mm512_mul_ps(smc_3, r_ab_n_3); + // # 128 MULTs, 64 ADDs __m512 f_x_0 = _mm512_fmadd_ps(r_ab2_x_0, sm_r_ab2_0, _mm512_mul_ps(r_ab_x_0, sm_r_ab_0)); __m512 f_x_1 = _mm512_fmadd_ps(r_ab2_x_1, sm_r_ab2_1, _mm512_mul_ps(r_ab_x_1, sm_r_ab_1)); __m512 f_x_2 = _mm512_fmadd_ps(r_ab2_x_2, sm_r_ab2_2, _mm512_mul_ps(r_ab_x_2, sm_r_ab_2)); __m512 f_x_3 = _mm512_fmadd_ps(r_ab2_x_3, sm_r_ab2_3, _mm512_mul_ps(r_ab_x_3, sm_r_ab_3)); + // # 128 MULTs, 64 ADDs __m512 f_y_0 = _mm512_fmadd_ps(r_ab2_y_0, sm_r_ab2_0, _mm512_mul_ps(r_ab_y_0, sm_r_ab_0)); __m512 f_y_1 = _mm512_fmadd_ps(r_ab2_y_1, sm_r_ab2_1, _mm512_mul_ps(r_ab_y_1, sm_r_ab_1)); __m512 f_y_2 = _mm512_fmadd_ps(r_ab2_y_2, sm_r_ab2_2, _mm512_mul_ps(r_ab_y_2, sm_r_ab_2)); __m512 f_y_3 = _mm512_fmadd_ps(r_ab2_y_3, sm_r_ab2_3, _mm512_mul_ps(r_ab_y_3, sm_r_ab_3)); + // # 128 MULTs, 64 ADDs __m512 f_norm_sq_0 = _mm512_fmadd_ps(f_x_0, f_x_0, _mm512_mul_ps(f_y_0, f_y_0)); __m512 f_norm_sq_1 = _mm512_fmadd_ps(f_x_1, f_x_1, _mm512_mul_ps(f_y_1, f_y_1)); __m512 f_norm_sq_2 = _mm512_fmadd_ps(f_x_2, f_x_2, _mm512_mul_ps(f_y_2, f_y_2)); __m512 f_norm_sq_3 = _mm512_fmadd_ps(f_x_3, f_x_3, _mm512_mul_ps(f_y_3, f_y_3)); + // # 64 MULTs __m512 rhs_0 = _mm512_mul_ps(f_norm_sq_0, v_cos_phi_sq); __m512 rhs_1 = _mm512_mul_ps(f_norm_sq_1, v_cos_phi_sq); __m512 rhs_2 = _mm512_mul_ps(f_norm_sq_2, v_cos_phi_sq); __m512 rhs_3 = _mm512_mul_ps(f_norm_sq_3, v_cos_phi_sq); + // # 128 MULTs, 64 ADDs __m512 e_dot_f_0 = _mm512_fmadd_ps(eix, f_x_0, _mm512_mul_ps(eiy, f_y_0)); __m512 e_dot_f_1 = _mm512_fmadd_ps(eix, f_x_1, _mm512_mul_ps(eiy, f_y_1)); __m512 e_dot_f_2 = _mm512_fmadd_ps(eix, f_x_2, _mm512_mul_ps(eiy, f_y_2)); __m512 e_dot_f_3 = _mm512_fmadd_ps(eix, f_x_3, _mm512_mul_ps(eiy, f_y_3)); + // # 64 MULTs __m512 e_dot_f_sq_0 = _mm512_mul_ps(e_dot_f_0, e_dot_f_0); __m512 e_dot_f_sq_1 = _mm512_mul_ps(e_dot_f_1, e_dot_f_1); __m512 e_dot_f_sq_2 = _mm512_mul_ps(e_dot_f_2, e_dot_f_2); @@ -454,26 +539,31 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 f_y_safe_2 = _mm512_maskz_mov_ps(active_2, f_y_2); __m512 f_y_safe_3 = _mm512_maskz_mov_ps(active_3, f_y_3); + // # 64 MULTs, 64 ADDs acc_x_0 = _mm512_fmadd_ps(f_x_safe_0, w_val_0, acc_x_0); acc_x_1 = _mm512_fmadd_ps(f_x_safe_1, w_val_1, acc_x_1); acc_x_2 = _mm512_fmadd_ps(f_x_safe_2, w_val_2, acc_x_2); acc_x_3 = _mm512_fmadd_ps(f_x_safe_3, w_val_3, acc_x_3); + // # 64 MULTs, 64 ADDs acc_y_0 = _mm512_fmadd_ps(f_y_safe_0, w_val_0, acc_y_0); acc_y_1 = _mm512_fmadd_ps(f_y_safe_1, w_val_1, acc_y_1); acc_y_2 = _mm512_fmadd_ps(f_y_safe_2, w_val_2, acc_y_2); acc_y_3 = _mm512_fmadd_ps(f_y_safe_3, w_val_3, acc_y_3); } - + // # 128 ADDs f_alpha_dt_x += _mm512_reduce_add_ps(_mm512_add_ps(_mm512_add_ps(acc_x_0, acc_x_1), _mm512_add_ps(acc_x_2, acc_x_3))); f_alpha_dt_y += _mm512_reduce_add_ps(_mm512_add_ps(_mm512_add_ps(acc_y_0, acc_y_1), _mm512_add_ps(acc_y_2, acc_y_3))); for (int k = 0; k < board.n_obstacles; k++) { + + // # 2 ADDs float v1_x = pos_x[i] - board.obstacles[k].start_x; float v1_y = pos_y[i] - board.obstacles[k].start_y; float v2_x = board.obstacles[k].obstacle_v_x; float v2_y = board.obstacles[k].obstacle_v_y; + // # 3 MULTs, 1 ADD float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; if (projection < 0.0f) @@ -481,12 +571,15 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c else if (projection > 1.0f) projection = 1.0f; + // # 4 ADDs, 2 MULTs float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); + // # 1 SQRT, 2 MULTs, 1 ADD float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; + // # 1 EXP, 4 MULTs, 1 DIV float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; float f_alpha_B_neg_x = r_aB_x * scalar_mult; float f_alpha_B_neg_y = r_aB_y * scalar_mult; @@ -497,19 +590,22 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c if (e_dot_f < cos_phi) w_val = c_neg_times_dt; + // # 2 MULTs float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; + // # 2 ADDs f_alpha_dt_x += f_alpha_B_dt_x; f_alpha_dt_y += f_alpha_B_dt_y; } + // # 2 ADDs w_x[i] += f_alpha_dt_x; w_y[i] += f_alpha_dt_y; } for (int i = 0; i < n_p_pad; i += 16) { - + __m512 w_x_i_vec = _mm512_loadu_ps(&w_x[i]); __m512 w_y_i_vec = _mm512_loadu_ps(&w_y[i]); __m512 v_max_i_vec = _mm512_loadu_ps(&v_max[i]); @@ -518,22 +614,30 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512 destination_y_i_vec = _mm512_loadu_ps(&destination_y[i]); __m512 destination_x_i_vec = _mm512_loadu_ps(&destination_x[i]); __m512 desired_v0_i_vec = _mm512_loadu_ps(&desired_v0[i]); - - __m512i color_i_vec = _mm512_loadu_si512((__m512i*)&color[i]); + __m512i color_i_vec = _mm512_loadu_si512((__m512i *)&color[i]); + + // # 32 MULTs, 16 ADDs __m512 w_norm_sq = _mm512_fmadd_ps(w_x_i_vec, w_x_i_vec, _mm512_mul_ps(w_y_i_vec, w_y_i_vec)); + + // # 16 SQRTs __m512 w_norm = _mm512_sqrt_ps(w_norm_sq); + + // # 16 DIVs __m512 correction_factor = _mm512_min_ps(_mm512_set1_ps(1.0f), _mm512_div_ps(v_max_i_vec, w_norm)); + // # 32 MULTs __m512 curr_vel_x_i_vec = _mm512_mul_ps(w_x_i_vec, correction_factor); __m512 curr_vel_y_i_vec = _mm512_mul_ps(w_y_i_vec, correction_factor); __m512 dt_vec = _mm512_set1_ps(dt); + + // # 32 MULTs, 32 ADDs pos_x_i_vec = _mm512_fmadd_ps(curr_vel_x_i_vec, dt_vec, pos_x_i_vec); pos_y_i_vec = _mm512_fmadd_ps(curr_vel_y_i_vec, dt_vec, pos_y_i_vec); __mmask16 cond_1_left = _mm512_cmpeq_epi32_mask(color_i_vec, _mm512_setzero_si512()); - __mmask16 cond_1_right = _mm512_cmp_ps_mask(pos_x_i_vec, _mm512_set1_ps(BOARD_LENGTH - 1.5f), _CMP_GT_OQ); + __mmask16 cond_1_right = _mm512_cmp_ps_mask(pos_x_i_vec, _mm512_set1_ps(BOARD_LENGTH_MINUS_ONE_POINT_FIVE), _CMP_GT_OQ); __mmask16 cond_1 = cond_1_left & cond_1_right; pos_x_i_vec = _mm512_mask_blend_ps(cond_1, pos_x_i_vec, _mm512_set1_ps(1.0f)); @@ -547,7 +651,7 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __mmask16 cond_2_right = _mm512_cmp_ps_mask(pos_x_i_vec, _mm512_set1_ps(1.5f), _CMP_LT_OQ); __mmask16 cond_2 = cond_2_left & cond_2_right; - pos_x_i_vec = _mm512_mask_blend_ps(cond_2, pos_x_i_vec, _mm512_set1_ps(BOARD_LENGTH - 1.0f)); + pos_x_i_vec = _mm512_mask_blend_ps(cond_2, pos_x_i_vec, _mm512_set1_ps(BOARD_LENGTH_MINUS_ONE)); destination_y_i_vec = _mm512_mask_blend_ps(cond_2, destination_y_i_vec, pos_y_i_vec); __m512 neg_desired_v0 = _mm512_xor_ps(desired_v0_i_vec, _mm512_set1_ps(-0.0f)); w_x_i_vec = _mm512_mask_blend_ps(cond_2, w_x_i_vec, neg_desired_v0); @@ -558,16 +662,30 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c pos_y_i_vec = _mm512_max_ps(pos_y_i_vec, _mm512_set1_ps(WALL_EPS)); pos_y_i_vec = _mm512_min_ps(pos_y_i_vec, _mm512_set1_ps(BOARD_WIDTH_MINUS_WALL_EPS)); + // # 32 ADDs __m512 ex_vec = _mm512_sub_ps(destination_x_i_vec, pos_x_i_vec); __m512 ey_vec = _mm512_sub_ps(destination_y_i_vec, pos_y_i_vec); + + // # 32 MULTs, 16 ADDs __m512 e_norm_sq = _mm512_fmadd_ps(ex_vec, ex_vec, _mm512_mul_ps(ey_vec, ey_vec)); + + // # 16 SQRTs __m512 e_norm = _mm512_sqrt_ps(e_norm_sq); + + // # 16 DIVs __m512 e_norm_inv = _mm512_div_ps(_mm512_set1_ps(1.0f), e_norm); + + // # 32 MULTs __m512 e_x_i_vec = _mm512_mul_ps(ex_vec, e_norm_inv); __m512 e_y_i_vec = _mm512_mul_ps(ey_vec, e_norm_inv); + // # 32 MULTs, 16 ADDs __m512 vel_norm_sq = _mm512_fmadd_ps(curr_vel_x_i_vec, curr_vel_x_i_vec, _mm512_mul_ps(curr_vel_y_i_vec, curr_vel_y_i_vec)); + + // # 16 MULTs __m512 sb_sq_i_vec = _mm512_mul_ps(vel_norm_sq, _mm512_set1_ps(delta_t_sq)); + + // # 16 SQRTs __m512 vel_norm_dt = _mm512_sqrt_ps(sb_sq_i_vec); _mm512_storeu_ps(&curr_vel_x[i], curr_vel_x_i_vec); @@ -580,11 +698,12 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c _mm512_storeu_ps(&e_y[i], e_y_i_vec); _mm512_storeu_ps(&destination_y[i], destination_y_i_vec); _mm512_storeu_ps(&sb_sq[i], sb_sq_i_vec); + + // # 32 MULTs _mm512_storeu_ps(&sb_e_x[i], _mm512_mul_ps(e_x_i_vec, vel_norm_dt)); _mm512_storeu_ps(&sb_e_y[i], _mm512_mul_ps(e_y_i_vec, vel_norm_dt)); } - #if !BENCHMARK for (int i = 0; i < n_p; i++) { if (dump_path && (t % dump_interval == 0)) { diff --git a/variants/variant_float_inlining_SoA_NEON_polyexp_moreavx_ilp_2_rsqrt_morrsqrt.cpp b/variants/variant_float_inlining_SoA_NEON_polyexp_moreavx_ilp_2_rsqrt_morersqrt.cpp similarity index 100% rename from variants/variant_float_inlining_SoA_NEON_polyexp_moreavx_ilp_2_rsqrt_morrsqrt.cpp rename to variants/variant_float_inlining_SoA_NEON_polyexp_moreavx_ilp_2_rsqrt_morersqrt.cpp diff --git a/variants/variant_float_inlining_SoA_symmetry_ILP_16_flopcount.cpp b/variants/variant_float_inlining_SoA_symmetry_ILP_16_flopcount.cpp deleted file mode 100644 index f84bd66..0000000 --- a/variants/variant_float_inlining_SoA_symmetry_ILP_16_flopcount.cpp +++ /dev/null @@ -1,1496 +0,0 @@ -// # Changes: Added ILP for j-loop with K = 16 -// # added flopcount -// FLOPCOUNT = n_iter * ( 69 * n_p ** 2 + 32 * n_p + 55 * n_obstacles * n_p ) -// # Predecessor: variant_float_inlining_SoA_symmetry_ILP_8.cpp - -#include "../headers/board_reduced_float.hpp" -#include "../headers/constants_float.hpp" -#include "../headers/pedestrian_reduced_float.hpp" - -#include -#include -#include - -#define SEED 42 -#define BOARD_WIDTH 10.0f -#define BOARD_LENGTH 50.0f -#define WALL_EPS 1e-3f -#define BOARD_WIDTH_MINUS_WALL_EPS 9.999f - -#ifndef RANDOM_SEED -#define RANDOM_SEED 0 -#endif - -#ifndef BENCHMARK -#define BENCHMARK 0 -#endif - -using namespace std; - -vector pos_x, pos_y; -vector sb_sq; -vector sb_e_x, sb_e_y; -vector e_x, e_y; -vector curr_vel_x, curr_vel_y; -vector w_x, w_y; -vector desired_v0; -vector v_max; -vector destination_x, destination_y; -vector color; - -Pedestrian *init_pedestrians(int n_p) { -#if RANDOM_SEED - random_device rd; - mt19937 gen(rd()); -#else - mt19937 gen(SEED); -#endif - - normal_distribution velocity_gen(v0_mean, v0_std_dev); - uniform_real_distribution y_gen(0.3, BOARD_WIDTH - 0.3); - uniform_real_distribution x_gen_left(2.0, BOARD_LENGTH / 2.0); - uniform_real_distribution x_gen_right(BOARD_LENGTH / 2.0, BOARD_LENGTH - 2.0); - - pos_x.resize(n_p); - pos_y.resize(n_p); - sb_sq.resize(n_p); - sb_e_x.resize(n_p); - sb_e_y.resize(n_p); - e_x.resize(n_p); - e_y.resize(n_p); - curr_vel_x.resize(n_p); - curr_vel_y.resize(n_p); - w_x.resize(n_p); - w_y.resize(n_p); - desired_v0.resize(n_p); - v_max.resize(n_p); - destination_x.resize(n_p); - destination_y.resize(n_p); - color.resize(n_p); - - int n_p_half = n_p / 2; - - for (int i = 0; i < n_p_half; i++) { - float x = x_gen_left(gen); - float y = y_gen(gen); - - float dest_x = BOARD_LENGTH + 30.0; - float dest_y = y; - - float init_e_x = dest_x - x; - float init_e_y = dest_y - y; - float init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - float init_e_unit_x = init_e_x / init_e_norm; - float init_e_unit_y = init_e_y / init_e_norm; - - float d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1); - - float v_m = 1.3 * d_v0; - - color[i] = 0; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - w_x[i] = 0.0f; - w_y[i] = 0.0f; - curr_vel_x[i] = 0.0f; - curr_vel_y[i] = 0.0f; - sb_sq[i] = 0.0f; - sb_e_x[i] = 0.0f; - sb_e_y[i] = 0.0f; - } - - for (int i = n_p_half; i < n_p; i++) { - float x = x_gen_right(gen); - float y = y_gen(gen); - - float dest_x = -30; - float dest_y = y; - - float init_e_x = dest_x - x; - float init_e_y = dest_y - y; - float init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - float init_e_unit_x = init_e_x / init_e_norm; - float init_e_unit_y = init_e_y / init_e_norm; - - float d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1); - - float v_m = 1.3 * d_v0; - - color[i] = 1; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - w_x[i] = 0.0f; - w_y[i] = 0.0f; - curr_vel_x[i] = 0.0f; - curr_vel_y[i] = 0.0f; - sb_sq[i] = 0.0f; - sb_e_x[i] = 0.0f; - sb_e_y[i] = 0.0f; - } - - return nullptr; -} - -Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } - -int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { - (void)pedestrians; -#if BENCHMARK - (void)dump_path; -#endif - -#if !BENCHMARK - const int dump_interval = 1; - - vector> samples; - - if (dump_path) { - samples.reserve(static_cast(n_iter / dump_interval + 1) * n_p); - - for (int i = 0; i < n_p; i++) { - samples.emplace_back(0, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } - } -#endif - - vector r_ab_x_lut(n_p * n_p, 0.0); - vector r_ab_y_lut(n_p * n_p, 0.0); - vector r_ab_norm_lut(n_p * n_p, 0.0); - - // FLOPCOUNT (everything inside the t-loop). EXP kept as its own op (one real exp() per call). - // section costs: overhead 4 ADD 4 MULT (+ reductions 4*K = 64 ADD, K=16) | - // distance pair 3 ADD 2 MULT 1 SQRT | - // ped-ped j 11 ADD 22 MULT 2 SQRT 1 DIV 1 EXP | - // obstacle 10 ADD 13 MULT 1 SQRT 1 DIV 1 EXP | update 7 ADD 17 MULT 3 SQRT 2 DIV - - // # ADDs: n_iter * ( - // # n_p * 68 + - // # 0.5 * (n_p*n_p - n_p) * 3 + - // # n_p * (n_p - 1) * 11 + - // # n_p * board.n_obstacles * 10 + - // # n_p * 7 - // # ) - - // # MULTs: n_iter * ( - // # n_p * 4 + - // # 0.5 * (n_p*n_p - n_p) * 2 + - // # n_p * (n_p - 1) * 22 + - // # n_p * board.n_obstacles * 13 + - // # n_p * 17 - // # ) - - // # DIVs: n_iter * ( - // # n_p * (n_p - 1) + - // # n_p * board.n_obstacles + - // # n_p * 2 - // # ) - - // # SQRTs: n_iter * ( - // # 0.5 * (n_p*n_p - n_p) + - // # n_p * (n_p - 1) * 2 + - // # n_p * board.n_obstacles + - // # n_p * 3 - // # ) - - // # EXPs: n_iter * ( - // # n_p * (n_p - 1) + - // # n_p * board.n_obstacles - // # ) - - // total with EXP = 30: n_iter * ( 69 * n_p ** 2 + 32 * n_p + 55 * n_obstacles * n_p ) - for (int t = 0; t < n_iter; t++) { - for (int i = 0; i < n_p; i++) { - - // # 1 MULT - float desired_velocity_x = e_x[i] * desired_v0[i]; - // # 1 MULT - float desired_velocity_y = e_y[i] * desired_v0[i]; - // # 1 ADD, 1 MULT - float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; - // # 1 ADD, 1 MULT - float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; - - float e_x_i = e_x[i]; - float e_y_i = e_y[i]; - float pos_x_i = pos_x[i]; - float pos_y_i = pos_y[i]; - - // distance precompute, # each pair: 6 FLOPS, total over all i = 0.5*(n_p*n_p - n_p)*6 - for (int j = i + 1; j < n_p; j++) { - // # 1 ADD - float dx = pos_x_i - pos_x[j]; - // # 1 ADD - float dy = pos_y_i - pos_y[j]; - // # 1 ADD, 2 MULTs, 1 SQRT - float norm = sqrt(dx * dx + dy * dy); - int idx = i * n_p + j; - r_ab_x_lut[idx] = dx; - r_ab_y_lut[idx] = dy; - r_ab_norm_lut[idx] = norm; - } - - int j; - - float acc_x_0 = 0.0f, acc_x_1 = 0.0f, acc_x_2 = 0.0f, acc_x_3 = 0.0f; - float acc_x_4 = 0.0f, acc_x_5 = 0.0f, acc_x_6 = 0.0f, acc_x_7 = 0.0f; - float acc_x_8 = 0.0f, acc_x_9 = 0.0f, acc_x_10 = 0.0f, acc_x_11 = 0.0f; - float acc_x_12 = 0.0f, acc_x_13 = 0.0f, acc_x_14 = 0.0f, acc_x_15 = 0.0f; - float acc_y_0 = 0.0f, acc_y_1 = 0.0f, acc_y_2 = 0.0f, acc_y_3 = 0.0f; - float acc_y_4 = 0.0f, acc_y_5 = 0.0f, acc_y_6 = 0.0f, acc_y_7 = 0.0f; - float acc_y_8 = 0.0f, acc_y_9 = 0.0f, acc_y_10 = 0.0f, acc_y_11 = 0.0f; - float acc_y_12 = 0.0f, acc_y_13 = 0.0f, acc_y_14 = 0.0f, acc_y_15 = 0.0f; - - // ILP over the j < i half. # each lane = 66 FLOPS (per-line breakdown is the - // same as the single-lane remainder loop below), K = 16 lanes per step - for (j = 0; j + 16 < i; j += 16) { - float r_ab_x_0 = -1 * r_ab_x_lut[j * n_p + i]; - float r_ab_x_1 = -1 * r_ab_x_lut[(j + 1) * n_p + i]; - float r_ab_x_2 = -1 * r_ab_x_lut[(j + 2) * n_p + i]; - float r_ab_x_3 = -1 * r_ab_x_lut[(j + 3) * n_p + i]; - float r_ab_x_4 = -1 * r_ab_x_lut[(j + 4) * n_p + i]; - float r_ab_x_5 = -1 * r_ab_x_lut[(j + 5) * n_p + i]; - float r_ab_x_6 = -1 * r_ab_x_lut[(j + 6) * n_p + i]; - float r_ab_x_7 = -1 * r_ab_x_lut[(j + 7) * n_p + i]; - float r_ab_x_8 = -1 * r_ab_x_lut[(j + 8) * n_p + i]; - float r_ab_x_9 = -1 * r_ab_x_lut[(j + 9) * n_p + i]; - float r_ab_x_10 = -1 * r_ab_x_lut[(j + 10) * n_p + i]; - float r_ab_x_11 = -1 * r_ab_x_lut[(j + 11) * n_p + i]; - float r_ab_x_12 = -1 * r_ab_x_lut[(j + 12) * n_p + i]; - float r_ab_x_13 = -1 * r_ab_x_lut[(j + 13) * n_p + i]; - float r_ab_x_14 = -1 * r_ab_x_lut[(j + 14) * n_p + i]; - float r_ab_x_15 = -1 * r_ab_x_lut[(j + 15) * n_p + i]; - - float r_ab_y_0 = -1 * r_ab_y_lut[j * n_p + i]; - float r_ab_y_1 = -1 * r_ab_y_lut[(j + 1) * n_p + i]; - float r_ab_y_2 = -1 * r_ab_y_lut[(j + 2) * n_p + i]; - float r_ab_y_3 = -1 * r_ab_y_lut[(j + 3) * n_p + i]; - float r_ab_y_4 = -1 * r_ab_y_lut[(j + 4) * n_p + i]; - float r_ab_y_5 = -1 * r_ab_y_lut[(j + 5) * n_p + i]; - float r_ab_y_6 = -1 * r_ab_y_lut[(j + 6) * n_p + i]; - float r_ab_y_7 = -1 * r_ab_y_lut[(j + 7) * n_p + i]; - float r_ab_y_8 = -1 * r_ab_y_lut[(j + 8) * n_p + i]; - float r_ab_y_9 = -1 * r_ab_y_lut[(j + 9) * n_p + i]; - float r_ab_y_10 = -1 * r_ab_y_lut[(j + 10) * n_p + i]; - float r_ab_y_11 = -1 * r_ab_y_lut[(j + 11) * n_p + i]; - float r_ab_y_12 = -1 * r_ab_y_lut[(j + 12) * n_p + i]; - float r_ab_y_13 = -1 * r_ab_y_lut[(j + 13) * n_p + i]; - float r_ab_y_14 = -1 * r_ab_y_lut[(j + 14) * n_p + i]; - float r_ab_y_15 = -1 * r_ab_y_lut[(j + 15) * n_p + i]; - - float r_ab_norm_0 = r_ab_norm_lut[j * n_p + i]; - float r_ab_norm_1 = r_ab_norm_lut[(j + 1) * n_p + i]; - float r_ab_norm_2 = r_ab_norm_lut[(j + 2) * n_p + i]; - float r_ab_norm_3 = r_ab_norm_lut[(j + 3) * n_p + i]; - float r_ab_norm_4 = r_ab_norm_lut[(j + 4) * n_p + i]; - float r_ab_norm_5 = r_ab_norm_lut[(j + 5) * n_p + i]; - float r_ab_norm_6 = r_ab_norm_lut[(j + 6) * n_p + i]; - float r_ab_norm_7 = r_ab_norm_lut[(j + 7) * n_p + i]; - float r_ab_norm_8 = r_ab_norm_lut[(j + 8) * n_p + i]; - float r_ab_norm_9 = r_ab_norm_lut[(j + 9) * n_p + i]; - float r_ab_norm_10 = r_ab_norm_lut[(j + 10) * n_p + i]; - float r_ab_norm_11 = r_ab_norm_lut[(j + 11) * n_p + i]; - float r_ab_norm_12 = r_ab_norm_lut[(j + 12) * n_p + i]; - float r_ab_norm_13 = r_ab_norm_lut[(j + 13) * n_p + i]; - float r_ab_norm_14 = r_ab_norm_lut[(j + 14) * n_p + i]; - float r_ab_norm_15 = r_ab_norm_lut[(j + 15) * n_p + i]; - - r_ab_norm_0 = r_ab_norm_0 > EPS ? r_ab_norm_0 : EPS; - r_ab_norm_1 = r_ab_norm_1 > EPS ? r_ab_norm_1 : EPS; - r_ab_norm_2 = r_ab_norm_2 > EPS ? r_ab_norm_2 : EPS; - r_ab_norm_3 = r_ab_norm_3 > EPS ? r_ab_norm_3 : EPS; - r_ab_norm_4 = r_ab_norm_4 > EPS ? r_ab_norm_4 : EPS; - r_ab_norm_5 = r_ab_norm_5 > EPS ? r_ab_norm_5 : EPS; - r_ab_norm_6 = r_ab_norm_6 > EPS ? r_ab_norm_6 : EPS; - r_ab_norm_7 = r_ab_norm_7 > EPS ? r_ab_norm_7 : EPS; - r_ab_norm_8 = r_ab_norm_8 > EPS ? r_ab_norm_8 : EPS; - r_ab_norm_9 = r_ab_norm_9 > EPS ? r_ab_norm_9 : EPS; - r_ab_norm_10 = r_ab_norm_10 > EPS ? r_ab_norm_10 : EPS; - r_ab_norm_11 = r_ab_norm_11 > EPS ? r_ab_norm_11 : EPS; - r_ab_norm_12 = r_ab_norm_12 > EPS ? r_ab_norm_12 : EPS; - r_ab_norm_13 = r_ab_norm_13 > EPS ? r_ab_norm_13 : EPS; - r_ab_norm_14 = r_ab_norm_14 > EPS ? r_ab_norm_14 : EPS; - r_ab_norm_15 = r_ab_norm_15 > EPS ? r_ab_norm_15 : EPS; - - float r_ab2_x_0 = r_ab_x_0 - sb_e_x[j]; - float r_ab2_x_1 = r_ab_x_1 - sb_e_x[j + 1]; - float r_ab2_x_2 = r_ab_x_2 - sb_e_x[j + 2]; - float r_ab2_x_3 = r_ab_x_3 - sb_e_x[j + 3]; - float r_ab2_x_4 = r_ab_x_4 - sb_e_x[j + 4]; - float r_ab2_x_5 = r_ab_x_5 - sb_e_x[j + 5]; - float r_ab2_x_6 = r_ab_x_6 - sb_e_x[j + 6]; - float r_ab2_x_7 = r_ab_x_7 - sb_e_x[j + 7]; - float r_ab2_x_8 = r_ab_x_8 - sb_e_x[j + 8]; - float r_ab2_x_9 = r_ab_x_9 - sb_e_x[j + 9]; - float r_ab2_x_10 = r_ab_x_10 - sb_e_x[j + 10]; - float r_ab2_x_11 = r_ab_x_11 - sb_e_x[j + 11]; - float r_ab2_x_12 = r_ab_x_12 - sb_e_x[j + 12]; - float r_ab2_x_13 = r_ab_x_13 - sb_e_x[j + 13]; - float r_ab2_x_14 = r_ab_x_14 - sb_e_x[j + 14]; - float r_ab2_x_15 = r_ab_x_15 - sb_e_x[j + 15]; - - float r_ab2_y_0 = r_ab_y_0 - sb_e_y[j]; - float r_ab2_y_1 = r_ab_y_1 - sb_e_y[j + 1]; - float r_ab2_y_2 = r_ab_y_2 - sb_e_y[j + 2]; - float r_ab2_y_3 = r_ab_y_3 - sb_e_y[j + 3]; - float r_ab2_y_4 = r_ab_y_4 - sb_e_y[j + 4]; - float r_ab2_y_5 = r_ab_y_5 - sb_e_y[j + 5]; - float r_ab2_y_6 = r_ab_y_6 - sb_e_y[j + 6]; - float r_ab2_y_7 = r_ab_y_7 - sb_e_y[j + 7]; - float r_ab2_y_8 = r_ab_y_8 - sb_e_y[j + 8]; - float r_ab2_y_9 = r_ab_y_9 - sb_e_y[j + 9]; - float r_ab2_y_10 = r_ab_y_10 - sb_e_y[j + 10]; - float r_ab2_y_11 = r_ab_y_11 - sb_e_y[j + 11]; - float r_ab2_y_12 = r_ab_y_12 - sb_e_y[j + 12]; - float r_ab2_y_13 = r_ab_y_13 - sb_e_y[j + 13]; - float r_ab2_y_14 = r_ab_y_14 - sb_e_y[j + 14]; - float r_ab2_y_15 = r_ab_y_15 - sb_e_y[j + 15]; - - float r_ab2_norm_0 = sqrt(r_ab2_x_0 * r_ab2_x_0 + r_ab2_y_0 * r_ab2_y_0); - float r_ab2_norm_1 = sqrt(r_ab2_x_1 * r_ab2_x_1 + r_ab2_y_1 * r_ab2_y_1); - float r_ab2_norm_2 = sqrt(r_ab2_x_2 * r_ab2_x_2 + r_ab2_y_2 * r_ab2_y_2); - float r_ab2_norm_3 = sqrt(r_ab2_x_3 * r_ab2_x_3 + r_ab2_y_3 * r_ab2_y_3); - float r_ab2_norm_4 = sqrt(r_ab2_x_4 * r_ab2_x_4 + r_ab2_y_4 * r_ab2_y_4); - float r_ab2_norm_5 = sqrt(r_ab2_x_5 * r_ab2_x_5 + r_ab2_y_5 * r_ab2_y_5); - float r_ab2_norm_6 = sqrt(r_ab2_x_6 * r_ab2_x_6 + r_ab2_y_6 * r_ab2_y_6); - float r_ab2_norm_7 = sqrt(r_ab2_x_7 * r_ab2_x_7 + r_ab2_y_7 * r_ab2_y_7); - float r_ab2_norm_8 = sqrt(r_ab2_x_8 * r_ab2_x_8 + r_ab2_y_8 * r_ab2_y_8); - float r_ab2_norm_9 = sqrt(r_ab2_x_9 * r_ab2_x_9 + r_ab2_y_9 * r_ab2_y_9); - float r_ab2_norm_10 = sqrt(r_ab2_x_10 * r_ab2_x_10 + r_ab2_y_10 * r_ab2_y_10); - float r_ab2_norm_11 = sqrt(r_ab2_x_11 * r_ab2_x_11 + r_ab2_y_11 * r_ab2_y_11); - float r_ab2_norm_12 = sqrt(r_ab2_x_12 * r_ab2_x_12 + r_ab2_y_12 * r_ab2_y_12); - float r_ab2_norm_13 = sqrt(r_ab2_x_13 * r_ab2_x_13 + r_ab2_y_13 * r_ab2_y_13); - float r_ab2_norm_14 = sqrt(r_ab2_x_14 * r_ab2_x_14 + r_ab2_y_14 * r_ab2_y_14); - float r_ab2_norm_15 = sqrt(r_ab2_x_15 * r_ab2_x_15 + r_ab2_y_15 * r_ab2_y_15); - - r_ab2_norm_0 = r_ab2_norm_0 > EPS ? r_ab2_norm_0 : EPS; - r_ab2_norm_1 = r_ab2_norm_1 > EPS ? r_ab2_norm_1 : EPS; - r_ab2_norm_2 = r_ab2_norm_2 > EPS ? r_ab2_norm_2 : EPS; - r_ab2_norm_3 = r_ab2_norm_3 > EPS ? r_ab2_norm_3 : EPS; - r_ab2_norm_4 = r_ab2_norm_4 > EPS ? r_ab2_norm_4 : EPS; - r_ab2_norm_5 = r_ab2_norm_5 > EPS ? r_ab2_norm_5 : EPS; - r_ab2_norm_6 = r_ab2_norm_6 > EPS ? r_ab2_norm_6 : EPS; - r_ab2_norm_7 = r_ab2_norm_7 > EPS ? r_ab2_norm_7 : EPS; - r_ab2_norm_8 = r_ab2_norm_8 > EPS ? r_ab2_norm_8 : EPS; - r_ab2_norm_9 = r_ab2_norm_9 > EPS ? r_ab2_norm_9 : EPS; - r_ab2_norm_10 = r_ab2_norm_10 > EPS ? r_ab2_norm_10 : EPS; - r_ab2_norm_11 = r_ab2_norm_11 > EPS ? r_ab2_norm_11 : EPS; - r_ab2_norm_12 = r_ab2_norm_12 > EPS ? r_ab2_norm_12 : EPS; - r_ab2_norm_13 = r_ab2_norm_13 > EPS ? r_ab2_norm_13 : EPS; - r_ab2_norm_14 = r_ab2_norm_14 > EPS ? r_ab2_norm_14 : EPS; - r_ab2_norm_15 = r_ab2_norm_15 > EPS ? r_ab2_norm_15 : EPS; - - float r_ab_norm_sum_0 = r_ab_norm_0 + r_ab2_norm_0; - float r_ab_norm_sum_1 = r_ab_norm_1 + r_ab2_norm_1; - float r_ab_norm_sum_2 = r_ab_norm_2 + r_ab2_norm_2; - float r_ab_norm_sum_3 = r_ab_norm_3 + r_ab2_norm_3; - float r_ab_norm_sum_4 = r_ab_norm_4 + r_ab2_norm_4; - float r_ab_norm_sum_5 = r_ab_norm_5 + r_ab2_norm_5; - float r_ab_norm_sum_6 = r_ab_norm_6 + r_ab2_norm_6; - float r_ab_norm_sum_7 = r_ab_norm_7 + r_ab2_norm_7; - float r_ab_norm_sum_8 = r_ab_norm_8 + r_ab2_norm_8; - float r_ab_norm_sum_9 = r_ab_norm_9 + r_ab2_norm_9; - float r_ab_norm_sum_10 = r_ab_norm_10 + r_ab2_norm_10; - float r_ab_norm_sum_11 = r_ab_norm_11 + r_ab2_norm_11; - float r_ab_norm_sum_12 = r_ab_norm_12 + r_ab2_norm_12; - float r_ab_norm_sum_13 = r_ab_norm_13 + r_ab2_norm_13; - float r_ab_norm_sum_14 = r_ab_norm_14 + r_ab2_norm_14; - float r_ab_norm_sum_15 = r_ab_norm_15 + r_ab2_norm_15; - - float two_b_sq_0 = r_ab_norm_sum_0 * r_ab_norm_sum_0 - sb_sq[j]; - float two_b_sq_1 = r_ab_norm_sum_1 * r_ab_norm_sum_1 - sb_sq[j + 1]; - float two_b_sq_2 = r_ab_norm_sum_2 * r_ab_norm_sum_2 - sb_sq[j + 2]; - float two_b_sq_3 = r_ab_norm_sum_3 * r_ab_norm_sum_3 - sb_sq[j + 3]; - float two_b_sq_4 = r_ab_norm_sum_4 * r_ab_norm_sum_4 - sb_sq[j + 4]; - float two_b_sq_5 = r_ab_norm_sum_5 * r_ab_norm_sum_5 - sb_sq[j + 5]; - float two_b_sq_6 = r_ab_norm_sum_6 * r_ab_norm_sum_6 - sb_sq[j + 6]; - float two_b_sq_7 = r_ab_norm_sum_7 * r_ab_norm_sum_7 - sb_sq[j + 7]; - float two_b_sq_8 = r_ab_norm_sum_8 * r_ab_norm_sum_8 - sb_sq[j + 8]; - float two_b_sq_9 = r_ab_norm_sum_9 * r_ab_norm_sum_9 - sb_sq[j + 9]; - float two_b_sq_10 = r_ab_norm_sum_10 * r_ab_norm_sum_10 - sb_sq[j + 10]; - float two_b_sq_11 = r_ab_norm_sum_11 * r_ab_norm_sum_11 - sb_sq[j + 11]; - float two_b_sq_12 = r_ab_norm_sum_12 * r_ab_norm_sum_12 - sb_sq[j + 12]; - float two_b_sq_13 = r_ab_norm_sum_13 * r_ab_norm_sum_13 - sb_sq[j + 13]; - float two_b_sq_14 = r_ab_norm_sum_14 * r_ab_norm_sum_14 - sb_sq[j + 14]; - float two_b_sq_15 = r_ab_norm_sum_15 * r_ab_norm_sum_15 - sb_sq[j + 15]; - - two_b_sq_0 = two_b_sq_0 > EPS_SQ ? two_b_sq_0 : EPS_SQ; - two_b_sq_1 = two_b_sq_1 > EPS_SQ ? two_b_sq_1 : EPS_SQ; - two_b_sq_2 = two_b_sq_2 > EPS_SQ ? two_b_sq_2 : EPS_SQ; - two_b_sq_3 = two_b_sq_3 > EPS_SQ ? two_b_sq_3 : EPS_SQ; - two_b_sq_4 = two_b_sq_4 > EPS_SQ ? two_b_sq_4 : EPS_SQ; - two_b_sq_5 = two_b_sq_5 > EPS_SQ ? two_b_sq_5 : EPS_SQ; - two_b_sq_6 = two_b_sq_6 > EPS_SQ ? two_b_sq_6 : EPS_SQ; - two_b_sq_7 = two_b_sq_7 > EPS_SQ ? two_b_sq_7 : EPS_SQ; - two_b_sq_8 = two_b_sq_8 > EPS_SQ ? two_b_sq_8 : EPS_SQ; - two_b_sq_9 = two_b_sq_9 > EPS_SQ ? two_b_sq_9 : EPS_SQ; - two_b_sq_10 = two_b_sq_10 > EPS_SQ ? two_b_sq_10 : EPS_SQ; - two_b_sq_11 = two_b_sq_11 > EPS_SQ ? two_b_sq_11 : EPS_SQ; - two_b_sq_12 = two_b_sq_12 > EPS_SQ ? two_b_sq_12 : EPS_SQ; - two_b_sq_13 = two_b_sq_13 > EPS_SQ ? two_b_sq_13 : EPS_SQ; - two_b_sq_14 = two_b_sq_14 > EPS_SQ ? two_b_sq_14 : EPS_SQ; - two_b_sq_15 = two_b_sq_15 > EPS_SQ ? two_b_sq_15 : EPS_SQ; - - float two_b_0 = sqrt(two_b_sq_0); - float two_b_1 = sqrt(two_b_sq_1); - float two_b_2 = sqrt(two_b_sq_2); - float two_b_3 = sqrt(two_b_sq_3); - float two_b_4 = sqrt(two_b_sq_4); - float two_b_5 = sqrt(two_b_sq_5); - float two_b_6 = sqrt(two_b_sq_6); - float two_b_7 = sqrt(two_b_sq_7); - float two_b_8 = sqrt(two_b_sq_8); - float two_b_9 = sqrt(two_b_sq_9); - float two_b_10 = sqrt(two_b_sq_10); - float two_b_11 = sqrt(two_b_sq_11); - float two_b_12 = sqrt(two_b_sq_12); - float two_b_13 = sqrt(two_b_sq_13); - float two_b_14 = sqrt(two_b_sq_14); - float two_b_15 = sqrt(two_b_sq_15); - - float scalar_mult_common_0 = (r_ab_norm_sum_0 / (two_b_0 * r_ab_norm_0 * r_ab2_norm_0)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_0 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_1 = (r_ab_norm_sum_1 / (two_b_1 * r_ab_norm_1 * r_ab2_norm_1)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_1 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_2 = (r_ab_norm_sum_2 / (two_b_2 * r_ab_norm_2 * r_ab2_norm_2)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_2 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_3 = (r_ab_norm_sum_3 / (two_b_3 * r_ab_norm_3 * r_ab2_norm_3)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_3 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_4 = (r_ab_norm_sum_4 / (two_b_4 * r_ab_norm_4 * r_ab2_norm_4)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_4 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_5 = (r_ab_norm_sum_5 / (two_b_5 * r_ab_norm_5 * r_ab2_norm_5)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_5 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_6 = (r_ab_norm_sum_6 / (two_b_6 * r_ab_norm_6 * r_ab2_norm_6)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_6 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_7 = (r_ab_norm_sum_7 / (two_b_7 * r_ab_norm_7 * r_ab2_norm_7)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_7 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_8 = (r_ab_norm_sum_8 / (two_b_8 * r_ab_norm_8 * r_ab2_norm_8)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_8 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_9 = (r_ab_norm_sum_9 / (two_b_9 * r_ab_norm_9 * r_ab2_norm_9)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_9 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_10 = (r_ab_norm_sum_10 / (two_b_10 * r_ab_norm_10 * r_ab2_norm_10)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_10 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_11 = (r_ab_norm_sum_11 / (two_b_11 * r_ab_norm_11 * r_ab2_norm_11)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_11 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_12 = (r_ab_norm_sum_12 / (two_b_12 * r_ab_norm_12 * r_ab2_norm_12)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_12 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_13 = (r_ab_norm_sum_13 / (two_b_13 * r_ab_norm_13 * r_ab2_norm_13)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_13 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_14 = (r_ab_norm_sum_14 / (two_b_14 * r_ab_norm_14 * r_ab2_norm_14)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_14 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_15 = (r_ab_norm_sum_15 / (two_b_15 * r_ab_norm_15 * r_ab2_norm_15)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_15 * NEG_TWO_SIGMA_INV)); - - float scalar_mult_r_ab_0 = scalar_mult_common_0 * r_ab2_norm_0; - float scalar_mult_r_ab_1 = scalar_mult_common_1 * r_ab2_norm_1; - float scalar_mult_r_ab_2 = scalar_mult_common_2 * r_ab2_norm_2; - float scalar_mult_r_ab_3 = scalar_mult_common_3 * r_ab2_norm_3; - float scalar_mult_r_ab_4 = scalar_mult_common_4 * r_ab2_norm_4; - float scalar_mult_r_ab_5 = scalar_mult_common_5 * r_ab2_norm_5; - float scalar_mult_r_ab_6 = scalar_mult_common_6 * r_ab2_norm_6; - float scalar_mult_r_ab_7 = scalar_mult_common_7 * r_ab2_norm_7; - float scalar_mult_r_ab_8 = scalar_mult_common_8 * r_ab2_norm_8; - float scalar_mult_r_ab_9 = scalar_mult_common_9 * r_ab2_norm_9; - float scalar_mult_r_ab_10 = scalar_mult_common_10 * r_ab2_norm_10; - float scalar_mult_r_ab_11 = scalar_mult_common_11 * r_ab2_norm_11; - float scalar_mult_r_ab_12 = scalar_mult_common_12 * r_ab2_norm_12; - float scalar_mult_r_ab_13 = scalar_mult_common_13 * r_ab2_norm_13; - float scalar_mult_r_ab_14 = scalar_mult_common_14 * r_ab2_norm_14; - float scalar_mult_r_ab_15 = scalar_mult_common_15 * r_ab2_norm_15; - - float scalar_mult_r_ab2_0 = scalar_mult_common_0 * r_ab_norm_0; - float scalar_mult_r_ab2_1 = scalar_mult_common_1 * r_ab_norm_1; - float scalar_mult_r_ab2_2 = scalar_mult_common_2 * r_ab_norm_2; - float scalar_mult_r_ab2_3 = scalar_mult_common_3 * r_ab_norm_3; - float scalar_mult_r_ab2_4 = scalar_mult_common_4 * r_ab_norm_4; - float scalar_mult_r_ab2_5 = scalar_mult_common_5 * r_ab_norm_5; - float scalar_mult_r_ab2_6 = scalar_mult_common_6 * r_ab_norm_6; - float scalar_mult_r_ab2_7 = scalar_mult_common_7 * r_ab_norm_7; - float scalar_mult_r_ab2_8 = scalar_mult_common_8 * r_ab_norm_8; - float scalar_mult_r_ab2_9 = scalar_mult_common_9 * r_ab_norm_9; - float scalar_mult_r_ab2_10 = scalar_mult_common_10 * r_ab_norm_10; - float scalar_mult_r_ab2_11 = scalar_mult_common_11 * r_ab_norm_11; - float scalar_mult_r_ab2_12 = scalar_mult_common_12 * r_ab_norm_12; - float scalar_mult_r_ab2_13 = scalar_mult_common_13 * r_ab_norm_13; - float scalar_mult_r_ab2_14 = scalar_mult_common_14 * r_ab_norm_14; - float scalar_mult_r_ab2_15 = scalar_mult_common_15 * r_ab_norm_15; - - float f_alpha_beta_neg_x_0 = r_ab_x_0 * scalar_mult_r_ab_0 + r_ab2_x_0 * scalar_mult_r_ab2_0; - float f_alpha_beta_neg_x_1 = r_ab_x_1 * scalar_mult_r_ab_1 + r_ab2_x_1 * scalar_mult_r_ab2_1; - float f_alpha_beta_neg_x_2 = r_ab_x_2 * scalar_mult_r_ab_2 + r_ab2_x_2 * scalar_mult_r_ab2_2; - float f_alpha_beta_neg_x_3 = r_ab_x_3 * scalar_mult_r_ab_3 + r_ab2_x_3 * scalar_mult_r_ab2_3; - float f_alpha_beta_neg_x_4 = r_ab_x_4 * scalar_mult_r_ab_4 + r_ab2_x_4 * scalar_mult_r_ab2_4; - float f_alpha_beta_neg_x_5 = r_ab_x_5 * scalar_mult_r_ab_5 + r_ab2_x_5 * scalar_mult_r_ab2_5; - float f_alpha_beta_neg_x_6 = r_ab_x_6 * scalar_mult_r_ab_6 + r_ab2_x_6 * scalar_mult_r_ab2_6; - float f_alpha_beta_neg_x_7 = r_ab_x_7 * scalar_mult_r_ab_7 + r_ab2_x_7 * scalar_mult_r_ab2_7; - float f_alpha_beta_neg_x_8 = r_ab_x_8 * scalar_mult_r_ab_8 + r_ab2_x_8 * scalar_mult_r_ab2_8; - float f_alpha_beta_neg_x_9 = r_ab_x_9 * scalar_mult_r_ab_9 + r_ab2_x_9 * scalar_mult_r_ab2_9; - float f_alpha_beta_neg_x_10 = r_ab_x_10 * scalar_mult_r_ab_10 + r_ab2_x_10 * scalar_mult_r_ab2_10; - float f_alpha_beta_neg_x_11 = r_ab_x_11 * scalar_mult_r_ab_11 + r_ab2_x_11 * scalar_mult_r_ab2_11; - float f_alpha_beta_neg_x_12 = r_ab_x_12 * scalar_mult_r_ab_12 + r_ab2_x_12 * scalar_mult_r_ab2_12; - float f_alpha_beta_neg_x_13 = r_ab_x_13 * scalar_mult_r_ab_13 + r_ab2_x_13 * scalar_mult_r_ab2_13; - float f_alpha_beta_neg_x_14 = r_ab_x_14 * scalar_mult_r_ab_14 + r_ab2_x_14 * scalar_mult_r_ab2_14; - float f_alpha_beta_neg_x_15 = r_ab_x_15 * scalar_mult_r_ab_15 + r_ab2_x_15 * scalar_mult_r_ab2_15; - - float f_alpha_beta_neg_y_0 = r_ab_y_0 * scalar_mult_r_ab_0 + r_ab2_y_0 * scalar_mult_r_ab2_0; - float f_alpha_beta_neg_y_1 = r_ab_y_1 * scalar_mult_r_ab_1 + r_ab2_y_1 * scalar_mult_r_ab2_1; - float f_alpha_beta_neg_y_2 = r_ab_y_2 * scalar_mult_r_ab_2 + r_ab2_y_2 * scalar_mult_r_ab2_2; - float f_alpha_beta_neg_y_3 = r_ab_y_3 * scalar_mult_r_ab_3 + r_ab2_y_3 * scalar_mult_r_ab2_3; - float f_alpha_beta_neg_y_4 = r_ab_y_4 * scalar_mult_r_ab_4 + r_ab2_y_4 * scalar_mult_r_ab2_4; - float f_alpha_beta_neg_y_5 = r_ab_y_5 * scalar_mult_r_ab_5 + r_ab2_y_5 * scalar_mult_r_ab2_5; - float f_alpha_beta_neg_y_6 = r_ab_y_6 * scalar_mult_r_ab_6 + r_ab2_y_6 * scalar_mult_r_ab2_6; - float f_alpha_beta_neg_y_7 = r_ab_y_7 * scalar_mult_r_ab_7 + r_ab2_y_7 * scalar_mult_r_ab2_7; - float f_alpha_beta_neg_y_8 = r_ab_y_8 * scalar_mult_r_ab_8 + r_ab2_y_8 * scalar_mult_r_ab2_8; - float f_alpha_beta_neg_y_9 = r_ab_y_9 * scalar_mult_r_ab_9 + r_ab2_y_9 * scalar_mult_r_ab2_9; - float f_alpha_beta_neg_y_10 = r_ab_y_10 * scalar_mult_r_ab_10 + r_ab2_y_10 * scalar_mult_r_ab2_10; - float f_alpha_beta_neg_y_11 = r_ab_y_11 * scalar_mult_r_ab_11 + r_ab2_y_11 * scalar_mult_r_ab2_11; - float f_alpha_beta_neg_y_12 = r_ab_y_12 * scalar_mult_r_ab_12 + r_ab2_y_12 * scalar_mult_r_ab2_12; - float f_alpha_beta_neg_y_13 = r_ab_y_13 * scalar_mult_r_ab_13 + r_ab2_y_13 * scalar_mult_r_ab2_13; - float f_alpha_beta_neg_y_14 = r_ab_y_14 * scalar_mult_r_ab_14 + r_ab2_y_14 * scalar_mult_r_ab2_14; - float f_alpha_beta_neg_y_15 = r_ab_y_15 * scalar_mult_r_ab_15 + r_ab2_y_15 * scalar_mult_r_ab2_15; - - float w_val_0, w_val_1, w_val_2, w_val_3, w_val_4, w_val_5, w_val_6, w_val_7; - float w_val_8, w_val_9, w_val_10, w_val_11, w_val_12, w_val_13, w_val_14, w_val_15; - - float f_norm_sq_0 = f_alpha_beta_neg_x_0 * f_alpha_beta_neg_x_0 + f_alpha_beta_neg_y_0 * f_alpha_beta_neg_y_0; - float f_norm_sq_1 = f_alpha_beta_neg_x_1 * f_alpha_beta_neg_x_1 + f_alpha_beta_neg_y_1 * f_alpha_beta_neg_y_1; - float f_norm_sq_2 = f_alpha_beta_neg_x_2 * f_alpha_beta_neg_x_2 + f_alpha_beta_neg_y_2 * f_alpha_beta_neg_y_2; - float f_norm_sq_3 = f_alpha_beta_neg_x_3 * f_alpha_beta_neg_x_3 + f_alpha_beta_neg_y_3 * f_alpha_beta_neg_y_3; - float f_norm_sq_4 = f_alpha_beta_neg_x_4 * f_alpha_beta_neg_x_4 + f_alpha_beta_neg_y_4 * f_alpha_beta_neg_y_4; - float f_norm_sq_5 = f_alpha_beta_neg_x_5 * f_alpha_beta_neg_x_5 + f_alpha_beta_neg_y_5 * f_alpha_beta_neg_y_5; - float f_norm_sq_6 = f_alpha_beta_neg_x_6 * f_alpha_beta_neg_x_6 + f_alpha_beta_neg_y_6 * f_alpha_beta_neg_y_6; - float f_norm_sq_7 = f_alpha_beta_neg_x_7 * f_alpha_beta_neg_x_7 + f_alpha_beta_neg_y_7 * f_alpha_beta_neg_y_7; - float f_norm_sq_8 = f_alpha_beta_neg_x_8 * f_alpha_beta_neg_x_8 + f_alpha_beta_neg_y_8 * f_alpha_beta_neg_y_8; - float f_norm_sq_9 = f_alpha_beta_neg_x_9 * f_alpha_beta_neg_x_9 + f_alpha_beta_neg_y_9 * f_alpha_beta_neg_y_9; - float f_norm_sq_10 = f_alpha_beta_neg_x_10 * f_alpha_beta_neg_x_10 + f_alpha_beta_neg_y_10 * f_alpha_beta_neg_y_10; - float f_norm_sq_11 = f_alpha_beta_neg_x_11 * f_alpha_beta_neg_x_11 + f_alpha_beta_neg_y_11 * f_alpha_beta_neg_y_11; - float f_norm_sq_12 = f_alpha_beta_neg_x_12 * f_alpha_beta_neg_x_12 + f_alpha_beta_neg_y_12 * f_alpha_beta_neg_y_12; - float f_norm_sq_13 = f_alpha_beta_neg_x_13 * f_alpha_beta_neg_x_13 + f_alpha_beta_neg_y_13 * f_alpha_beta_neg_y_13; - float f_norm_sq_14 = f_alpha_beta_neg_x_14 * f_alpha_beta_neg_x_14 + f_alpha_beta_neg_y_14 * f_alpha_beta_neg_y_14; - float f_norm_sq_15 = f_alpha_beta_neg_x_15 * f_alpha_beta_neg_x_15 + f_alpha_beta_neg_y_15 * f_alpha_beta_neg_y_15; - - float rhs_0 = f_norm_sq_0 * cos_phi_sq; - float rhs_1 = f_norm_sq_1 * cos_phi_sq; - float rhs_2 = f_norm_sq_2 * cos_phi_sq; - float rhs_3 = f_norm_sq_3 * cos_phi_sq; - float rhs_4 = f_norm_sq_4 * cos_phi_sq; - float rhs_5 = f_norm_sq_5 * cos_phi_sq; - float rhs_6 = f_norm_sq_6 * cos_phi_sq; - float rhs_7 = f_norm_sq_7 * cos_phi_sq; - float rhs_8 = f_norm_sq_8 * cos_phi_sq; - float rhs_9 = f_norm_sq_9 * cos_phi_sq; - float rhs_10 = f_norm_sq_10 * cos_phi_sq; - float rhs_11 = f_norm_sq_11 * cos_phi_sq; - float rhs_12 = f_norm_sq_12 * cos_phi_sq; - float rhs_13 = f_norm_sq_13 * cos_phi_sq; - float rhs_14 = f_norm_sq_14 * cos_phi_sq; - float rhs_15 = f_norm_sq_15 * cos_phi_sq; - - float e_dot_f_0 = e_x_i * f_alpha_beta_neg_x_0 + e_y_i * f_alpha_beta_neg_y_0; - float e_dot_f_1 = e_x_i * f_alpha_beta_neg_x_1 + e_y_i * f_alpha_beta_neg_y_1; - float e_dot_f_2 = e_x_i * f_alpha_beta_neg_x_2 + e_y_i * f_alpha_beta_neg_y_2; - float e_dot_f_3 = e_x_i * f_alpha_beta_neg_x_3 + e_y_i * f_alpha_beta_neg_y_3; - float e_dot_f_4 = e_x_i * f_alpha_beta_neg_x_4 + e_y_i * f_alpha_beta_neg_y_4; - float e_dot_f_5 = e_x_i * f_alpha_beta_neg_x_5 + e_y_i * f_alpha_beta_neg_y_5; - float e_dot_f_6 = e_x_i * f_alpha_beta_neg_x_6 + e_y_i * f_alpha_beta_neg_y_6; - float e_dot_f_7 = e_x_i * f_alpha_beta_neg_x_7 + e_y_i * f_alpha_beta_neg_y_7; - float e_dot_f_8 = e_x_i * f_alpha_beta_neg_x_8 + e_y_i * f_alpha_beta_neg_y_8; - float e_dot_f_9 = e_x_i * f_alpha_beta_neg_x_9 + e_y_i * f_alpha_beta_neg_y_9; - float e_dot_f_10 = e_x_i * f_alpha_beta_neg_x_10 + e_y_i * f_alpha_beta_neg_y_10; - float e_dot_f_11 = e_x_i * f_alpha_beta_neg_x_11 + e_y_i * f_alpha_beta_neg_y_11; - float e_dot_f_12 = e_x_i * f_alpha_beta_neg_x_12 + e_y_i * f_alpha_beta_neg_y_12; - float e_dot_f_13 = e_x_i * f_alpha_beta_neg_x_13 + e_y_i * f_alpha_beta_neg_y_13; - float e_dot_f_14 = e_x_i * f_alpha_beta_neg_x_14 + e_y_i * f_alpha_beta_neg_y_14; - float e_dot_f_15 = e_x_i * f_alpha_beta_neg_x_15 + e_y_i * f_alpha_beta_neg_y_15; - - float e_dot_f_sq_0 = e_dot_f_0 * e_dot_f_0; - float e_dot_f_sq_1 = e_dot_f_1 * e_dot_f_1; - float e_dot_f_sq_2 = e_dot_f_2 * e_dot_f_2; - float e_dot_f_sq_3 = e_dot_f_3 * e_dot_f_3; - float e_dot_f_sq_4 = e_dot_f_4 * e_dot_f_4; - float e_dot_f_sq_5 = e_dot_f_5 * e_dot_f_5; - float e_dot_f_sq_6 = e_dot_f_6 * e_dot_f_6; - float e_dot_f_sq_7 = e_dot_f_7 * e_dot_f_7; - float e_dot_f_sq_8 = e_dot_f_8 * e_dot_f_8; - float e_dot_f_sq_9 = e_dot_f_9 * e_dot_f_9; - float e_dot_f_sq_10 = e_dot_f_10 * e_dot_f_10; - float e_dot_f_sq_11 = e_dot_f_11 * e_dot_f_11; - float e_dot_f_sq_12 = e_dot_f_12 * e_dot_f_12; - float e_dot_f_sq_13 = e_dot_f_13 * e_dot_f_13; - float e_dot_f_sq_14 = e_dot_f_14 * e_dot_f_14; - float e_dot_f_sq_15 = e_dot_f_15 * e_dot_f_15; - - if (e_dot_f_0 >= 0.0 || e_dot_f_sq_0 <= rhs_0) - w_val_0 = dt_neg; - else - w_val_0 = c_neg_times_dt; - if (e_dot_f_1 >= 0.0 || e_dot_f_sq_1 <= rhs_1) - w_val_1 = dt_neg; - else - w_val_1 = c_neg_times_dt; - if (e_dot_f_2 >= 0.0 || e_dot_f_sq_2 <= rhs_2) - w_val_2 = dt_neg; - else - w_val_2 = c_neg_times_dt; - if (e_dot_f_3 >= 0.0 || e_dot_f_sq_3 <= rhs_3) - w_val_3 = dt_neg; - else - w_val_3 = c_neg_times_dt; - if (e_dot_f_4 >= 0.0 || e_dot_f_sq_4 <= rhs_4) - w_val_4 = dt_neg; - else - w_val_4 = c_neg_times_dt; - if (e_dot_f_5 >= 0.0 || e_dot_f_sq_5 <= rhs_5) - w_val_5 = dt_neg; - else - w_val_5 = c_neg_times_dt; - if (e_dot_f_6 >= 0.0 || e_dot_f_sq_6 <= rhs_6) - w_val_6 = dt_neg; - else - w_val_6 = c_neg_times_dt; - if (e_dot_f_7 >= 0.0 || e_dot_f_sq_7 <= rhs_7) - w_val_7 = dt_neg; - else - w_val_7 = c_neg_times_dt; - if (e_dot_f_8 >= 0.0 || e_dot_f_sq_8 <= rhs_8) - w_val_8 = dt_neg; - else - w_val_8 = c_neg_times_dt; - if (e_dot_f_9 >= 0.0 || e_dot_f_sq_9 <= rhs_9) - w_val_9 = dt_neg; - else - w_val_9 = c_neg_times_dt; - if (e_dot_f_10 >= 0.0 || e_dot_f_sq_10 <= rhs_10) - w_val_10 = dt_neg; - else - w_val_10 = c_neg_times_dt; - if (e_dot_f_11 >= 0.0 || e_dot_f_sq_11 <= rhs_11) - w_val_11 = dt_neg; - else - w_val_11 = c_neg_times_dt; - if (e_dot_f_12 >= 0.0 || e_dot_f_sq_12 <= rhs_12) - w_val_12 = dt_neg; - else - w_val_12 = c_neg_times_dt; - if (e_dot_f_13 >= 0.0 || e_dot_f_sq_13 <= rhs_13) - w_val_13 = dt_neg; - else - w_val_13 = c_neg_times_dt; - if (e_dot_f_14 >= 0.0 || e_dot_f_sq_14 <= rhs_14) - w_val_14 = dt_neg; - else - w_val_14 = c_neg_times_dt; - if (e_dot_f_15 >= 0.0 || e_dot_f_sq_15 <= rhs_15) - w_val_15 = dt_neg; - else - w_val_15 = c_neg_times_dt; - - acc_x_0 += f_alpha_beta_neg_x_0 * w_val_0; - acc_x_1 += f_alpha_beta_neg_x_1 * w_val_1; - acc_x_2 += f_alpha_beta_neg_x_2 * w_val_2; - acc_x_3 += f_alpha_beta_neg_x_3 * w_val_3; - acc_x_4 += f_alpha_beta_neg_x_4 * w_val_4; - acc_x_5 += f_alpha_beta_neg_x_5 * w_val_5; - acc_x_6 += f_alpha_beta_neg_x_6 * w_val_6; - acc_x_7 += f_alpha_beta_neg_x_7 * w_val_7; - acc_x_8 += f_alpha_beta_neg_x_8 * w_val_8; - acc_x_9 += f_alpha_beta_neg_x_9 * w_val_9; - acc_x_10 += f_alpha_beta_neg_x_10 * w_val_10; - acc_x_11 += f_alpha_beta_neg_x_11 * w_val_11; - acc_x_12 += f_alpha_beta_neg_x_12 * w_val_12; - acc_x_13 += f_alpha_beta_neg_x_13 * w_val_13; - acc_x_14 += f_alpha_beta_neg_x_14 * w_val_14; - acc_x_15 += f_alpha_beta_neg_x_15 * w_val_15; - acc_y_0 += f_alpha_beta_neg_y_0 * w_val_0; - acc_y_1 += f_alpha_beta_neg_y_1 * w_val_1; - acc_y_2 += f_alpha_beta_neg_y_2 * w_val_2; - acc_y_3 += f_alpha_beta_neg_y_3 * w_val_3; - acc_y_4 += f_alpha_beta_neg_y_4 * w_val_4; - acc_y_5 += f_alpha_beta_neg_y_5 * w_val_5; - acc_y_6 += f_alpha_beta_neg_y_6 * w_val_6; - acc_y_7 += f_alpha_beta_neg_y_7 * w_val_7; - acc_y_8 += f_alpha_beta_neg_y_8 * w_val_8; - acc_y_9 += f_alpha_beta_neg_y_9 * w_val_9; - acc_y_10 += f_alpha_beta_neg_y_10 * w_val_10; - acc_y_11 += f_alpha_beta_neg_y_11 * w_val_11; - acc_y_12 += f_alpha_beta_neg_y_12 * w_val_12; - acc_y_13 += f_alpha_beta_neg_y_13 * w_val_13; - acc_y_14 += f_alpha_beta_neg_y_14 * w_val_14; - acc_y_15 += f_alpha_beta_neg_y_15 * w_val_15; - } - - // remainder of the j < i half, single lane. # one j = 66 FLOPS - for (; j < i; j++) { - // lut lookup + -1* sign flip: not counted - float r_ab_x = -1 * r_ab_x_lut[j * n_p + i]; - float r_ab_y = -1 * r_ab_y_lut[j * n_p + i]; - float r_ab_norm = r_ab_norm_lut[j * n_p + i]; - - r_ab_norm = r_ab_norm > EPS ? r_ab_norm : EPS; - - // # 1 ADD - float r_ab2_x = r_ab_x - sb_e_x[j]; - // # 1 ADD - float r_ab2_y = r_ab_y - sb_e_y[j]; - - // # 1 ADD, 2 MULTs, 1 SQRT - float r_ab2_norm = sqrt(r_ab2_x * r_ab2_x + r_ab2_y * r_ab2_y); - r_ab2_norm = r_ab2_norm > EPS ? r_ab2_norm : EPS; - - // # 1 ADD - float r_ab_norm_sum = r_ab_norm + r_ab2_norm; - - // # 1 ADD, 1 MULT - float two_b_sq = r_ab_norm_sum * r_ab_norm_sum - sb_sq[j]; - two_b_sq = two_b_sq > EPS_SQ ? two_b_sq : EPS_SQ; - // # 1 SQRT - float two_b = sqrt(two_b_sq); - // # 5 MULTs, 1 DIV, 1 EXP - float scalar_mult_common = (r_ab_norm_sum / (two_b * r_ab_norm * r_ab2_norm)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b * NEG_TWO_SIGMA_INV)); - // # 1 MULT - float scalar_mult_r_ab = scalar_mult_common * r_ab2_norm; - // # 1 MULT - float scalar_mult_r_ab2 = scalar_mult_common * r_ab_norm; - - // # 1 ADD, 2 MULTs - float f_alpha_beta_neg_x = r_ab_x * scalar_mult_r_ab + r_ab2_x * scalar_mult_r_ab2; - // # 1 ADD, 2 MULTs - float f_alpha_beta_neg_y = r_ab_y * scalar_mult_r_ab + r_ab2_y * scalar_mult_r_ab2; - - float w_val; - - // # 1 ADD, 2 MULTs - float f_norm_sq = f_alpha_beta_neg_x * f_alpha_beta_neg_x + f_alpha_beta_neg_y * f_alpha_beta_neg_y; - // # 1 MULT - float rhs = f_norm_sq * cos_phi_sq; - // # 1 ADD, 2 MULTs - float e_dot_f = e_x[i] * f_alpha_beta_neg_x + e_y[i] * f_alpha_beta_neg_y; - // # 1 MULT - float e_dot_f_sq = e_dot_f * e_dot_f; - if (e_dot_f >= 0.0 || e_dot_f_sq <= rhs) - w_val = dt_neg; - else - w_val = c_neg_times_dt; - - // # 1 ADD, 1 MULT - f_alpha_dt_x += f_alpha_beta_neg_x * w_val; - // # 1 ADD, 1 MULT - f_alpha_dt_y += f_alpha_beta_neg_y * w_val; - } - - // reduction of the j < i accumulators. # K adds per line (K=16) => 32 ADDs - f_alpha_dt_x += acc_x_0 + acc_x_1 + acc_x_2 + acc_x_3 + acc_x_4 + acc_x_5 + acc_x_6 + acc_x_7 + acc_x_8 + acc_x_9 + acc_x_10 + acc_x_11 + acc_x_12 + acc_x_13 + acc_x_14 + acc_x_15; - f_alpha_dt_y += acc_y_0 + acc_y_1 + acc_y_2 + acc_y_3 + acc_y_4 + acc_y_5 + acc_y_6 + acc_y_7 + acc_y_8 + acc_y_9 + acc_y_10 + acc_y_11 + acc_y_12 + acc_y_13 + acc_y_14 + acc_y_15; - - acc_x_0 = 0.0f; - acc_x_1 = 0.0f; - acc_x_2 = 0.0f; - acc_x_3 = 0.0f; - acc_x_4 = 0.0f; - acc_x_5 = 0.0f; - acc_x_6 = 0.0f; - acc_x_7 = 0.0f; - acc_x_8 = 0.0f; - acc_x_9 = 0.0f; - acc_x_10 = 0.0f; - acc_x_11 = 0.0f; - acc_x_12 = 0.0f; - acc_x_13 = 0.0f; - acc_x_14 = 0.0f; - acc_x_15 = 0.0f; - acc_y_0 = 0.0f; - acc_y_1 = 0.0f; - acc_y_2 = 0.0f; - acc_y_3 = 0.0f; - acc_y_4 = 0.0f; - acc_y_5 = 0.0f; - acc_y_6 = 0.0f; - acc_y_7 = 0.0f; - acc_y_8 = 0.0f; - acc_y_9 = 0.0f; - acc_y_10 = 0.0f; - acc_y_11 = 0.0f; - acc_y_12 = 0.0f; - acc_y_13 = 0.0f; - acc_y_14 = 0.0f; - acc_y_15 = 0.0f; - - // ILP over the j > i half. # each lane = 66 FLOPS, K = 16 lanes per step - for (j = i + 1; j + 16 < n_p; j += 16) { - float r_ab_x_0 = r_ab_x_lut[i * n_p + j]; - float r_ab_x_1 = r_ab_x_lut[i * n_p + j + 1]; - float r_ab_x_2 = r_ab_x_lut[i * n_p + j + 2]; - float r_ab_x_3 = r_ab_x_lut[i * n_p + j + 3]; - float r_ab_x_4 = r_ab_x_lut[i * n_p + j + 4]; - float r_ab_x_5 = r_ab_x_lut[i * n_p + j + 5]; - float r_ab_x_6 = r_ab_x_lut[i * n_p + j + 6]; - float r_ab_x_7 = r_ab_x_lut[i * n_p + j + 7]; - float r_ab_x_8 = r_ab_x_lut[i * n_p + j + 8]; - float r_ab_x_9 = r_ab_x_lut[i * n_p + j + 9]; - float r_ab_x_10 = r_ab_x_lut[i * n_p + j + 10]; - float r_ab_x_11 = r_ab_x_lut[i * n_p + j + 11]; - float r_ab_x_12 = r_ab_x_lut[i * n_p + j + 12]; - float r_ab_x_13 = r_ab_x_lut[i * n_p + j + 13]; - float r_ab_x_14 = r_ab_x_lut[i * n_p + j + 14]; - float r_ab_x_15 = r_ab_x_lut[i * n_p + j + 15]; - - float r_ab_y_0 = r_ab_y_lut[i * n_p + j]; - float r_ab_y_1 = r_ab_y_lut[i * n_p + j + 1]; - float r_ab_y_2 = r_ab_y_lut[i * n_p + j + 2]; - float r_ab_y_3 = r_ab_y_lut[i * n_p + j + 3]; - float r_ab_y_4 = r_ab_y_lut[i * n_p + j + 4]; - float r_ab_y_5 = r_ab_y_lut[i * n_p + j + 5]; - float r_ab_y_6 = r_ab_y_lut[i * n_p + j + 6]; - float r_ab_y_7 = r_ab_y_lut[i * n_p + j + 7]; - float r_ab_y_8 = r_ab_y_lut[i * n_p + j + 8]; - float r_ab_y_9 = r_ab_y_lut[i * n_p + j + 9]; - float r_ab_y_10 = r_ab_y_lut[i * n_p + j + 10]; - float r_ab_y_11 = r_ab_y_lut[i * n_p + j + 11]; - float r_ab_y_12 = r_ab_y_lut[i * n_p + j + 12]; - float r_ab_y_13 = r_ab_y_lut[i * n_p + j + 13]; - float r_ab_y_14 = r_ab_y_lut[i * n_p + j + 14]; - float r_ab_y_15 = r_ab_y_lut[i * n_p + j + 15]; - - float r_ab_norm_0 = r_ab_norm_lut[i * n_p + j]; - float r_ab_norm_1 = r_ab_norm_lut[i * n_p + j + 1]; - float r_ab_norm_2 = r_ab_norm_lut[i * n_p + j + 2]; - float r_ab_norm_3 = r_ab_norm_lut[i * n_p + j + 3]; - float r_ab_norm_4 = r_ab_norm_lut[i * n_p + j + 4]; - float r_ab_norm_5 = r_ab_norm_lut[i * n_p + j + 5]; - float r_ab_norm_6 = r_ab_norm_lut[i * n_p + j + 6]; - float r_ab_norm_7 = r_ab_norm_lut[i * n_p + j + 7]; - float r_ab_norm_8 = r_ab_norm_lut[i * n_p + j + 8]; - float r_ab_norm_9 = r_ab_norm_lut[i * n_p + j + 9]; - float r_ab_norm_10 = r_ab_norm_lut[i * n_p + j + 10]; - float r_ab_norm_11 = r_ab_norm_lut[i * n_p + j + 11]; - float r_ab_norm_12 = r_ab_norm_lut[i * n_p + j + 12]; - float r_ab_norm_13 = r_ab_norm_lut[i * n_p + j + 13]; - float r_ab_norm_14 = r_ab_norm_lut[i * n_p + j + 14]; - float r_ab_norm_15 = r_ab_norm_lut[i * n_p + j + 15]; - - r_ab_norm_0 = r_ab_norm_0 > EPS ? r_ab_norm_0 : EPS; - r_ab_norm_1 = r_ab_norm_1 > EPS ? r_ab_norm_1 : EPS; - r_ab_norm_2 = r_ab_norm_2 > EPS ? r_ab_norm_2 : EPS; - r_ab_norm_3 = r_ab_norm_3 > EPS ? r_ab_norm_3 : EPS; - r_ab_norm_4 = r_ab_norm_4 > EPS ? r_ab_norm_4 : EPS; - r_ab_norm_5 = r_ab_norm_5 > EPS ? r_ab_norm_5 : EPS; - r_ab_norm_6 = r_ab_norm_6 > EPS ? r_ab_norm_6 : EPS; - r_ab_norm_7 = r_ab_norm_7 > EPS ? r_ab_norm_7 : EPS; - r_ab_norm_8 = r_ab_norm_8 > EPS ? r_ab_norm_8 : EPS; - r_ab_norm_9 = r_ab_norm_9 > EPS ? r_ab_norm_9 : EPS; - r_ab_norm_10 = r_ab_norm_10 > EPS ? r_ab_norm_10 : EPS; - r_ab_norm_11 = r_ab_norm_11 > EPS ? r_ab_norm_11 : EPS; - r_ab_norm_12 = r_ab_norm_12 > EPS ? r_ab_norm_12 : EPS; - r_ab_norm_13 = r_ab_norm_13 > EPS ? r_ab_norm_13 : EPS; - r_ab_norm_14 = r_ab_norm_14 > EPS ? r_ab_norm_14 : EPS; - r_ab_norm_15 = r_ab_norm_15 > EPS ? r_ab_norm_15 : EPS; - - float r_ab2_x_0 = r_ab_x_0 - sb_e_x[j]; - float r_ab2_x_1 = r_ab_x_1 - sb_e_x[j + 1]; - float r_ab2_x_2 = r_ab_x_2 - sb_e_x[j + 2]; - float r_ab2_x_3 = r_ab_x_3 - sb_e_x[j + 3]; - float r_ab2_x_4 = r_ab_x_4 - sb_e_x[j + 4]; - float r_ab2_x_5 = r_ab_x_5 - sb_e_x[j + 5]; - float r_ab2_x_6 = r_ab_x_6 - sb_e_x[j + 6]; - float r_ab2_x_7 = r_ab_x_7 - sb_e_x[j + 7]; - float r_ab2_x_8 = r_ab_x_8 - sb_e_x[j + 8]; - float r_ab2_x_9 = r_ab_x_9 - sb_e_x[j + 9]; - float r_ab2_x_10 = r_ab_x_10 - sb_e_x[j + 10]; - float r_ab2_x_11 = r_ab_x_11 - sb_e_x[j + 11]; - float r_ab2_x_12 = r_ab_x_12 - sb_e_x[j + 12]; - float r_ab2_x_13 = r_ab_x_13 - sb_e_x[j + 13]; - float r_ab2_x_14 = r_ab_x_14 - sb_e_x[j + 14]; - float r_ab2_x_15 = r_ab_x_15 - sb_e_x[j + 15]; - - float r_ab2_y_0 = r_ab_y_0 - sb_e_y[j]; - float r_ab2_y_1 = r_ab_y_1 - sb_e_y[j + 1]; - float r_ab2_y_2 = r_ab_y_2 - sb_e_y[j + 2]; - float r_ab2_y_3 = r_ab_y_3 - sb_e_y[j + 3]; - float r_ab2_y_4 = r_ab_y_4 - sb_e_y[j + 4]; - float r_ab2_y_5 = r_ab_y_5 - sb_e_y[j + 5]; - float r_ab2_y_6 = r_ab_y_6 - sb_e_y[j + 6]; - float r_ab2_y_7 = r_ab_y_7 - sb_e_y[j + 7]; - float r_ab2_y_8 = r_ab_y_8 - sb_e_y[j + 8]; - float r_ab2_y_9 = r_ab_y_9 - sb_e_y[j + 9]; - float r_ab2_y_10 = r_ab_y_10 - sb_e_y[j + 10]; - float r_ab2_y_11 = r_ab_y_11 - sb_e_y[j + 11]; - float r_ab2_y_12 = r_ab_y_12 - sb_e_y[j + 12]; - float r_ab2_y_13 = r_ab_y_13 - sb_e_y[j + 13]; - float r_ab2_y_14 = r_ab_y_14 - sb_e_y[j + 14]; - float r_ab2_y_15 = r_ab_y_15 - sb_e_y[j + 15]; - - float r_ab2_norm_0 = sqrt(r_ab2_x_0 * r_ab2_x_0 + r_ab2_y_0 * r_ab2_y_0); - float r_ab2_norm_1 = sqrt(r_ab2_x_1 * r_ab2_x_1 + r_ab2_y_1 * r_ab2_y_1); - float r_ab2_norm_2 = sqrt(r_ab2_x_2 * r_ab2_x_2 + r_ab2_y_2 * r_ab2_y_2); - float r_ab2_norm_3 = sqrt(r_ab2_x_3 * r_ab2_x_3 + r_ab2_y_3 * r_ab2_y_3); - float r_ab2_norm_4 = sqrt(r_ab2_x_4 * r_ab2_x_4 + r_ab2_y_4 * r_ab2_y_4); - float r_ab2_norm_5 = sqrt(r_ab2_x_5 * r_ab2_x_5 + r_ab2_y_5 * r_ab2_y_5); - float r_ab2_norm_6 = sqrt(r_ab2_x_6 * r_ab2_x_6 + r_ab2_y_6 * r_ab2_y_6); - float r_ab2_norm_7 = sqrt(r_ab2_x_7 * r_ab2_x_7 + r_ab2_y_7 * r_ab2_y_7); - float r_ab2_norm_8 = sqrt(r_ab2_x_8 * r_ab2_x_8 + r_ab2_y_8 * r_ab2_y_8); - float r_ab2_norm_9 = sqrt(r_ab2_x_9 * r_ab2_x_9 + r_ab2_y_9 * r_ab2_y_9); - float r_ab2_norm_10 = sqrt(r_ab2_x_10 * r_ab2_x_10 + r_ab2_y_10 * r_ab2_y_10); - float r_ab2_norm_11 = sqrt(r_ab2_x_11 * r_ab2_x_11 + r_ab2_y_11 * r_ab2_y_11); - float r_ab2_norm_12 = sqrt(r_ab2_x_12 * r_ab2_x_12 + r_ab2_y_12 * r_ab2_y_12); - float r_ab2_norm_13 = sqrt(r_ab2_x_13 * r_ab2_x_13 + r_ab2_y_13 * r_ab2_y_13); - float r_ab2_norm_14 = sqrt(r_ab2_x_14 * r_ab2_x_14 + r_ab2_y_14 * r_ab2_y_14); - float r_ab2_norm_15 = sqrt(r_ab2_x_15 * r_ab2_x_15 + r_ab2_y_15 * r_ab2_y_15); - - r_ab2_norm_0 = r_ab2_norm_0 > EPS ? r_ab2_norm_0 : EPS; - r_ab2_norm_1 = r_ab2_norm_1 > EPS ? r_ab2_norm_1 : EPS; - r_ab2_norm_2 = r_ab2_norm_2 > EPS ? r_ab2_norm_2 : EPS; - r_ab2_norm_3 = r_ab2_norm_3 > EPS ? r_ab2_norm_3 : EPS; - r_ab2_norm_4 = r_ab2_norm_4 > EPS ? r_ab2_norm_4 : EPS; - r_ab2_norm_5 = r_ab2_norm_5 > EPS ? r_ab2_norm_5 : EPS; - r_ab2_norm_6 = r_ab2_norm_6 > EPS ? r_ab2_norm_6 : EPS; - r_ab2_norm_7 = r_ab2_norm_7 > EPS ? r_ab2_norm_7 : EPS; - r_ab2_norm_8 = r_ab2_norm_8 > EPS ? r_ab2_norm_8 : EPS; - r_ab2_norm_9 = r_ab2_norm_9 > EPS ? r_ab2_norm_9 : EPS; - r_ab2_norm_10 = r_ab2_norm_10 > EPS ? r_ab2_norm_10 : EPS; - r_ab2_norm_11 = r_ab2_norm_11 > EPS ? r_ab2_norm_11 : EPS; - r_ab2_norm_12 = r_ab2_norm_12 > EPS ? r_ab2_norm_12 : EPS; - r_ab2_norm_13 = r_ab2_norm_13 > EPS ? r_ab2_norm_13 : EPS; - r_ab2_norm_14 = r_ab2_norm_14 > EPS ? r_ab2_norm_14 : EPS; - r_ab2_norm_15 = r_ab2_norm_15 > EPS ? r_ab2_norm_15 : EPS; - - float r_ab_norm_sum_0 = r_ab_norm_0 + r_ab2_norm_0; - float r_ab_norm_sum_1 = r_ab_norm_1 + r_ab2_norm_1; - float r_ab_norm_sum_2 = r_ab_norm_2 + r_ab2_norm_2; - float r_ab_norm_sum_3 = r_ab_norm_3 + r_ab2_norm_3; - float r_ab_norm_sum_4 = r_ab_norm_4 + r_ab2_norm_4; - float r_ab_norm_sum_5 = r_ab_norm_5 + r_ab2_norm_5; - float r_ab_norm_sum_6 = r_ab_norm_6 + r_ab2_norm_6; - float r_ab_norm_sum_7 = r_ab_norm_7 + r_ab2_norm_7; - float r_ab_norm_sum_8 = r_ab_norm_8 + r_ab2_norm_8; - float r_ab_norm_sum_9 = r_ab_norm_9 + r_ab2_norm_9; - float r_ab_norm_sum_10 = r_ab_norm_10 + r_ab2_norm_10; - float r_ab_norm_sum_11 = r_ab_norm_11 + r_ab2_norm_11; - float r_ab_norm_sum_12 = r_ab_norm_12 + r_ab2_norm_12; - float r_ab_norm_sum_13 = r_ab_norm_13 + r_ab2_norm_13; - float r_ab_norm_sum_14 = r_ab_norm_14 + r_ab2_norm_14; - float r_ab_norm_sum_15 = r_ab_norm_15 + r_ab2_norm_15; - - float two_b_sq_0 = r_ab_norm_sum_0 * r_ab_norm_sum_0 - sb_sq[j]; - float two_b_sq_1 = r_ab_norm_sum_1 * r_ab_norm_sum_1 - sb_sq[j + 1]; - float two_b_sq_2 = r_ab_norm_sum_2 * r_ab_norm_sum_2 - sb_sq[j + 2]; - float two_b_sq_3 = r_ab_norm_sum_3 * r_ab_norm_sum_3 - sb_sq[j + 3]; - float two_b_sq_4 = r_ab_norm_sum_4 * r_ab_norm_sum_4 - sb_sq[j + 4]; - float two_b_sq_5 = r_ab_norm_sum_5 * r_ab_norm_sum_5 - sb_sq[j + 5]; - float two_b_sq_6 = r_ab_norm_sum_6 * r_ab_norm_sum_6 - sb_sq[j + 6]; - float two_b_sq_7 = r_ab_norm_sum_7 * r_ab_norm_sum_7 - sb_sq[j + 7]; - float two_b_sq_8 = r_ab_norm_sum_8 * r_ab_norm_sum_8 - sb_sq[j + 8]; - float two_b_sq_9 = r_ab_norm_sum_9 * r_ab_norm_sum_9 - sb_sq[j + 9]; - float two_b_sq_10 = r_ab_norm_sum_10 * r_ab_norm_sum_10 - sb_sq[j + 10]; - float two_b_sq_11 = r_ab_norm_sum_11 * r_ab_norm_sum_11 - sb_sq[j + 11]; - float two_b_sq_12 = r_ab_norm_sum_12 * r_ab_norm_sum_12 - sb_sq[j + 12]; - float two_b_sq_13 = r_ab_norm_sum_13 * r_ab_norm_sum_13 - sb_sq[j + 13]; - float two_b_sq_14 = r_ab_norm_sum_14 * r_ab_norm_sum_14 - sb_sq[j + 14]; - float two_b_sq_15 = r_ab_norm_sum_15 * r_ab_norm_sum_15 - sb_sq[j + 15]; - - two_b_sq_0 = two_b_sq_0 > EPS_SQ ? two_b_sq_0 : EPS_SQ; - two_b_sq_1 = two_b_sq_1 > EPS_SQ ? two_b_sq_1 : EPS_SQ; - two_b_sq_2 = two_b_sq_2 > EPS_SQ ? two_b_sq_2 : EPS_SQ; - two_b_sq_3 = two_b_sq_3 > EPS_SQ ? two_b_sq_3 : EPS_SQ; - two_b_sq_4 = two_b_sq_4 > EPS_SQ ? two_b_sq_4 : EPS_SQ; - two_b_sq_5 = two_b_sq_5 > EPS_SQ ? two_b_sq_5 : EPS_SQ; - two_b_sq_6 = two_b_sq_6 > EPS_SQ ? two_b_sq_6 : EPS_SQ; - two_b_sq_7 = two_b_sq_7 > EPS_SQ ? two_b_sq_7 : EPS_SQ; - two_b_sq_8 = two_b_sq_8 > EPS_SQ ? two_b_sq_8 : EPS_SQ; - two_b_sq_9 = two_b_sq_9 > EPS_SQ ? two_b_sq_9 : EPS_SQ; - two_b_sq_10 = two_b_sq_10 > EPS_SQ ? two_b_sq_10 : EPS_SQ; - two_b_sq_11 = two_b_sq_11 > EPS_SQ ? two_b_sq_11 : EPS_SQ; - two_b_sq_12 = two_b_sq_12 > EPS_SQ ? two_b_sq_12 : EPS_SQ; - two_b_sq_13 = two_b_sq_13 > EPS_SQ ? two_b_sq_13 : EPS_SQ; - two_b_sq_14 = two_b_sq_14 > EPS_SQ ? two_b_sq_14 : EPS_SQ; - two_b_sq_15 = two_b_sq_15 > EPS_SQ ? two_b_sq_15 : EPS_SQ; - - float two_b_0 = sqrt(two_b_sq_0); - float two_b_1 = sqrt(two_b_sq_1); - float two_b_2 = sqrt(two_b_sq_2); - float two_b_3 = sqrt(two_b_sq_3); - float two_b_4 = sqrt(two_b_sq_4); - float two_b_5 = sqrt(two_b_sq_5); - float two_b_6 = sqrt(two_b_sq_6); - float two_b_7 = sqrt(two_b_sq_7); - float two_b_8 = sqrt(two_b_sq_8); - float two_b_9 = sqrt(two_b_sq_9); - float two_b_10 = sqrt(two_b_sq_10); - float two_b_11 = sqrt(two_b_sq_11); - float two_b_12 = sqrt(two_b_sq_12); - float two_b_13 = sqrt(two_b_sq_13); - float two_b_14 = sqrt(two_b_sq_14); - float two_b_15 = sqrt(two_b_sq_15); - - float scalar_mult_common_0 = (r_ab_norm_sum_0 / (two_b_0 * r_ab_norm_0 * r_ab2_norm_0)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_0 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_1 = (r_ab_norm_sum_1 / (two_b_1 * r_ab_norm_1 * r_ab2_norm_1)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_1 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_2 = (r_ab_norm_sum_2 / (two_b_2 * r_ab_norm_2 * r_ab2_norm_2)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_2 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_3 = (r_ab_norm_sum_3 / (two_b_3 * r_ab_norm_3 * r_ab2_norm_3)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_3 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_4 = (r_ab_norm_sum_4 / (two_b_4 * r_ab_norm_4 * r_ab2_norm_4)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_4 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_5 = (r_ab_norm_sum_5 / (two_b_5 * r_ab_norm_5 * r_ab2_norm_5)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_5 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_6 = (r_ab_norm_sum_6 / (two_b_6 * r_ab_norm_6 * r_ab2_norm_6)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_6 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_7 = (r_ab_norm_sum_7 / (two_b_7 * r_ab_norm_7 * r_ab2_norm_7)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_7 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_8 = (r_ab_norm_sum_8 / (two_b_8 * r_ab_norm_8 * r_ab2_norm_8)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_8 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_9 = (r_ab_norm_sum_9 / (two_b_9 * r_ab_norm_9 * r_ab2_norm_9)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_9 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_10 = (r_ab_norm_sum_10 / (two_b_10 * r_ab_norm_10 * r_ab2_norm_10)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_10 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_11 = (r_ab_norm_sum_11 / (two_b_11 * r_ab_norm_11 * r_ab2_norm_11)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_11 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_12 = (r_ab_norm_sum_12 / (two_b_12 * r_ab_norm_12 * r_ab2_norm_12)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_12 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_13 = (r_ab_norm_sum_13 / (two_b_13 * r_ab_norm_13 * r_ab2_norm_13)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_13 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_14 = (r_ab_norm_sum_14 / (two_b_14 * r_ab_norm_14 * r_ab2_norm_14)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_14 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_15 = (r_ab_norm_sum_15 / (two_b_15 * r_ab_norm_15 * r_ab2_norm_15)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_15 * NEG_TWO_SIGMA_INV)); - - float scalar_mult_r_ab_0 = scalar_mult_common_0 * r_ab2_norm_0; - float scalar_mult_r_ab_1 = scalar_mult_common_1 * r_ab2_norm_1; - float scalar_mult_r_ab_2 = scalar_mult_common_2 * r_ab2_norm_2; - float scalar_mult_r_ab_3 = scalar_mult_common_3 * r_ab2_norm_3; - float scalar_mult_r_ab_4 = scalar_mult_common_4 * r_ab2_norm_4; - float scalar_mult_r_ab_5 = scalar_mult_common_5 * r_ab2_norm_5; - float scalar_mult_r_ab_6 = scalar_mult_common_6 * r_ab2_norm_6; - float scalar_mult_r_ab_7 = scalar_mult_common_7 * r_ab2_norm_7; - float scalar_mult_r_ab_8 = scalar_mult_common_8 * r_ab2_norm_8; - float scalar_mult_r_ab_9 = scalar_mult_common_9 * r_ab2_norm_9; - float scalar_mult_r_ab_10 = scalar_mult_common_10 * r_ab2_norm_10; - float scalar_mult_r_ab_11 = scalar_mult_common_11 * r_ab2_norm_11; - float scalar_mult_r_ab_12 = scalar_mult_common_12 * r_ab2_norm_12; - float scalar_mult_r_ab_13 = scalar_mult_common_13 * r_ab2_norm_13; - float scalar_mult_r_ab_14 = scalar_mult_common_14 * r_ab2_norm_14; - float scalar_mult_r_ab_15 = scalar_mult_common_15 * r_ab2_norm_15; - - float scalar_mult_r_ab2_0 = scalar_mult_common_0 * r_ab_norm_0; - float scalar_mult_r_ab2_1 = scalar_mult_common_1 * r_ab_norm_1; - float scalar_mult_r_ab2_2 = scalar_mult_common_2 * r_ab_norm_2; - float scalar_mult_r_ab2_3 = scalar_mult_common_3 * r_ab_norm_3; - float scalar_mult_r_ab2_4 = scalar_mult_common_4 * r_ab_norm_4; - float scalar_mult_r_ab2_5 = scalar_mult_common_5 * r_ab_norm_5; - float scalar_mult_r_ab2_6 = scalar_mult_common_6 * r_ab_norm_6; - float scalar_mult_r_ab2_7 = scalar_mult_common_7 * r_ab_norm_7; - float scalar_mult_r_ab2_8 = scalar_mult_common_8 * r_ab_norm_8; - float scalar_mult_r_ab2_9 = scalar_mult_common_9 * r_ab_norm_9; - float scalar_mult_r_ab2_10 = scalar_mult_common_10 * r_ab_norm_10; - float scalar_mult_r_ab2_11 = scalar_mult_common_11 * r_ab_norm_11; - float scalar_mult_r_ab2_12 = scalar_mult_common_12 * r_ab_norm_12; - float scalar_mult_r_ab2_13 = scalar_mult_common_13 * r_ab_norm_13; - float scalar_mult_r_ab2_14 = scalar_mult_common_14 * r_ab_norm_14; - float scalar_mult_r_ab2_15 = scalar_mult_common_15 * r_ab_norm_15; - - float f_alpha_beta_neg_x_0 = r_ab_x_0 * scalar_mult_r_ab_0 + r_ab2_x_0 * scalar_mult_r_ab2_0; - float f_alpha_beta_neg_x_1 = r_ab_x_1 * scalar_mult_r_ab_1 + r_ab2_x_1 * scalar_mult_r_ab2_1; - float f_alpha_beta_neg_x_2 = r_ab_x_2 * scalar_mult_r_ab_2 + r_ab2_x_2 * scalar_mult_r_ab2_2; - float f_alpha_beta_neg_x_3 = r_ab_x_3 * scalar_mult_r_ab_3 + r_ab2_x_3 * scalar_mult_r_ab2_3; - float f_alpha_beta_neg_x_4 = r_ab_x_4 * scalar_mult_r_ab_4 + r_ab2_x_4 * scalar_mult_r_ab2_4; - float f_alpha_beta_neg_x_5 = r_ab_x_5 * scalar_mult_r_ab_5 + r_ab2_x_5 * scalar_mult_r_ab2_5; - float f_alpha_beta_neg_x_6 = r_ab_x_6 * scalar_mult_r_ab_6 + r_ab2_x_6 * scalar_mult_r_ab2_6; - float f_alpha_beta_neg_x_7 = r_ab_x_7 * scalar_mult_r_ab_7 + r_ab2_x_7 * scalar_mult_r_ab2_7; - float f_alpha_beta_neg_x_8 = r_ab_x_8 * scalar_mult_r_ab_8 + r_ab2_x_8 * scalar_mult_r_ab2_8; - float f_alpha_beta_neg_x_9 = r_ab_x_9 * scalar_mult_r_ab_9 + r_ab2_x_9 * scalar_mult_r_ab2_9; - float f_alpha_beta_neg_x_10 = r_ab_x_10 * scalar_mult_r_ab_10 + r_ab2_x_10 * scalar_mult_r_ab2_10; - float f_alpha_beta_neg_x_11 = r_ab_x_11 * scalar_mult_r_ab_11 + r_ab2_x_11 * scalar_mult_r_ab2_11; - float f_alpha_beta_neg_x_12 = r_ab_x_12 * scalar_mult_r_ab_12 + r_ab2_x_12 * scalar_mult_r_ab2_12; - float f_alpha_beta_neg_x_13 = r_ab_x_13 * scalar_mult_r_ab_13 + r_ab2_x_13 * scalar_mult_r_ab2_13; - float f_alpha_beta_neg_x_14 = r_ab_x_14 * scalar_mult_r_ab_14 + r_ab2_x_14 * scalar_mult_r_ab2_14; - float f_alpha_beta_neg_x_15 = r_ab_x_15 * scalar_mult_r_ab_15 + r_ab2_x_15 * scalar_mult_r_ab2_15; - - float f_alpha_beta_neg_y_0 = r_ab_y_0 * scalar_mult_r_ab_0 + r_ab2_y_0 * scalar_mult_r_ab2_0; - float f_alpha_beta_neg_y_1 = r_ab_y_1 * scalar_mult_r_ab_1 + r_ab2_y_1 * scalar_mult_r_ab2_1; - float f_alpha_beta_neg_y_2 = r_ab_y_2 * scalar_mult_r_ab_2 + r_ab2_y_2 * scalar_mult_r_ab2_2; - float f_alpha_beta_neg_y_3 = r_ab_y_3 * scalar_mult_r_ab_3 + r_ab2_y_3 * scalar_mult_r_ab2_3; - float f_alpha_beta_neg_y_4 = r_ab_y_4 * scalar_mult_r_ab_4 + r_ab2_y_4 * scalar_mult_r_ab2_4; - float f_alpha_beta_neg_y_5 = r_ab_y_5 * scalar_mult_r_ab_5 + r_ab2_y_5 * scalar_mult_r_ab2_5; - float f_alpha_beta_neg_y_6 = r_ab_y_6 * scalar_mult_r_ab_6 + r_ab2_y_6 * scalar_mult_r_ab2_6; - float f_alpha_beta_neg_y_7 = r_ab_y_7 * scalar_mult_r_ab_7 + r_ab2_y_7 * scalar_mult_r_ab2_7; - float f_alpha_beta_neg_y_8 = r_ab_y_8 * scalar_mult_r_ab_8 + r_ab2_y_8 * scalar_mult_r_ab2_8; - float f_alpha_beta_neg_y_9 = r_ab_y_9 * scalar_mult_r_ab_9 + r_ab2_y_9 * scalar_mult_r_ab2_9; - float f_alpha_beta_neg_y_10 = r_ab_y_10 * scalar_mult_r_ab_10 + r_ab2_y_10 * scalar_mult_r_ab2_10; - float f_alpha_beta_neg_y_11 = r_ab_y_11 * scalar_mult_r_ab_11 + r_ab2_y_11 * scalar_mult_r_ab2_11; - float f_alpha_beta_neg_y_12 = r_ab_y_12 * scalar_mult_r_ab_12 + r_ab2_y_12 * scalar_mult_r_ab2_12; - float f_alpha_beta_neg_y_13 = r_ab_y_13 * scalar_mult_r_ab_13 + r_ab2_y_13 * scalar_mult_r_ab2_13; - float f_alpha_beta_neg_y_14 = r_ab_y_14 * scalar_mult_r_ab_14 + r_ab2_y_14 * scalar_mult_r_ab2_14; - float f_alpha_beta_neg_y_15 = r_ab_y_15 * scalar_mult_r_ab_15 + r_ab2_y_15 * scalar_mult_r_ab2_15; - - float w_val_0, w_val_1, w_val_2, w_val_3, w_val_4, w_val_5, w_val_6, w_val_7; - float w_val_8, w_val_9, w_val_10, w_val_11, w_val_12, w_val_13, w_val_14, w_val_15; - - float f_norm_sq_0 = f_alpha_beta_neg_x_0 * f_alpha_beta_neg_x_0 + f_alpha_beta_neg_y_0 * f_alpha_beta_neg_y_0; - float f_norm_sq_1 = f_alpha_beta_neg_x_1 * f_alpha_beta_neg_x_1 + f_alpha_beta_neg_y_1 * f_alpha_beta_neg_y_1; - float f_norm_sq_2 = f_alpha_beta_neg_x_2 * f_alpha_beta_neg_x_2 + f_alpha_beta_neg_y_2 * f_alpha_beta_neg_y_2; - float f_norm_sq_3 = f_alpha_beta_neg_x_3 * f_alpha_beta_neg_x_3 + f_alpha_beta_neg_y_3 * f_alpha_beta_neg_y_3; - float f_norm_sq_4 = f_alpha_beta_neg_x_4 * f_alpha_beta_neg_x_4 + f_alpha_beta_neg_y_4 * f_alpha_beta_neg_y_4; - float f_norm_sq_5 = f_alpha_beta_neg_x_5 * f_alpha_beta_neg_x_5 + f_alpha_beta_neg_y_5 * f_alpha_beta_neg_y_5; - float f_norm_sq_6 = f_alpha_beta_neg_x_6 * f_alpha_beta_neg_x_6 + f_alpha_beta_neg_y_6 * f_alpha_beta_neg_y_6; - float f_norm_sq_7 = f_alpha_beta_neg_x_7 * f_alpha_beta_neg_x_7 + f_alpha_beta_neg_y_7 * f_alpha_beta_neg_y_7; - float f_norm_sq_8 = f_alpha_beta_neg_x_8 * f_alpha_beta_neg_x_8 + f_alpha_beta_neg_y_8 * f_alpha_beta_neg_y_8; - float f_norm_sq_9 = f_alpha_beta_neg_x_9 * f_alpha_beta_neg_x_9 + f_alpha_beta_neg_y_9 * f_alpha_beta_neg_y_9; - float f_norm_sq_10 = f_alpha_beta_neg_x_10 * f_alpha_beta_neg_x_10 + f_alpha_beta_neg_y_10 * f_alpha_beta_neg_y_10; - float f_norm_sq_11 = f_alpha_beta_neg_x_11 * f_alpha_beta_neg_x_11 + f_alpha_beta_neg_y_11 * f_alpha_beta_neg_y_11; - float f_norm_sq_12 = f_alpha_beta_neg_x_12 * f_alpha_beta_neg_x_12 + f_alpha_beta_neg_y_12 * f_alpha_beta_neg_y_12; - float f_norm_sq_13 = f_alpha_beta_neg_x_13 * f_alpha_beta_neg_x_13 + f_alpha_beta_neg_y_13 * f_alpha_beta_neg_y_13; - float f_norm_sq_14 = f_alpha_beta_neg_x_14 * f_alpha_beta_neg_x_14 + f_alpha_beta_neg_y_14 * f_alpha_beta_neg_y_14; - float f_norm_sq_15 = f_alpha_beta_neg_x_15 * f_alpha_beta_neg_x_15 + f_alpha_beta_neg_y_15 * f_alpha_beta_neg_y_15; - - float rhs_0 = f_norm_sq_0 * cos_phi_sq; - float rhs_1 = f_norm_sq_1 * cos_phi_sq; - float rhs_2 = f_norm_sq_2 * cos_phi_sq; - float rhs_3 = f_norm_sq_3 * cos_phi_sq; - float rhs_4 = f_norm_sq_4 * cos_phi_sq; - float rhs_5 = f_norm_sq_5 * cos_phi_sq; - float rhs_6 = f_norm_sq_6 * cos_phi_sq; - float rhs_7 = f_norm_sq_7 * cos_phi_sq; - float rhs_8 = f_norm_sq_8 * cos_phi_sq; - float rhs_9 = f_norm_sq_9 * cos_phi_sq; - float rhs_10 = f_norm_sq_10 * cos_phi_sq; - float rhs_11 = f_norm_sq_11 * cos_phi_sq; - float rhs_12 = f_norm_sq_12 * cos_phi_sq; - float rhs_13 = f_norm_sq_13 * cos_phi_sq; - float rhs_14 = f_norm_sq_14 * cos_phi_sq; - float rhs_15 = f_norm_sq_15 * cos_phi_sq; - - float e_dot_f_0 = e_x_i * f_alpha_beta_neg_x_0 + e_y_i * f_alpha_beta_neg_y_0; - float e_dot_f_1 = e_x_i * f_alpha_beta_neg_x_1 + e_y_i * f_alpha_beta_neg_y_1; - float e_dot_f_2 = e_x_i * f_alpha_beta_neg_x_2 + e_y_i * f_alpha_beta_neg_y_2; - float e_dot_f_3 = e_x_i * f_alpha_beta_neg_x_3 + e_y_i * f_alpha_beta_neg_y_3; - float e_dot_f_4 = e_x_i * f_alpha_beta_neg_x_4 + e_y_i * f_alpha_beta_neg_y_4; - float e_dot_f_5 = e_x_i * f_alpha_beta_neg_x_5 + e_y_i * f_alpha_beta_neg_y_5; - float e_dot_f_6 = e_x_i * f_alpha_beta_neg_x_6 + e_y_i * f_alpha_beta_neg_y_6; - float e_dot_f_7 = e_x_i * f_alpha_beta_neg_x_7 + e_y_i * f_alpha_beta_neg_y_7; - float e_dot_f_8 = e_x_i * f_alpha_beta_neg_x_8 + e_y_i * f_alpha_beta_neg_y_8; - float e_dot_f_9 = e_x_i * f_alpha_beta_neg_x_9 + e_y_i * f_alpha_beta_neg_y_9; - float e_dot_f_10 = e_x_i * f_alpha_beta_neg_x_10 + e_y_i * f_alpha_beta_neg_y_10; - float e_dot_f_11 = e_x_i * f_alpha_beta_neg_x_11 + e_y_i * f_alpha_beta_neg_y_11; - float e_dot_f_12 = e_x_i * f_alpha_beta_neg_x_12 + e_y_i * f_alpha_beta_neg_y_12; - float e_dot_f_13 = e_x_i * f_alpha_beta_neg_x_13 + e_y_i * f_alpha_beta_neg_y_13; - float e_dot_f_14 = e_x_i * f_alpha_beta_neg_x_14 + e_y_i * f_alpha_beta_neg_y_14; - float e_dot_f_15 = e_x_i * f_alpha_beta_neg_x_15 + e_y_i * f_alpha_beta_neg_y_15; - - float e_dot_f_sq_0 = e_dot_f_0 * e_dot_f_0; - float e_dot_f_sq_1 = e_dot_f_1 * e_dot_f_1; - float e_dot_f_sq_2 = e_dot_f_2 * e_dot_f_2; - float e_dot_f_sq_3 = e_dot_f_3 * e_dot_f_3; - float e_dot_f_sq_4 = e_dot_f_4 * e_dot_f_4; - float e_dot_f_sq_5 = e_dot_f_5 * e_dot_f_5; - float e_dot_f_sq_6 = e_dot_f_6 * e_dot_f_6; - float e_dot_f_sq_7 = e_dot_f_7 * e_dot_f_7; - float e_dot_f_sq_8 = e_dot_f_8 * e_dot_f_8; - float e_dot_f_sq_9 = e_dot_f_9 * e_dot_f_9; - float e_dot_f_sq_10 = e_dot_f_10 * e_dot_f_10; - float e_dot_f_sq_11 = e_dot_f_11 * e_dot_f_11; - float e_dot_f_sq_12 = e_dot_f_12 * e_dot_f_12; - float e_dot_f_sq_13 = e_dot_f_13 * e_dot_f_13; - float e_dot_f_sq_14 = e_dot_f_14 * e_dot_f_14; - float e_dot_f_sq_15 = e_dot_f_15 * e_dot_f_15; - - if (e_dot_f_0 >= 0.0 || e_dot_f_sq_0 <= rhs_0) - w_val_0 = dt_neg; - else - w_val_0 = c_neg_times_dt; - if (e_dot_f_1 >= 0.0 || e_dot_f_sq_1 <= rhs_1) - w_val_1 = dt_neg; - else - w_val_1 = c_neg_times_dt; - if (e_dot_f_2 >= 0.0 || e_dot_f_sq_2 <= rhs_2) - w_val_2 = dt_neg; - else - w_val_2 = c_neg_times_dt; - if (e_dot_f_3 >= 0.0 || e_dot_f_sq_3 <= rhs_3) - w_val_3 = dt_neg; - else - w_val_3 = c_neg_times_dt; - if (e_dot_f_4 >= 0.0 || e_dot_f_sq_4 <= rhs_4) - w_val_4 = dt_neg; - else - w_val_4 = c_neg_times_dt; - if (e_dot_f_5 >= 0.0 || e_dot_f_sq_5 <= rhs_5) - w_val_5 = dt_neg; - else - w_val_5 = c_neg_times_dt; - if (e_dot_f_6 >= 0.0 || e_dot_f_sq_6 <= rhs_6) - w_val_6 = dt_neg; - else - w_val_6 = c_neg_times_dt; - if (e_dot_f_7 >= 0.0 || e_dot_f_sq_7 <= rhs_7) - w_val_7 = dt_neg; - else - w_val_7 = c_neg_times_dt; - if (e_dot_f_8 >= 0.0 || e_dot_f_sq_8 <= rhs_8) - w_val_8 = dt_neg; - else - w_val_8 = c_neg_times_dt; - if (e_dot_f_9 >= 0.0 || e_dot_f_sq_9 <= rhs_9) - w_val_9 = dt_neg; - else - w_val_9 = c_neg_times_dt; - if (e_dot_f_10 >= 0.0 || e_dot_f_sq_10 <= rhs_10) - w_val_10 = dt_neg; - else - w_val_10 = c_neg_times_dt; - if (e_dot_f_11 >= 0.0 || e_dot_f_sq_11 <= rhs_11) - w_val_11 = dt_neg; - else - w_val_11 = c_neg_times_dt; - if (e_dot_f_12 >= 0.0 || e_dot_f_sq_12 <= rhs_12) - w_val_12 = dt_neg; - else - w_val_12 = c_neg_times_dt; - if (e_dot_f_13 >= 0.0 || e_dot_f_sq_13 <= rhs_13) - w_val_13 = dt_neg; - else - w_val_13 = c_neg_times_dt; - if (e_dot_f_14 >= 0.0 || e_dot_f_sq_14 <= rhs_14) - w_val_14 = dt_neg; - else - w_val_14 = c_neg_times_dt; - if (e_dot_f_15 >= 0.0 || e_dot_f_sq_15 <= rhs_15) - w_val_15 = dt_neg; - else - w_val_15 = c_neg_times_dt; - - acc_x_0 += f_alpha_beta_neg_x_0 * w_val_0; - acc_x_1 += f_alpha_beta_neg_x_1 * w_val_1; - acc_x_2 += f_alpha_beta_neg_x_2 * w_val_2; - acc_x_3 += f_alpha_beta_neg_x_3 * w_val_3; - acc_x_4 += f_alpha_beta_neg_x_4 * w_val_4; - acc_x_5 += f_alpha_beta_neg_x_5 * w_val_5; - acc_x_6 += f_alpha_beta_neg_x_6 * w_val_6; - acc_x_7 += f_alpha_beta_neg_x_7 * w_val_7; - acc_x_8 += f_alpha_beta_neg_x_8 * w_val_8; - acc_x_9 += f_alpha_beta_neg_x_9 * w_val_9; - acc_x_10 += f_alpha_beta_neg_x_10 * w_val_10; - acc_x_11 += f_alpha_beta_neg_x_11 * w_val_11; - acc_x_12 += f_alpha_beta_neg_x_12 * w_val_12; - acc_x_13 += f_alpha_beta_neg_x_13 * w_val_13; - acc_x_14 += f_alpha_beta_neg_x_14 * w_val_14; - acc_x_15 += f_alpha_beta_neg_x_15 * w_val_15; - acc_y_0 += f_alpha_beta_neg_y_0 * w_val_0; - acc_y_1 += f_alpha_beta_neg_y_1 * w_val_1; - acc_y_2 += f_alpha_beta_neg_y_2 * w_val_2; - acc_y_3 += f_alpha_beta_neg_y_3 * w_val_3; - acc_y_4 += f_alpha_beta_neg_y_4 * w_val_4; - acc_y_5 += f_alpha_beta_neg_y_5 * w_val_5; - acc_y_6 += f_alpha_beta_neg_y_6 * w_val_6; - acc_y_7 += f_alpha_beta_neg_y_7 * w_val_7; - acc_y_8 += f_alpha_beta_neg_y_8 * w_val_8; - acc_y_9 += f_alpha_beta_neg_y_9 * w_val_9; - acc_y_10 += f_alpha_beta_neg_y_10 * w_val_10; - acc_y_11 += f_alpha_beta_neg_y_11 * w_val_11; - acc_y_12 += f_alpha_beta_neg_y_12 * w_val_12; - acc_y_13 += f_alpha_beta_neg_y_13 * w_val_13; - acc_y_14 += f_alpha_beta_neg_y_14 * w_val_14; - acc_y_15 += f_alpha_beta_neg_y_15 * w_val_15; - } - - // remainder of the j > i half, single lane. # one j = 66 FLOPS - for (; j < n_p; j++) { - float r_ab_x = r_ab_x_lut[i * n_p + j]; - float r_ab_y = r_ab_y_lut[i * n_p + j]; - float r_ab_norm = r_ab_norm_lut[i * n_p + j]; - - r_ab_norm = r_ab_norm > EPS ? r_ab_norm : EPS; - - // # 1 ADD - float r_ab2_x = r_ab_x - sb_e_x[j]; - // # 1 ADD - float r_ab2_y = r_ab_y - sb_e_y[j]; - - // # 1 ADD, 2 MULTs, 1 SQRT - float r_ab2_norm = sqrt(r_ab2_x * r_ab2_x + r_ab2_y * r_ab2_y); - r_ab2_norm = r_ab2_norm > EPS ? r_ab2_norm : EPS; - - // # 1 ADD - float r_ab_norm_sum = r_ab_norm + r_ab2_norm; - - // # 1 ADD, 1 MULT - float two_b_sq = r_ab_norm_sum * r_ab_norm_sum - sb_sq[j]; - two_b_sq = two_b_sq > EPS_SQ ? two_b_sq : EPS_SQ; - // # 1 SQRT - float two_b = sqrt(two_b_sq); - // # 5 MULTs, 1 DIV, 1 EXP - float scalar_mult_common = (r_ab_norm_sum / (two_b * r_ab_norm * r_ab2_norm)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b * NEG_TWO_SIGMA_INV)); - // # 1 MULT - float scalar_mult_r_ab = scalar_mult_common * r_ab2_norm; - // # 1 MULT - float scalar_mult_r_ab2 = scalar_mult_common * r_ab_norm; - - // # 1 ADD, 2 MULTs - float f_alpha_beta_neg_x = r_ab_x * scalar_mult_r_ab + r_ab2_x * scalar_mult_r_ab2; - // # 1 ADD, 2 MULTs - float f_alpha_beta_neg_y = r_ab_y * scalar_mult_r_ab + r_ab2_y * scalar_mult_r_ab2; - - float w_val; - - // # 1 ADD, 2 MULTs - float f_norm_sq = f_alpha_beta_neg_x * f_alpha_beta_neg_x + f_alpha_beta_neg_y * f_alpha_beta_neg_y; - // # 1 MULT - float rhs = f_norm_sq * cos_phi_sq; - // # 1 ADD, 2 MULTs - float e_dot_f = e_x[i] * f_alpha_beta_neg_x + e_y[i] * f_alpha_beta_neg_y; - // # 1 MULT - float e_dot_f_sq = e_dot_f * e_dot_f; - if (e_dot_f >= 0.0 || e_dot_f_sq <= rhs) - w_val = dt_neg; - else - w_val = c_neg_times_dt; - - // # 1 ADD, 1 MULT - f_alpha_dt_x += f_alpha_beta_neg_x * w_val; - // # 1 ADD, 1 MULT - f_alpha_dt_y += f_alpha_beta_neg_y * w_val; - } - - // reduction of the j > i accumulators. # K adds per line (K=16) => 32 ADDs - f_alpha_dt_x += acc_x_0 + acc_x_1 + acc_x_2 + acc_x_3 + acc_x_4 + acc_x_5 + acc_x_6 + acc_x_7 + acc_x_8 + acc_x_9 + acc_x_10 + acc_x_11 + acc_x_12 + acc_x_13 + acc_x_14 + acc_x_15; - f_alpha_dt_y += acc_y_0 + acc_y_1 + acc_y_2 + acc_y_3 + acc_y_4 + acc_y_5 + acc_y_6 + acc_y_7 + acc_y_8 + acc_y_9 + acc_y_10 + acc_y_11 + acc_y_12 + acc_y_13 + acc_y_14 + acc_y_15; - - // force between pedestrian and obstacles - // # one obstacle = 55 FLOPS (w_val sign-based, no a*a / b_sq) - for (int k = 0; k < board.n_obstacles; k++) { - // # 1 ADD - float v1_x = pos_x[i] - board.obstacles[k].start_x; - // # 1 ADD - float v1_y = pos_y[i] - board.obstacles[k].start_y; - float v2_x = board.obstacles[k].obstacle_v_x; - float v2_y = board.obstacles[k].obstacle_v_y; - - // # 1 ADD, 3 MULTs - float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; - - if (projection < 0.0) - projection = 0.0; - else if (projection > 1.0) - projection = 1.0; - - // # 2 ADDs, 1 MULT - float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); - // # 2 ADDs, 1 MULT - float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); - - // # 1 ADD, 2 MULTs, 1 SQRT - float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); - r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; - - // # 2 MULTs, 1 DIV, 1 EXP - float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; - // # 1 MULT - float f_alpha_B_neg_x = r_aB_x * scalar_mult; - // # 1 MULT - float f_alpha_B_neg_y = r_aB_y * scalar_mult; - - float w_val; - - // sign select only, no flops - float e_dot_f = (f_alpha_B_neg_y == 0) ? 0 : (f_alpha_B_neg_y < 0 ? -e_y[i] : e_y[i]); - - if (e_dot_f >= cos_phi) - w_val = dt_neg; - else - w_val = c_neg_times_dt; - - // # 1 MULT - float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; - // # 1 MULT - float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; - - // # 1 ADD - f_alpha_dt_x += f_alpha_B_dt_x; - // # 1 ADD - f_alpha_dt_y += f_alpha_B_dt_y; - } - - // # 1 ADD - w_x[i] += f_alpha_dt_x; - // # 1 ADD - w_y[i] += f_alpha_dt_y; - } - - // update each pedestrian - // # 29 FLOPS per pedestrian - for (int i = 0; i < n_p; i++) { - - // # 1 ADD, 2 MULTs, 1 SQRT - float w_norm = sqrt(w_x[i] * w_x[i] + w_y[i] * w_y[i]); - - float w_norm2 = w_norm > EPS ? w_norm : EPS; - - // # 1 DIV - float correction_factor = min(1.0f, v_max[i] / w_norm2); - - // # 1 MULT - curr_vel_x[i] = w_x[i] * correction_factor; - // # 1 MULT - curr_vel_y[i] = w_y[i] * correction_factor; - - // # 1 ADD, 1 MULT - pos_x[i] = pos_x[i] + curr_vel_x[i] * dt; - // # 1 ADD, 1 MULT - pos_y[i] = pos_y[i] + curr_vel_y[i] * dt; - - if (color[i] == 0 && pos_x[i] > (BOARD_LENGTH - 1.5)) { - pos_x[i] = 1.0; - destination_y[i] = pos_y[i]; - w_x[i] = desired_v0[i]; - w_y[i] = 0.0; - curr_vel_x[i] = w_x[i]; - curr_vel_y[i] = w_y[i]; - } - if (color[i] == 1 && pos_x[i] < 1.5) { - pos_x[i] = BOARD_LENGTH - 1.0; - destination_y[i] = pos_y[i]; - w_x[i] = -desired_v0[i]; - w_y[i] = 0.0; - curr_vel_x[i] = w_x[i]; - curr_vel_y[i] = w_y[i]; - } - - pos_y[i] = clamp(pos_y[i], WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - - // # 1 ADD - float ex = destination_x[i] - pos_x[i]; - // # 1 ADD - float ey = destination_y[i] - pos_y[i]; - - // # 1 ADD, 2 MULTs, 1 SQRT - float e_norm = sqrt(ex * ex + ey * ey); - float e_norm2 = e_norm > EPS ? e_norm : EPS; - // # 1 DIV - float e_norm_inv = 1.0 / e_norm2; - - // # 1 MULT - e_x[i] = ex * e_norm_inv; - // # 1 MULT - e_y[i] = ey * e_norm_inv; - - // # 1 ADD, 2 MULTs - float velocity_norm_sq = curr_vel_x[i] * curr_vel_x[i] + curr_vel_y[i] * curr_vel_y[i]; - - // # 1 SQRT - float velocity_norm = sqrt(velocity_norm_sq); - - // # 1 MULT - sb_sq[i] = velocity_norm_sq * delta_t_sq; - - // # 2 MULTs (velocity_norm*delta_t written on both lines, counted as is) - sb_e_x[i] = e_x[i] * (velocity_norm * delta_t); - // # 2 MULTs - sb_e_y[i] = e_y[i] * (velocity_norm * delta_t); - -#if !BENCHMARK - if (dump_path && (t % dump_interval == 0)) { - samples.emplace_back(t + 1, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } -#endif - } - } - -#if !BENCHMARK - if (dump_path) { - ofstream out(dump_path); - out << "time,id,x,y,p.e.x,p.e.y,color\n"; - - for (auto &[t, id, x, y, e_x, e_y, c] : samples) { - out << t << ',' << id << ',' << x << ',' << y << ',' << e_x << ',' << e_y << ',' << c << '\n'; - } - } -#endif - - return 0; -} diff --git a/variants/variant_float_inlining_SoA_symmetry_ILP_2_flopcount.cpp b/variants/variant_float_inlining_SoA_symmetry_ILP_2_flopcount.cpp deleted file mode 100644 index 8a845af..0000000 --- a/variants/variant_float_inlining_SoA_symmetry_ILP_2_flopcount.cpp +++ /dev/null @@ -1,703 +0,0 @@ -// # Changes: Added ILP for j-loop with K = 2 -// # added flopcount -// FLOPCOUNT = n_iter * ( 69 * n_p ** 2 - 24 * n_p + 55 * n_obstacles * n_p ) -// # Predecessor: variant_float_inlining_SoA_symmetry.cpp - -#include "../headers/board_reduced_float.hpp" -#include "../headers/constants_float.hpp" -#include "../headers/pedestrian_reduced_float.hpp" - -#include -#include -#include - -#define SEED 42 -#define BOARD_WIDTH 10.0f -#define BOARD_LENGTH 50.0f -#define WALL_EPS 1e-3f -#define BOARD_WIDTH_MINUS_WALL_EPS 9.999f - -#ifndef RANDOM_SEED -#define RANDOM_SEED 0 -#endif - -#ifndef BENCHMARK -#define BENCHMARK 0 -#endif - -using namespace std; - -vector pos_x, pos_y; -vector sb_sq; -vector sb_e_x, sb_e_y; -vector e_x, e_y; -vector curr_vel_x, curr_vel_y; -vector w_x, w_y; -vector desired_v0; -vector v_max; -vector destination_x, destination_y; -vector color; - -Pedestrian *init_pedestrians(int n_p) { -#if RANDOM_SEED - random_device rd; - mt19937 gen(rd()); -#else - mt19937 gen(SEED); -#endif - - normal_distribution velocity_gen(v0_mean, v0_std_dev); - uniform_real_distribution y_gen(0.3, BOARD_WIDTH - 0.3); - uniform_real_distribution x_gen_left(2.0, BOARD_LENGTH / 2.0); - uniform_real_distribution x_gen_right(BOARD_LENGTH / 2.0, BOARD_LENGTH - 2.0); - - pos_x.resize(n_p); - pos_y.resize(n_p); - sb_sq.resize(n_p); - sb_e_x.resize(n_p); - sb_e_y.resize(n_p); - e_x.resize(n_p); - e_y.resize(n_p); - curr_vel_x.resize(n_p); - curr_vel_y.resize(n_p); - w_x.resize(n_p); - w_y.resize(n_p); - desired_v0.resize(n_p); - v_max.resize(n_p); - destination_x.resize(n_p); - destination_y.resize(n_p); - color.resize(n_p); - - int n_p_half = n_p / 2; - - for (int i = 0; i < n_p_half; i++) { - float x = x_gen_left(gen); - float y = y_gen(gen); - - float dest_x = BOARD_LENGTH + 30.0; - float dest_y = y; - - float init_e_x = dest_x - x; - float init_e_y = dest_y - y; - float init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - float init_e_unit_x = init_e_x / init_e_norm; - float init_e_unit_y = init_e_y / init_e_norm; - - float d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1); - - float v_m = 1.3 * d_v0; - - color[i] = 0; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - w_x[i] = 0.0f; - w_y[i] = 0.0f; - curr_vel_x[i] = 0.0f; - curr_vel_y[i] = 0.0f; - sb_sq[i] = 0.0f; - sb_e_x[i] = 0.0f; - sb_e_y[i] = 0.0f; - } - - for (int i = n_p_half; i < n_p; i++) { - float x = x_gen_right(gen); - float y = y_gen(gen); - - float dest_x = -30; - float dest_y = y; - - float init_e_x = dest_x - x; - float init_e_y = dest_y - y; - float init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - float init_e_unit_x = init_e_x / init_e_norm; - float init_e_unit_y = init_e_y / init_e_norm; - - float d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1); - - float v_m = 1.3 * d_v0; - - color[i] = 1; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - w_x[i] = 0.0f; - w_y[i] = 0.0f; - curr_vel_x[i] = 0.0f; - curr_vel_y[i] = 0.0f; - sb_sq[i] = 0.0f; - sb_e_x[i] = 0.0f; - sb_e_y[i] = 0.0f; - } - - return nullptr; -} - -Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } - -int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { - (void)pedestrians; -#if BENCHMARK - (void)dump_path; -#endif - -#if !BENCHMARK - const int dump_interval = 1; - - vector> samples; - - if (dump_path) { - samples.reserve(static_cast(n_iter / dump_interval + 1) * n_p); - - for (int i = 0; i < n_p; i++) { - samples.emplace_back(0, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } - } -#endif - - vector r_ab_x_lut(n_p * n_p, 0.0); - vector r_ab_y_lut(n_p * n_p, 0.0); - vector r_ab_norm_lut(n_p * n_p, 0.0); - - // FLOPCOUNT (everything inside the t-loop). EXP kept as its own op (one real exp() per call). - // section costs: overhead 4 ADD 4 MULT (+ reductions 4*K = 8 ADD, K=2) | - // distance pair 3 ADD 2 MULT 1 SQRT | - // ped-ped j 11 ADD 22 MULT 2 SQRT 1 DIV 1 EXP | - // obstacle 10 ADD 13 MULT 1 SQRT 1 DIV 1 EXP | update 7 ADD 17 MULT 3 SQRT 2 DIV - - // # ADDs: n_iter * ( - // # n_p * 12 + - // # 0.5 * (n_p*n_p - n_p) * 3 + - // # n_p * (n_p - 1) * 11 + - // # n_p * board.n_obstacles * 10 + - // # n_p * 7 - // # ) - - // # MULTs: n_iter * ( - // # n_p * 4 + - // # 0.5 * (n_p*n_p - n_p) * 2 + - // # n_p * (n_p - 1) * 22 + - // # n_p * board.n_obstacles * 13 + - // # n_p * 17 - // # ) - - // # DIVs: n_iter * ( - // # n_p * (n_p - 1) + - // # n_p * board.n_obstacles + - // # n_p * 2 - // # ) - - // # SQRTs: n_iter * ( - // # 0.5 * (n_p*n_p - n_p) + - // # n_p * (n_p - 1) * 2 + - // # n_p * board.n_obstacles + - // # n_p * 3 - // # ) - - // # EXPs: n_iter * ( - // # n_p * (n_p - 1) + - // # n_p * board.n_obstacles - // # ) - - // total with EXP = 30: n_iter * ( 69 * n_p ** 2 - 24 * n_p + 55 * n_obstacles * n_p ) - for (int t = 0; t < n_iter; t++) { - for (int i = 0; i < n_p; i++) { - - // # 1 MULT - float desired_velocity_x = e_x[i] * desired_v0[i]; - // # 1 MULT - float desired_velocity_y = e_y[i] * desired_v0[i]; - // # 1 ADD, 1 MULT - float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; - // # 1 ADD, 1 MULT - float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; - - float e_x_i = e_x[i]; - float e_y_i = e_y[i]; - float pos_x_i = pos_x[i]; - float pos_y_i = pos_y[i]; - - // distance precompute, # each pair: 6 FLOPS, total over all i = 0.5*(n_p*n_p - n_p)*6 - for (int j = i + 1; j < n_p; j++) { - // # 1 ADD - float dx = pos_x_i - pos_x[j]; - // # 1 ADD - float dy = pos_y_i - pos_y[j]; - // # 1 ADD, 2 MULTs, 1 SQRT - float norm = sqrt(dx * dx + dy * dy); - int idx = i * n_p + j; - r_ab_x_lut[idx] = dx; - r_ab_y_lut[idx] = dy; - r_ab_norm_lut[idx] = norm; - } - - int j; - - float acc_x_0 = 0.0f, acc_x_1 = 0.0f; - float acc_y_0 = 0.0f, acc_y_1 = 0.0f; - - // ILP over the j < i half. # each lane = 66 FLOPS (same body as the remainder - // loop below where the per-line breakdown is given), K = 2 lanes per step - for (j = 0; j + 2 < i; j += 2) { - float r_ab_x_0 = -1 * r_ab_x_lut[j * n_p + i]; - float r_ab_x_1 = -1 * r_ab_x_lut[(j + 1) * n_p + i]; - - float r_ab_y_0 = -1 * r_ab_y_lut[j * n_p + i]; - float r_ab_y_1 = -1 * r_ab_y_lut[(j + 1) * n_p + i]; - - float r_ab_norm_0 = r_ab_norm_lut[j * n_p + i]; - float r_ab_norm_1 = r_ab_norm_lut[(j + 1) * n_p + i]; - - r_ab_norm_0 = r_ab_norm_0 > EPS ? r_ab_norm_0 : EPS; - r_ab_norm_1 = r_ab_norm_1 > EPS ? r_ab_norm_1 : EPS; - - float r_ab2_x_0 = r_ab_x_0 - sb_e_x[j]; - float r_ab2_x_1 = r_ab_x_1 - sb_e_x[j + 1]; - - float r_ab2_y_0 = r_ab_y_0 - sb_e_y[j]; - float r_ab2_y_1 = r_ab_y_1 - sb_e_y[j + 1]; - - float r_ab2_norm_0 = sqrt(r_ab2_x_0 * r_ab2_x_0 + r_ab2_y_0 * r_ab2_y_0); - float r_ab2_norm_1 = sqrt(r_ab2_x_1 * r_ab2_x_1 + r_ab2_y_1 * r_ab2_y_1); - - r_ab2_norm_0 = r_ab2_norm_0 > EPS ? r_ab2_norm_0 : EPS; - r_ab2_norm_1 = r_ab2_norm_1 > EPS ? r_ab2_norm_1 : EPS; - - float r_ab_norm_sum_0 = r_ab_norm_0 + r_ab2_norm_0; - float r_ab_norm_sum_1 = r_ab_norm_1 + r_ab2_norm_1; - - float two_b_sq_0 = r_ab_norm_sum_0 * r_ab_norm_sum_0 - sb_sq[j]; - float two_b_sq_1 = r_ab_norm_sum_1 * r_ab_norm_sum_1 - sb_sq[j + 1]; - - two_b_sq_0 = two_b_sq_0 > EPS_SQ ? two_b_sq_0 : EPS_SQ; - two_b_sq_1 = two_b_sq_1 > EPS_SQ ? two_b_sq_1 : EPS_SQ; - - float two_b_0 = sqrt(two_b_sq_0); - float two_b_1 = sqrt(two_b_sq_1); - - float scalar_mult_common_0 = (r_ab_norm_sum_0 / (two_b_0 * r_ab_norm_0 * r_ab2_norm_0)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_0 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_1 = (r_ab_norm_sum_1 / (two_b_1 * r_ab_norm_1 * r_ab2_norm_1)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_1 * NEG_TWO_SIGMA_INV)); - - float scalar_mult_r_ab_0 = scalar_mult_common_0 * r_ab2_norm_0; - float scalar_mult_r_ab_1 = scalar_mult_common_1 * r_ab2_norm_1; - - float scalar_mult_r_ab2_0 = scalar_mult_common_0 * r_ab_norm_0; - float scalar_mult_r_ab2_1 = scalar_mult_common_1 * r_ab_norm_1; - - float f_alpha_beta_neg_x_0 = r_ab_x_0 * scalar_mult_r_ab_0 + r_ab2_x_0 * scalar_mult_r_ab2_0; - float f_alpha_beta_neg_x_1 = r_ab_x_1 * scalar_mult_r_ab_1 + r_ab2_x_1 * scalar_mult_r_ab2_1; - - float f_alpha_beta_neg_y_0 = r_ab_y_0 * scalar_mult_r_ab_0 + r_ab2_y_0 * scalar_mult_r_ab2_0; - float f_alpha_beta_neg_y_1 = r_ab_y_1 * scalar_mult_r_ab_1 + r_ab2_y_1 * scalar_mult_r_ab2_1; - - float w_val_0, w_val_1; - - float f_norm_sq_0 = f_alpha_beta_neg_x_0 * f_alpha_beta_neg_x_0 + f_alpha_beta_neg_y_0 * f_alpha_beta_neg_y_0; - float f_norm_sq_1 = f_alpha_beta_neg_x_1 * f_alpha_beta_neg_x_1 + f_alpha_beta_neg_y_1 * f_alpha_beta_neg_y_1; - - float rhs_0 = f_norm_sq_0 * cos_phi_sq; - float rhs_1 = f_norm_sq_1 * cos_phi_sq; - - float e_dot_f_0 = e_x_i * f_alpha_beta_neg_x_0 + e_y_i * f_alpha_beta_neg_y_0; - float e_dot_f_1 = e_x_i * f_alpha_beta_neg_x_1 + e_y_i * f_alpha_beta_neg_y_1; - - float e_dot_f_sq_0 = e_dot_f_0 * e_dot_f_0; - float e_dot_f_sq_1 = e_dot_f_1 * e_dot_f_1; - - if (e_dot_f_0 >= 0.0 || e_dot_f_sq_0 <= rhs_0) - w_val_0 = dt_neg; - else - w_val_0 = c_neg_times_dt; - - if (e_dot_f_1 >= 0.0 || e_dot_f_sq_1 <= rhs_1) - w_val_1 = dt_neg; - else - w_val_1 = c_neg_times_dt; - - acc_x_0 += f_alpha_beta_neg_x_0 * w_val_0; - acc_x_1 += f_alpha_beta_neg_x_1 * w_val_1; - acc_y_0 += f_alpha_beta_neg_y_0 * w_val_0; - acc_y_1 += f_alpha_beta_neg_y_1 * w_val_1; - } - - // remainder of the j < i half, single lane. # one j = 66 FLOPS - for (; j < i; j++) { - // lut lookup + -1* sign flip: not counted - float r_ab_x = -1 * r_ab_x_lut[j * n_p + i]; - float r_ab_y = -1 * r_ab_y_lut[j * n_p + i]; - float r_ab_norm = r_ab_norm_lut[j * n_p + i]; - - r_ab_norm = r_ab_norm > EPS ? r_ab_norm : EPS; - - // # 1 ADD - float r_ab2_x = r_ab_x - sb_e_x[j]; - // # 1 ADD - float r_ab2_y = r_ab_y - sb_e_y[j]; - - // # 1 ADD, 2 MULTs, 1 SQRT - float r_ab2_norm = sqrt(r_ab2_x * r_ab2_x + r_ab2_y * r_ab2_y); - r_ab2_norm = r_ab2_norm > EPS ? r_ab2_norm : EPS; - - // # 1 ADD - float r_ab_norm_sum = r_ab_norm + r_ab2_norm; - - // # 1 ADD, 1 MULT - float two_b_sq = r_ab_norm_sum * r_ab_norm_sum - sb_sq[j]; - two_b_sq = two_b_sq > EPS_SQ ? two_b_sq : EPS_SQ; - // # 1 SQRT - float two_b = sqrt(two_b_sq); - // # 5 MULTs, 1 DIV, 1 EXP - float scalar_mult_common = (r_ab_norm_sum / (two_b * r_ab_norm * r_ab2_norm)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b * NEG_TWO_SIGMA_INV)); - // # 1 MULT - float scalar_mult_r_ab = scalar_mult_common * r_ab2_norm; - // # 1 MULT - float scalar_mult_r_ab2 = scalar_mult_common * r_ab_norm; - - // # 1 ADD, 2 MULTs - float f_alpha_beta_neg_x = r_ab_x * scalar_mult_r_ab + r_ab2_x * scalar_mult_r_ab2; - // # 1 ADD, 2 MULTs - float f_alpha_beta_neg_y = r_ab_y * scalar_mult_r_ab + r_ab2_y * scalar_mult_r_ab2; - - float w_val; - - // # 1 ADD, 2 MULTs - float f_norm_sq = f_alpha_beta_neg_x * f_alpha_beta_neg_x + f_alpha_beta_neg_y * f_alpha_beta_neg_y; - // # 1 MULT - float rhs = f_norm_sq * cos_phi_sq; - // # 1 ADD, 2 MULTs - float e_dot_f = e_x[i] * f_alpha_beta_neg_x + e_y[i] * f_alpha_beta_neg_y; - // # 1 MULT - float e_dot_f_sq = e_dot_f * e_dot_f; - if (e_dot_f >= 0.0 || e_dot_f_sq <= rhs) - w_val = dt_neg; - else - w_val = c_neg_times_dt; - - // # 1 ADD, 1 MULT - f_alpha_dt_x += f_alpha_beta_neg_x * w_val; - // # 1 ADD, 1 MULT - f_alpha_dt_y += f_alpha_beta_neg_y * w_val; - } - - // reduction of the j < i accumulators. # K adds per line (K=2) => 4 ADDs - f_alpha_dt_x += acc_x_0 + acc_x_1; - f_alpha_dt_y += acc_y_0 + acc_y_1; - - acc_x_0 = 0.0f; acc_x_1 = 0.0f; - acc_y_0 = 0.0f; acc_y_1 = 0.0f; - - // ILP over the j > i half. # each lane = 66 FLOPS, K = 2 lanes per step - for (j = i + 1; j + 2 < n_p; j += 2) { - float r_ab_x_0 = r_ab_x_lut[i * n_p + j]; - float r_ab_x_1 = r_ab_x_lut[i * n_p + j + 1]; - - float r_ab_y_0 = r_ab_y_lut[i * n_p + j]; - float r_ab_y_1 = r_ab_y_lut[i * n_p + j + 1]; - - float r_ab_norm_0 = r_ab_norm_lut[i * n_p + j]; - float r_ab_norm_1 = r_ab_norm_lut[i * n_p + j + 1]; - - r_ab_norm_0 = r_ab_norm_0 > EPS ? r_ab_norm_0 : EPS; - r_ab_norm_1 = r_ab_norm_1 > EPS ? r_ab_norm_1 : EPS; - - float r_ab2_x_0 = r_ab_x_0 - sb_e_x[j]; - float r_ab2_x_1 = r_ab_x_1 - sb_e_x[j + 1]; - - float r_ab2_y_0 = r_ab_y_0 - sb_e_y[j]; - float r_ab2_y_1 = r_ab_y_1 - sb_e_y[j + 1]; - - float r_ab2_norm_0 = sqrt(r_ab2_x_0 * r_ab2_x_0 + r_ab2_y_0 * r_ab2_y_0); - float r_ab2_norm_1 = sqrt(r_ab2_x_1 * r_ab2_x_1 + r_ab2_y_1 * r_ab2_y_1); - - r_ab2_norm_0 = r_ab2_norm_0 > EPS ? r_ab2_norm_0 : EPS; - r_ab2_norm_1 = r_ab2_norm_1 > EPS ? r_ab2_norm_1 : EPS; - - float r_ab_norm_sum_0 = r_ab_norm_0 + r_ab2_norm_0; - float r_ab_norm_sum_1 = r_ab_norm_1 + r_ab2_norm_1; - - float two_b_sq_0 = r_ab_norm_sum_0 * r_ab_norm_sum_0 - sb_sq[j]; - float two_b_sq_1 = r_ab_norm_sum_1 * r_ab_norm_sum_1 - sb_sq[j + 1]; - - two_b_sq_0 = two_b_sq_0 > EPS_SQ ? two_b_sq_0 : EPS_SQ; - two_b_sq_1 = two_b_sq_1 > EPS_SQ ? two_b_sq_1 : EPS_SQ; - - float two_b_0 = sqrt(two_b_sq_0); - float two_b_1 = sqrt(two_b_sq_1); - - float scalar_mult_common_0 = (r_ab_norm_sum_0 / (two_b_0 * r_ab_norm_0 * r_ab2_norm_0)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_0 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_1 = (r_ab_norm_sum_1 / (two_b_1 * r_ab_norm_1 * r_ab2_norm_1)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_1 * NEG_TWO_SIGMA_INV)); - - float scalar_mult_r_ab_0 = scalar_mult_common_0 * r_ab2_norm_0; - float scalar_mult_r_ab_1 = scalar_mult_common_1 * r_ab2_norm_1; - - float scalar_mult_r_ab2_0 = scalar_mult_common_0 * r_ab_norm_0; - float scalar_mult_r_ab2_1 = scalar_mult_common_1 * r_ab_norm_1; - - float f_alpha_beta_neg_x_0 = r_ab_x_0 * scalar_mult_r_ab_0 + r_ab2_x_0 * scalar_mult_r_ab2_0; - float f_alpha_beta_neg_x_1 = r_ab_x_1 * scalar_mult_r_ab_1 + r_ab2_x_1 * scalar_mult_r_ab2_1; - - float f_alpha_beta_neg_y_0 = r_ab_y_0 * scalar_mult_r_ab_0 + r_ab2_y_0 * scalar_mult_r_ab2_0; - float f_alpha_beta_neg_y_1 = r_ab_y_1 * scalar_mult_r_ab_1 + r_ab2_y_1 * scalar_mult_r_ab2_1; - - float w_val_0, w_val_1; - - float f_norm_sq_0 = f_alpha_beta_neg_x_0 * f_alpha_beta_neg_x_0 + f_alpha_beta_neg_y_0 * f_alpha_beta_neg_y_0; - float f_norm_sq_1 = f_alpha_beta_neg_x_1 * f_alpha_beta_neg_x_1 + f_alpha_beta_neg_y_1 * f_alpha_beta_neg_y_1; - - float rhs_0 = f_norm_sq_0 * cos_phi_sq; - float rhs_1 = f_norm_sq_1 * cos_phi_sq; - - float e_dot_f_0 = e_x_i * f_alpha_beta_neg_x_0 + e_y_i * f_alpha_beta_neg_y_0; - float e_dot_f_1 = e_x_i * f_alpha_beta_neg_x_1 + e_y_i * f_alpha_beta_neg_y_1; - - float e_dot_f_sq_0 = e_dot_f_0 * e_dot_f_0; - float e_dot_f_sq_1 = e_dot_f_1 * e_dot_f_1; - - if (e_dot_f_0 >= 0.0 || e_dot_f_sq_0 <= rhs_0) - w_val_0 = dt_neg; - else - w_val_0 = c_neg_times_dt; - - if (e_dot_f_1 >= 0.0 || e_dot_f_sq_1 <= rhs_1) - w_val_1 = dt_neg; - else - w_val_1 = c_neg_times_dt; - - acc_x_0 += f_alpha_beta_neg_x_0 * w_val_0; - acc_x_1 += f_alpha_beta_neg_x_1 * w_val_1; - acc_y_0 += f_alpha_beta_neg_y_0 * w_val_0; - acc_y_1 += f_alpha_beta_neg_y_1 * w_val_1; - } - - // remainder of the j > i half, single lane. # one j = 66 FLOPS - for (; j < n_p; j++) { - float r_ab_x = r_ab_x_lut[i * n_p + j]; - float r_ab_y = r_ab_y_lut[i * n_p + j]; - float r_ab_norm = r_ab_norm_lut[i * n_p + j]; - - r_ab_norm = r_ab_norm > EPS ? r_ab_norm : EPS; - - // # 1 ADD - float r_ab2_x = r_ab_x - sb_e_x[j]; - // # 1 ADD - float r_ab2_y = r_ab_y - sb_e_y[j]; - - // # 1 ADD, 2 MULTs, 1 SQRT - float r_ab2_norm = sqrt(r_ab2_x * r_ab2_x + r_ab2_y * r_ab2_y); - r_ab2_norm = r_ab2_norm > EPS ? r_ab2_norm : EPS; - - // # 1 ADD - float r_ab_norm_sum = r_ab_norm + r_ab2_norm; - - // # 1 ADD, 1 MULT - float two_b_sq = r_ab_norm_sum * r_ab_norm_sum - sb_sq[j]; - two_b_sq = two_b_sq > EPS_SQ ? two_b_sq : EPS_SQ; - // # 1 SQRT - float two_b = sqrt(two_b_sq); - // # 5 MULTs, 1 DIV, 1 EXP - float scalar_mult_common = (r_ab_norm_sum / (two_b * r_ab_norm * r_ab2_norm)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b * NEG_TWO_SIGMA_INV)); - // # 1 MULT - float scalar_mult_r_ab = scalar_mult_common * r_ab2_norm; - // # 1 MULT - float scalar_mult_r_ab2 = scalar_mult_common * r_ab_norm; - - // # 1 ADD, 2 MULTs - float f_alpha_beta_neg_x = r_ab_x * scalar_mult_r_ab + r_ab2_x * scalar_mult_r_ab2; - // # 1 ADD, 2 MULTs - float f_alpha_beta_neg_y = r_ab_y * scalar_mult_r_ab + r_ab2_y * scalar_mult_r_ab2; - - float w_val; - - // # 1 ADD, 2 MULTs - float f_norm_sq = f_alpha_beta_neg_x * f_alpha_beta_neg_x + f_alpha_beta_neg_y * f_alpha_beta_neg_y; - // # 1 MULT - float rhs = f_norm_sq * cos_phi_sq; - // # 1 ADD, 2 MULTs - float e_dot_f = e_x[i] * f_alpha_beta_neg_x + e_y[i] * f_alpha_beta_neg_y; - // # 1 MULT - float e_dot_f_sq = e_dot_f * e_dot_f; - if (e_dot_f >= 0.0 || e_dot_f_sq <= rhs) - w_val = dt_neg; - else - w_val = c_neg_times_dt; - - // # 1 ADD, 1 MULT - f_alpha_dt_x += f_alpha_beta_neg_x * w_val; - // # 1 ADD, 1 MULT - f_alpha_dt_y += f_alpha_beta_neg_y * w_val; - } - - // reduction of the j > i accumulators. # K adds per line (K=2) => 4 ADDs - f_alpha_dt_x += acc_x_0 + acc_x_1; - f_alpha_dt_y += acc_y_0 + acc_y_1; - - // force between pedestrian and obstacles - // # one obstacle = 55 FLOPS (w_val sign-based, no a*a / b_sq) - for (int k = 0; k < board.n_obstacles; k++) { - // # 1 ADD - float v1_x = pos_x[i] - board.obstacles[k].start_x; - // # 1 ADD - float v1_y = pos_y[i] - board.obstacles[k].start_y; - float v2_x = board.obstacles[k].obstacle_v_x; - float v2_y = board.obstacles[k].obstacle_v_y; - - // # 1 ADD, 3 MULTs - float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; - - if (projection < 0.0) - projection = 0.0; - else if (projection > 1.0) - projection = 1.0; - - // # 2 ADDs, 1 MULT - float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); - // # 2 ADDs, 1 MULT - float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); - - // # 1 ADD, 2 MULTs, 1 SQRT - float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); - r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; - - // # 2 MULTs, 1 DIV, 1 EXP - float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; - // # 1 MULT - float f_alpha_B_neg_x = r_aB_x * scalar_mult; - // # 1 MULT - float f_alpha_B_neg_y = r_aB_y * scalar_mult; - - float w_val; - - // sign select only, no flops - float e_dot_f = (f_alpha_B_neg_y == 0) ? 0 : (f_alpha_B_neg_y < 0 ? -e_y[i] : e_y[i]); - - if (e_dot_f >= cos_phi) - w_val = dt_neg; - else - w_val = c_neg_times_dt; - - // # 1 MULT - float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; - // # 1 MULT - float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; - - // # 1 ADD - f_alpha_dt_x += f_alpha_B_dt_x; - // # 1 ADD - f_alpha_dt_y += f_alpha_B_dt_y; - } - - // # 1 ADD - w_x[i] += f_alpha_dt_x; - // # 1 ADD - w_y[i] += f_alpha_dt_y; - } - - // update each pedestrian - // # 29 FLOPS per pedestrian - for (int i = 0; i < n_p; i++) { - // # 1 ADD, 2 MULTs, 1 SQRT - float w_norm = sqrt(w_x[i] * w_x[i] + w_y[i] * w_y[i]); - - float w_norm2 = w_norm > EPS ? w_norm : EPS; - - // # 1 DIV - float correction_factor = min(1.0f, v_max[i] / w_norm2); - - // # 1 MULT - curr_vel_x[i] = w_x[i] * correction_factor; - // # 1 MULT - curr_vel_y[i] = w_y[i] * correction_factor; - - // # 1 ADD, 1 MULT - pos_x[i] = pos_x[i] + curr_vel_x[i] * dt; - // # 1 ADD, 1 MULT - pos_y[i] = pos_y[i] + curr_vel_y[i] * dt; - - if (color[i] == 0 && pos_x[i] > (BOARD_LENGTH - 1.5)) { - pos_x[i] = 1.0; - destination_y[i] = pos_y[i]; - w_x[i] = desired_v0[i]; - w_y[i] = 0.0; - curr_vel_x[i] = w_x[i]; - curr_vel_y[i] = w_y[i]; - } - if (color[i] == 1 && pos_x[i] < 1.5) { - pos_x[i] = BOARD_LENGTH - 1.0; - destination_y[i] = pos_y[i]; - w_x[i] = -desired_v0[i]; - w_y[i] = 0.0; - curr_vel_x[i] = w_x[i]; - curr_vel_y[i] = w_y[i]; - } - - pos_y[i] = clamp(pos_y[i], WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - - // # 1 ADD - float ex = destination_x[i] - pos_x[i]; - // # 1 ADD - float ey = destination_y[i] - pos_y[i]; - - // # 1 ADD, 2 MULTs, 1 SQRT - float e_norm = sqrt(ex * ex + ey * ey); - float e_norm2 = e_norm > EPS ? e_norm : EPS; - // # 1 DIV - float e_norm_inv = 1.0 / e_norm2; - - // # 1 MULT - e_x[i] = ex * e_norm_inv; - // # 1 MULT - e_y[i] = ey * e_norm_inv; - - // # 1 ADD, 2 MULTs - float velocity_norm_sq = curr_vel_x[i] * curr_vel_x[i] + curr_vel_y[i] * curr_vel_y[i]; - - // # 1 SQRT - float velocity_norm = sqrt(velocity_norm_sq); - - // # 1 MULT - sb_sq[i] = velocity_norm_sq * delta_t_sq; - - // # 2 MULTs (velocity_norm*delta_t written on both lines, counted as is) - sb_e_x[i] = e_x[i] * (velocity_norm * delta_t); - // # 2 MULTs - sb_e_y[i] = e_y[i] * (velocity_norm * delta_t); - -#if !BENCHMARK - if (dump_path && (t % dump_interval == 0)) { - samples.emplace_back(t + 1, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } -#endif - } - } - -#if !BENCHMARK - if (dump_path) { - ofstream out(dump_path); - out << "time,id,x,y,p.e.x,p.e.y,color\n"; - - for (auto &[t, id, x, y, e_x, e_y, c] : samples) { - out << t << ',' << id << ',' << x << ',' << y << ',' << e_x << ',' << e_y << ',' << c << '\n'; - } - } -#endif - - return 0; -} diff --git a/variants/variant_float_inlining_SoA_symmetry_ILP_4_flopcount.cpp b/variants/variant_float_inlining_SoA_symmetry_ILP_4_flopcount.cpp deleted file mode 100644 index e6d035c..0000000 --- a/variants/variant_float_inlining_SoA_symmetry_ILP_4_flopcount.cpp +++ /dev/null @@ -1,816 +0,0 @@ -// # Changes: Added ILP for j-loop with K = 4 -// # added flopcount -// FLOPCOUNT = n_iter * ( 69 * n_p ** 2 - 16 * n_p + 55 * n_obstacles * n_p ) -// # Predecessor: variant_float_inlining_SoA_symmetry_ILP_2.cpp - -#include "../headers/board_reduced_float.hpp" -#include "../headers/constants_float.hpp" -#include "../headers/pedestrian_reduced_float.hpp" - -#include -#include -#include - -#define SEED 42 -#define BOARD_WIDTH 10.0f -#define BOARD_LENGTH 50.0f -#define WALL_EPS 1e-3f -#define BOARD_WIDTH_MINUS_WALL_EPS 9.999f - -#ifndef RANDOM_SEED -#define RANDOM_SEED 0 -#endif - -#ifndef BENCHMARK -#define BENCHMARK 0 -#endif - -using namespace std; - -vector pos_x, pos_y; -vector sb_sq; -vector sb_e_x, sb_e_y; -vector e_x, e_y; -vector curr_vel_x, curr_vel_y; -vector w_x, w_y; -vector desired_v0; -vector v_max; -vector destination_x, destination_y; -vector color; - -Pedestrian *init_pedestrians(int n_p) { -#if RANDOM_SEED - random_device rd; - mt19937 gen(rd()); -#else - mt19937 gen(SEED); -#endif - - normal_distribution velocity_gen(v0_mean, v0_std_dev); - uniform_real_distribution y_gen(0.3, BOARD_WIDTH - 0.3); - uniform_real_distribution x_gen_left(2.0, BOARD_LENGTH / 2.0); - uniform_real_distribution x_gen_right(BOARD_LENGTH / 2.0, BOARD_LENGTH - 2.0); - - pos_x.resize(n_p); - pos_y.resize(n_p); - sb_sq.resize(n_p); - sb_e_x.resize(n_p); - sb_e_y.resize(n_p); - e_x.resize(n_p); - e_y.resize(n_p); - curr_vel_x.resize(n_p); - curr_vel_y.resize(n_p); - w_x.resize(n_p); - w_y.resize(n_p); - desired_v0.resize(n_p); - v_max.resize(n_p); - destination_x.resize(n_p); - destination_y.resize(n_p); - color.resize(n_p); - - int n_p_half = n_p / 2; - - for (int i = 0; i < n_p_half; i++) { - float x = x_gen_left(gen); - float y = y_gen(gen); - - float dest_x = BOARD_LENGTH + 30.0; - float dest_y = y; - - float init_e_x = dest_x - x; - float init_e_y = dest_y - y; - float init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - float init_e_unit_x = init_e_x / init_e_norm; - float init_e_unit_y = init_e_y / init_e_norm; - - float d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1); - - float v_m = 1.3 * d_v0; - - color[i] = 0; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - w_x[i] = 0.0f; - w_y[i] = 0.0f; - curr_vel_x[i] = 0.0f; - curr_vel_y[i] = 0.0f; - sb_sq[i] = 0.0f; - sb_e_x[i] = 0.0f; - sb_e_y[i] = 0.0f; - } - - for (int i = n_p_half; i < n_p; i++) { - float x = x_gen_right(gen); - float y = y_gen(gen); - - float dest_x = -30; - float dest_y = y; - - float init_e_x = dest_x - x; - float init_e_y = dest_y - y; - float init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - float init_e_unit_x = init_e_x / init_e_norm; - float init_e_unit_y = init_e_y / init_e_norm; - - float d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1); - - float v_m = 1.3 * d_v0; - - color[i] = 1; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - w_x[i] = 0.0f; - w_y[i] = 0.0f; - curr_vel_x[i] = 0.0f; - curr_vel_y[i] = 0.0f; - sb_sq[i] = 0.0f; - sb_e_x[i] = 0.0f; - sb_e_y[i] = 0.0f; - } - - return nullptr; -} - -Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } - -int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { - (void)pedestrians; -#if BENCHMARK - (void)dump_path; -#endif - -#if !BENCHMARK - const int dump_interval = 1; - - vector> samples; - - if (dump_path) { - samples.reserve(static_cast(n_iter / dump_interval + 1) * n_p); - - for (int i = 0; i < n_p; i++) { - samples.emplace_back(0, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } - } -#endif - - vector r_ab_x_lut(n_p * n_p, 0.0); - vector r_ab_y_lut(n_p * n_p, 0.0); - vector r_ab_norm_lut(n_p * n_p, 0.0); - - // FLOPCOUNT (everything inside the t-loop). EXP kept as its own op (one real exp() per call). - // section costs: overhead 4 ADD 4 MULT (+ reductions 4*K = 16 ADD, K=4) | - // distance pair 3 ADD 2 MULT 1 SQRT | - // ped-ped j 11 ADD 22 MULT 2 SQRT 1 DIV 1 EXP | - // obstacle 10 ADD 13 MULT 1 SQRT 1 DIV 1 EXP | update 7 ADD 17 MULT 3 SQRT 2 DIV - - // # ADDs: n_iter * ( - // # n_p * 20 + - // # 0.5 * (n_p*n_p - n_p) * 3 + - // # n_p * (n_p - 1) * 11 + - // # n_p * board.n_obstacles * 10 + - // # n_p * 7 - // # ) - - // # MULTs: n_iter * ( - // # n_p * 4 + - // # 0.5 * (n_p*n_p - n_p) * 2 + - // # n_p * (n_p - 1) * 22 + - // # n_p * board.n_obstacles * 13 + - // # n_p * 17 - // # ) - - // # DIVs: n_iter * ( - // # n_p * (n_p - 1) + - // # n_p * board.n_obstacles + - // # n_p * 2 - // # ) - - // # SQRTs: n_iter * ( - // # 0.5 * (n_p*n_p - n_p) + - // # n_p * (n_p - 1) * 2 + - // # n_p * board.n_obstacles + - // # n_p * 3 - // # ) - - // # EXPs: n_iter * ( - // # n_p * (n_p - 1) + - // # n_p * board.n_obstacles - // # ) - - // total with EXP = 30: n_iter * ( 69 * n_p ** 2 - 16 * n_p + 55 * n_obstacles * n_p ) - for (int t = 0; t < n_iter; t++) { - for (int i = 0; i < n_p; i++) { - - // # 1 MULT - float desired_velocity_x = e_x[i] * desired_v0[i]; - // # 1 MULT - float desired_velocity_y = e_y[i] * desired_v0[i]; - // # 1 ADD, 1 MULT - float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; - // # 1 ADD, 1 MULT - float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; - - float e_x_i = e_x[i]; - float e_y_i = e_y[i]; - float pos_x_i = pos_x[i]; - float pos_y_i = pos_y[i]; - - // distance precompute, # each pair: 6 FLOPS, total over all i = 0.5*(n_p*n_p - n_p)*6 - for (int j = i + 1; j < n_p; j++) { - // # 1 ADD - float dx = pos_x_i - pos_x[j]; - // # 1 ADD - float dy = pos_y_i - pos_y[j]; - // # 1 ADD, 2 MULTs, 1 SQRT - float norm = sqrt(dx * dx + dy * dy); - int idx = i * n_p + j; - r_ab_x_lut[idx] = dx; - r_ab_y_lut[idx] = dy; - r_ab_norm_lut[idx] = norm; - } - - int j; - - float acc_x_0 = 0.0f, acc_x_1 = 0.0f, acc_x_2 = 0.0f, acc_x_3 = 0.0f; - float acc_y_0 = 0.0f, acc_y_1 = 0.0f, acc_y_2 = 0.0f, acc_y_3 = 0.0f; - - // ILP over the j < i half. # each lane = 66 FLOPS (per-line breakdown is the - // same as the single-lane remainder loop below), K = 4 lanes per step - for (j = 0; j + 4 < i; j += 4) { - float r_ab_x_0 = -1 * r_ab_x_lut[j * n_p + i]; - float r_ab_x_1 = -1 * r_ab_x_lut[(j + 1) * n_p + i]; - float r_ab_x_2 = -1 * r_ab_x_lut[(j + 2) * n_p + i]; - float r_ab_x_3 = -1 * r_ab_x_lut[(j + 3) * n_p + i]; - - float r_ab_y_0 = -1 * r_ab_y_lut[j * n_p + i]; - float r_ab_y_1 = -1 * r_ab_y_lut[(j + 1) * n_p + i]; - float r_ab_y_2 = -1 * r_ab_y_lut[(j + 2) * n_p + i]; - float r_ab_y_3 = -1 * r_ab_y_lut[(j + 3) * n_p + i]; - - float r_ab_norm_0 = r_ab_norm_lut[j * n_p + i]; - float r_ab_norm_1 = r_ab_norm_lut[(j + 1) * n_p + i]; - float r_ab_norm_2 = r_ab_norm_lut[(j + 2) * n_p + i]; - float r_ab_norm_3 = r_ab_norm_lut[(j + 3) * n_p + i]; - - r_ab_norm_0 = r_ab_norm_0 > EPS ? r_ab_norm_0 : EPS; - r_ab_norm_1 = r_ab_norm_1 > EPS ? r_ab_norm_1 : EPS; - r_ab_norm_2 = r_ab_norm_2 > EPS ? r_ab_norm_2 : EPS; - r_ab_norm_3 = r_ab_norm_3 > EPS ? r_ab_norm_3 : EPS; - - float r_ab2_x_0 = r_ab_x_0 - sb_e_x[j]; - float r_ab2_x_1 = r_ab_x_1 - sb_e_x[j + 1]; - float r_ab2_x_2 = r_ab_x_2 - sb_e_x[j + 2]; - float r_ab2_x_3 = r_ab_x_3 - sb_e_x[j + 3]; - - float r_ab2_y_0 = r_ab_y_0 - sb_e_y[j]; - float r_ab2_y_1 = r_ab_y_1 - sb_e_y[j + 1]; - float r_ab2_y_2 = r_ab_y_2 - sb_e_y[j + 2]; - float r_ab2_y_3 = r_ab_y_3 - sb_e_y[j + 3]; - - float r_ab2_norm_0 = sqrt(r_ab2_x_0 * r_ab2_x_0 + r_ab2_y_0 * r_ab2_y_0); - float r_ab2_norm_1 = sqrt(r_ab2_x_1 * r_ab2_x_1 + r_ab2_y_1 * r_ab2_y_1); - float r_ab2_norm_2 = sqrt(r_ab2_x_2 * r_ab2_x_2 + r_ab2_y_2 * r_ab2_y_2); - float r_ab2_norm_3 = sqrt(r_ab2_x_3 * r_ab2_x_3 + r_ab2_y_3 * r_ab2_y_3); - - r_ab2_norm_0 = r_ab2_norm_0 > EPS ? r_ab2_norm_0 : EPS; - r_ab2_norm_1 = r_ab2_norm_1 > EPS ? r_ab2_norm_1 : EPS; - r_ab2_norm_2 = r_ab2_norm_2 > EPS ? r_ab2_norm_2 : EPS; - r_ab2_norm_3 = r_ab2_norm_3 > EPS ? r_ab2_norm_3 : EPS; - - float r_ab_norm_sum_0 = r_ab_norm_0 + r_ab2_norm_0; - float r_ab_norm_sum_1 = r_ab_norm_1 + r_ab2_norm_1; - float r_ab_norm_sum_2 = r_ab_norm_2 + r_ab2_norm_2; - float r_ab_norm_sum_3 = r_ab_norm_3 + r_ab2_norm_3; - - float two_b_sq_0 = r_ab_norm_sum_0 * r_ab_norm_sum_0 - sb_sq[j]; - float two_b_sq_1 = r_ab_norm_sum_1 * r_ab_norm_sum_1 - sb_sq[j + 1]; - float two_b_sq_2 = r_ab_norm_sum_2 * r_ab_norm_sum_2 - sb_sq[j + 2]; - float two_b_sq_3 = r_ab_norm_sum_3 * r_ab_norm_sum_3 - sb_sq[j + 3]; - - two_b_sq_0 = two_b_sq_0 > EPS_SQ ? two_b_sq_0 : EPS_SQ; - two_b_sq_1 = two_b_sq_1 > EPS_SQ ? two_b_sq_1 : EPS_SQ; - two_b_sq_2 = two_b_sq_2 > EPS_SQ ? two_b_sq_2 : EPS_SQ; - two_b_sq_3 = two_b_sq_3 > EPS_SQ ? two_b_sq_3 : EPS_SQ; - - float two_b_0 = sqrt(two_b_sq_0); - float two_b_1 = sqrt(two_b_sq_1); - float two_b_2 = sqrt(two_b_sq_2); - float two_b_3 = sqrt(two_b_sq_3); - - float scalar_mult_common_0 = (r_ab_norm_sum_0 / (two_b_0 * r_ab_norm_0 * r_ab2_norm_0)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_0 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_1 = (r_ab_norm_sum_1 / (two_b_1 * r_ab_norm_1 * r_ab2_norm_1)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_1 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_2 = (r_ab_norm_sum_2 / (two_b_2 * r_ab_norm_2 * r_ab2_norm_2)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_2 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_3 = (r_ab_norm_sum_3 / (two_b_3 * r_ab_norm_3 * r_ab2_norm_3)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_3 * NEG_TWO_SIGMA_INV)); - - float scalar_mult_r_ab_0 = scalar_mult_common_0 * r_ab2_norm_0; - float scalar_mult_r_ab_1 = scalar_mult_common_1 * r_ab2_norm_1; - float scalar_mult_r_ab_2 = scalar_mult_common_2 * r_ab2_norm_2; - float scalar_mult_r_ab_3 = scalar_mult_common_3 * r_ab2_norm_3; - - float scalar_mult_r_ab2_0 = scalar_mult_common_0 * r_ab_norm_0; - float scalar_mult_r_ab2_1 = scalar_mult_common_1 * r_ab_norm_1; - float scalar_mult_r_ab2_2 = scalar_mult_common_2 * r_ab_norm_2; - float scalar_mult_r_ab2_3 = scalar_mult_common_3 * r_ab_norm_3; - - float f_alpha_beta_neg_x_0 = r_ab_x_0 * scalar_mult_r_ab_0 + r_ab2_x_0 * scalar_mult_r_ab2_0; - float f_alpha_beta_neg_x_1 = r_ab_x_1 * scalar_mult_r_ab_1 + r_ab2_x_1 * scalar_mult_r_ab2_1; - float f_alpha_beta_neg_x_2 = r_ab_x_2 * scalar_mult_r_ab_2 + r_ab2_x_2 * scalar_mult_r_ab2_2; - float f_alpha_beta_neg_x_3 = r_ab_x_3 * scalar_mult_r_ab_3 + r_ab2_x_3 * scalar_mult_r_ab2_3; - - float f_alpha_beta_neg_y_0 = r_ab_y_0 * scalar_mult_r_ab_0 + r_ab2_y_0 * scalar_mult_r_ab2_0; - float f_alpha_beta_neg_y_1 = r_ab_y_1 * scalar_mult_r_ab_1 + r_ab2_y_1 * scalar_mult_r_ab2_1; - float f_alpha_beta_neg_y_2 = r_ab_y_2 * scalar_mult_r_ab_2 + r_ab2_y_2 * scalar_mult_r_ab2_2; - float f_alpha_beta_neg_y_3 = r_ab_y_3 * scalar_mult_r_ab_3 + r_ab2_y_3 * scalar_mult_r_ab2_3; - - float w_val_0, w_val_1, w_val_2, w_val_3; - - float f_norm_sq_0 = f_alpha_beta_neg_x_0 * f_alpha_beta_neg_x_0 + f_alpha_beta_neg_y_0 * f_alpha_beta_neg_y_0; - float f_norm_sq_1 = f_alpha_beta_neg_x_1 * f_alpha_beta_neg_x_1 + f_alpha_beta_neg_y_1 * f_alpha_beta_neg_y_1; - float f_norm_sq_2 = f_alpha_beta_neg_x_2 * f_alpha_beta_neg_x_2 + f_alpha_beta_neg_y_2 * f_alpha_beta_neg_y_2; - float f_norm_sq_3 = f_alpha_beta_neg_x_3 * f_alpha_beta_neg_x_3 + f_alpha_beta_neg_y_3 * f_alpha_beta_neg_y_3; - - float rhs_0 = f_norm_sq_0 * cos_phi_sq; - float rhs_1 = f_norm_sq_1 * cos_phi_sq; - float rhs_2 = f_norm_sq_2 * cos_phi_sq; - float rhs_3 = f_norm_sq_3 * cos_phi_sq; - - float e_dot_f_0 = e_x_i * f_alpha_beta_neg_x_0 + e_y_i * f_alpha_beta_neg_y_0; - float e_dot_f_1 = e_x_i * f_alpha_beta_neg_x_1 + e_y_i * f_alpha_beta_neg_y_1; - float e_dot_f_2 = e_x_i * f_alpha_beta_neg_x_2 + e_y_i * f_alpha_beta_neg_y_2; - float e_dot_f_3 = e_x_i * f_alpha_beta_neg_x_3 + e_y_i * f_alpha_beta_neg_y_3; - - float e_dot_f_sq_0 = e_dot_f_0 * e_dot_f_0; - float e_dot_f_sq_1 = e_dot_f_1 * e_dot_f_1; - float e_dot_f_sq_2 = e_dot_f_2 * e_dot_f_2; - float e_dot_f_sq_3 = e_dot_f_3 * e_dot_f_3; - - if (e_dot_f_0 >= 0.0 || e_dot_f_sq_0 <= rhs_0) - w_val_0 = dt_neg; - else - w_val_0 = c_neg_times_dt; - if (e_dot_f_1 >= 0.0 || e_dot_f_sq_1 <= rhs_1) - w_val_1 = dt_neg; - else - w_val_1 = c_neg_times_dt; - if (e_dot_f_2 >= 0.0 || e_dot_f_sq_2 <= rhs_2) - w_val_2 = dt_neg; - else - w_val_2 = c_neg_times_dt; - if (e_dot_f_3 >= 0.0 || e_dot_f_sq_3 <= rhs_3) - w_val_3 = dt_neg; - else - w_val_3 = c_neg_times_dt; - - acc_x_0 += f_alpha_beta_neg_x_0 * w_val_0; - acc_x_1 += f_alpha_beta_neg_x_1 * w_val_1; - acc_x_2 += f_alpha_beta_neg_x_2 * w_val_2; - acc_x_3 += f_alpha_beta_neg_x_3 * w_val_3; - acc_y_0 += f_alpha_beta_neg_y_0 * w_val_0; - acc_y_1 += f_alpha_beta_neg_y_1 * w_val_1; - acc_y_2 += f_alpha_beta_neg_y_2 * w_val_2; - acc_y_3 += f_alpha_beta_neg_y_3 * w_val_3; - } - - // remainder of the j < i half, single lane. # one j = 66 FLOPS - for (; j < i; j++) { - // lut lookup + -1* sign flip: not counted - float r_ab_x = -1 * r_ab_x_lut[j * n_p + i]; - float r_ab_y = -1 * r_ab_y_lut[j * n_p + i]; - float r_ab_norm = r_ab_norm_lut[j * n_p + i]; - - r_ab_norm = r_ab_norm > EPS ? r_ab_norm : EPS; - - // # 1 ADD - float r_ab2_x = r_ab_x - sb_e_x[j]; - // # 1 ADD - float r_ab2_y = r_ab_y - sb_e_y[j]; - - // # 1 ADD, 2 MULTs, 1 SQRT - float r_ab2_norm = sqrt(r_ab2_x * r_ab2_x + r_ab2_y * r_ab2_y); - r_ab2_norm = r_ab2_norm > EPS ? r_ab2_norm : EPS; - - // # 1 ADD - float r_ab_norm_sum = r_ab_norm + r_ab2_norm; - - // # 1 ADD, 1 MULT - float two_b_sq = r_ab_norm_sum * r_ab_norm_sum - sb_sq[j]; - two_b_sq = two_b_sq > EPS_SQ ? two_b_sq : EPS_SQ; - // # 1 SQRT - float two_b = sqrt(two_b_sq); - // # 5 MULTs, 1 DIV, 1 EXP - float scalar_mult_common = (r_ab_norm_sum / (two_b * r_ab_norm * r_ab2_norm)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b * NEG_TWO_SIGMA_INV)); - // # 1 MULT - float scalar_mult_r_ab = scalar_mult_common * r_ab2_norm; - // # 1 MULT - float scalar_mult_r_ab2 = scalar_mult_common * r_ab_norm; - - // # 1 ADD, 2 MULTs - float f_alpha_beta_neg_x = r_ab_x * scalar_mult_r_ab + r_ab2_x * scalar_mult_r_ab2; - // # 1 ADD, 2 MULTs - float f_alpha_beta_neg_y = r_ab_y * scalar_mult_r_ab + r_ab2_y * scalar_mult_r_ab2; - - float w_val; - - // # 1 ADD, 2 MULTs - float f_norm_sq = f_alpha_beta_neg_x * f_alpha_beta_neg_x + f_alpha_beta_neg_y * f_alpha_beta_neg_y; - // # 1 MULT - float rhs = f_norm_sq * cos_phi_sq; - // # 1 ADD, 2 MULTs - float e_dot_f = e_x[i] * f_alpha_beta_neg_x + e_y[i] * f_alpha_beta_neg_y; - // # 1 MULT - float e_dot_f_sq = e_dot_f * e_dot_f; - if (e_dot_f >= 0.0 || e_dot_f_sq <= rhs) - w_val = dt_neg; - else - w_val = c_neg_times_dt; - - // # 1 ADD, 1 MULT - f_alpha_dt_x += f_alpha_beta_neg_x * w_val; - // # 1 ADD, 1 MULT - f_alpha_dt_y += f_alpha_beta_neg_y * w_val; - } - - // reduction of the j < i accumulators. # K adds per line (K=4) => 8 ADDs - f_alpha_dt_x += acc_x_0 + acc_x_1 + acc_x_2 + acc_x_3; - f_alpha_dt_y += acc_y_0 + acc_y_1 + acc_y_2 + acc_y_3; - - acc_x_0 = 0.0f; - acc_x_1 = 0.0f; - acc_x_2 = 0.0f; - acc_x_3 = 0.0f; - acc_y_0 = 0.0f; - acc_y_1 = 0.0f; - acc_y_2 = 0.0f; - acc_y_3 = 0.0f; - - // ILP over the j > i half. # each lane = 66 FLOPS, K = 4 lanes per step - for (j = i + 1; j + 4 < n_p; j += 4) { - float r_ab_x_0 = r_ab_x_lut[i * n_p + j]; - float r_ab_x_1 = r_ab_x_lut[i * n_p + j + 1]; - float r_ab_x_2 = r_ab_x_lut[i * n_p + j + 2]; - float r_ab_x_3 = r_ab_x_lut[i * n_p + j + 3]; - - float r_ab_y_0 = r_ab_y_lut[i * n_p + j]; - float r_ab_y_1 = r_ab_y_lut[i * n_p + j + 1]; - float r_ab_y_2 = r_ab_y_lut[i * n_p + j + 2]; - float r_ab_y_3 = r_ab_y_lut[i * n_p + j + 3]; - - float r_ab_norm_0 = r_ab_norm_lut[i * n_p + j]; - float r_ab_norm_1 = r_ab_norm_lut[i * n_p + j + 1]; - float r_ab_norm_2 = r_ab_norm_lut[i * n_p + j + 2]; - float r_ab_norm_3 = r_ab_norm_lut[i * n_p + j + 3]; - - r_ab_norm_0 = r_ab_norm_0 > EPS ? r_ab_norm_0 : EPS; - r_ab_norm_1 = r_ab_norm_1 > EPS ? r_ab_norm_1 : EPS; - r_ab_norm_2 = r_ab_norm_2 > EPS ? r_ab_norm_2 : EPS; - r_ab_norm_3 = r_ab_norm_3 > EPS ? r_ab_norm_3 : EPS; - - float r_ab2_x_0 = r_ab_x_0 - sb_e_x[j]; - float r_ab2_x_1 = r_ab_x_1 - sb_e_x[j + 1]; - float r_ab2_x_2 = r_ab_x_2 - sb_e_x[j + 2]; - float r_ab2_x_3 = r_ab_x_3 - sb_e_x[j + 3]; - - float r_ab2_y_0 = r_ab_y_0 - sb_e_y[j]; - float r_ab2_y_1 = r_ab_y_1 - sb_e_y[j + 1]; - float r_ab2_y_2 = r_ab_y_2 - sb_e_y[j + 2]; - float r_ab2_y_3 = r_ab_y_3 - sb_e_y[j + 3]; - - float r_ab2_norm_0 = sqrt(r_ab2_x_0 * r_ab2_x_0 + r_ab2_y_0 * r_ab2_y_0); - float r_ab2_norm_1 = sqrt(r_ab2_x_1 * r_ab2_x_1 + r_ab2_y_1 * r_ab2_y_1); - float r_ab2_norm_2 = sqrt(r_ab2_x_2 * r_ab2_x_2 + r_ab2_y_2 * r_ab2_y_2); - float r_ab2_norm_3 = sqrt(r_ab2_x_3 * r_ab2_x_3 + r_ab2_y_3 * r_ab2_y_3); - - r_ab2_norm_0 = r_ab2_norm_0 > EPS ? r_ab2_norm_0 : EPS; - r_ab2_norm_1 = r_ab2_norm_1 > EPS ? r_ab2_norm_1 : EPS; - r_ab2_norm_2 = r_ab2_norm_2 > EPS ? r_ab2_norm_2 : EPS; - r_ab2_norm_3 = r_ab2_norm_3 > EPS ? r_ab2_norm_3 : EPS; - - float r_ab_norm_sum_0 = r_ab_norm_0 + r_ab2_norm_0; - float r_ab_norm_sum_1 = r_ab_norm_1 + r_ab2_norm_1; - float r_ab_norm_sum_2 = r_ab_norm_2 + r_ab2_norm_2; - float r_ab_norm_sum_3 = r_ab_norm_3 + r_ab2_norm_3; - - float two_b_sq_0 = r_ab_norm_sum_0 * r_ab_norm_sum_0 - sb_sq[j]; - float two_b_sq_1 = r_ab_norm_sum_1 * r_ab_norm_sum_1 - sb_sq[j + 1]; - float two_b_sq_2 = r_ab_norm_sum_2 * r_ab_norm_sum_2 - sb_sq[j + 2]; - float two_b_sq_3 = r_ab_norm_sum_3 * r_ab_norm_sum_3 - sb_sq[j + 3]; - - two_b_sq_0 = two_b_sq_0 > EPS_SQ ? two_b_sq_0 : EPS_SQ; - two_b_sq_1 = two_b_sq_1 > EPS_SQ ? two_b_sq_1 : EPS_SQ; - two_b_sq_2 = two_b_sq_2 > EPS_SQ ? two_b_sq_2 : EPS_SQ; - two_b_sq_3 = two_b_sq_3 > EPS_SQ ? two_b_sq_3 : EPS_SQ; - - float two_b_0 = sqrt(two_b_sq_0); - float two_b_1 = sqrt(two_b_sq_1); - float two_b_2 = sqrt(two_b_sq_2); - float two_b_3 = sqrt(two_b_sq_3); - - float scalar_mult_common_0 = (r_ab_norm_sum_0 / (two_b_0 * r_ab_norm_0 * r_ab2_norm_0)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_0 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_1 = (r_ab_norm_sum_1 / (two_b_1 * r_ab_norm_1 * r_ab2_norm_1)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_1 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_2 = (r_ab_norm_sum_2 / (two_b_2 * r_ab_norm_2 * r_ab2_norm_2)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_2 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_3 = (r_ab_norm_sum_3 / (two_b_3 * r_ab_norm_3 * r_ab2_norm_3)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_3 * NEG_TWO_SIGMA_INV)); - - float scalar_mult_r_ab_0 = scalar_mult_common_0 * r_ab2_norm_0; - float scalar_mult_r_ab_1 = scalar_mult_common_1 * r_ab2_norm_1; - float scalar_mult_r_ab_2 = scalar_mult_common_2 * r_ab2_norm_2; - float scalar_mult_r_ab_3 = scalar_mult_common_3 * r_ab2_norm_3; - - float scalar_mult_r_ab2_0 = scalar_mult_common_0 * r_ab_norm_0; - float scalar_mult_r_ab2_1 = scalar_mult_common_1 * r_ab_norm_1; - float scalar_mult_r_ab2_2 = scalar_mult_common_2 * r_ab_norm_2; - float scalar_mult_r_ab2_3 = scalar_mult_common_3 * r_ab_norm_3; - - float f_alpha_beta_neg_x_0 = r_ab_x_0 * scalar_mult_r_ab_0 + r_ab2_x_0 * scalar_mult_r_ab2_0; - float f_alpha_beta_neg_x_1 = r_ab_x_1 * scalar_mult_r_ab_1 + r_ab2_x_1 * scalar_mult_r_ab2_1; - float f_alpha_beta_neg_x_2 = r_ab_x_2 * scalar_mult_r_ab_2 + r_ab2_x_2 * scalar_mult_r_ab2_2; - float f_alpha_beta_neg_x_3 = r_ab_x_3 * scalar_mult_r_ab_3 + r_ab2_x_3 * scalar_mult_r_ab2_3; - - float f_alpha_beta_neg_y_0 = r_ab_y_0 * scalar_mult_r_ab_0 + r_ab2_y_0 * scalar_mult_r_ab2_0; - float f_alpha_beta_neg_y_1 = r_ab_y_1 * scalar_mult_r_ab_1 + r_ab2_y_1 * scalar_mult_r_ab2_1; - float f_alpha_beta_neg_y_2 = r_ab_y_2 * scalar_mult_r_ab_2 + r_ab2_y_2 * scalar_mult_r_ab2_2; - float f_alpha_beta_neg_y_3 = r_ab_y_3 * scalar_mult_r_ab_3 + r_ab2_y_3 * scalar_mult_r_ab2_3; - - float w_val_0, w_val_1, w_val_2, w_val_3; - - float f_norm_sq_0 = f_alpha_beta_neg_x_0 * f_alpha_beta_neg_x_0 + f_alpha_beta_neg_y_0 * f_alpha_beta_neg_y_0; - float f_norm_sq_1 = f_alpha_beta_neg_x_1 * f_alpha_beta_neg_x_1 + f_alpha_beta_neg_y_1 * f_alpha_beta_neg_y_1; - float f_norm_sq_2 = f_alpha_beta_neg_x_2 * f_alpha_beta_neg_x_2 + f_alpha_beta_neg_y_2 * f_alpha_beta_neg_y_2; - float f_norm_sq_3 = f_alpha_beta_neg_x_3 * f_alpha_beta_neg_x_3 + f_alpha_beta_neg_y_3 * f_alpha_beta_neg_y_3; - - float rhs_0 = f_norm_sq_0 * cos_phi_sq; - float rhs_1 = f_norm_sq_1 * cos_phi_sq; - float rhs_2 = f_norm_sq_2 * cos_phi_sq; - float rhs_3 = f_norm_sq_3 * cos_phi_sq; - - float e_dot_f_0 = e_x_i * f_alpha_beta_neg_x_0 + e_y_i * f_alpha_beta_neg_y_0; - float e_dot_f_1 = e_x_i * f_alpha_beta_neg_x_1 + e_y_i * f_alpha_beta_neg_y_1; - float e_dot_f_2 = e_x_i * f_alpha_beta_neg_x_2 + e_y_i * f_alpha_beta_neg_y_2; - float e_dot_f_3 = e_x_i * f_alpha_beta_neg_x_3 + e_y_i * f_alpha_beta_neg_y_3; - - float e_dot_f_sq_0 = e_dot_f_0 * e_dot_f_0; - float e_dot_f_sq_1 = e_dot_f_1 * e_dot_f_1; - float e_dot_f_sq_2 = e_dot_f_2 * e_dot_f_2; - float e_dot_f_sq_3 = e_dot_f_3 * e_dot_f_3; - - if (e_dot_f_0 >= 0.0 || e_dot_f_sq_0 <= rhs_0) - w_val_0 = dt_neg; - else - w_val_0 = c_neg_times_dt; - if (e_dot_f_1 >= 0.0 || e_dot_f_sq_1 <= rhs_1) - w_val_1 = dt_neg; - else - w_val_1 = c_neg_times_dt; - if (e_dot_f_2 >= 0.0 || e_dot_f_sq_2 <= rhs_2) - w_val_2 = dt_neg; - else - w_val_2 = c_neg_times_dt; - if (e_dot_f_3 >= 0.0 || e_dot_f_sq_3 <= rhs_3) - w_val_3 = dt_neg; - else - w_val_3 = c_neg_times_dt; - - acc_x_0 += f_alpha_beta_neg_x_0 * w_val_0; - acc_x_1 += f_alpha_beta_neg_x_1 * w_val_1; - acc_x_2 += f_alpha_beta_neg_x_2 * w_val_2; - acc_x_3 += f_alpha_beta_neg_x_3 * w_val_3; - acc_y_0 += f_alpha_beta_neg_y_0 * w_val_0; - acc_y_1 += f_alpha_beta_neg_y_1 * w_val_1; - acc_y_2 += f_alpha_beta_neg_y_2 * w_val_2; - acc_y_3 += f_alpha_beta_neg_y_3 * w_val_3; - } - - // remainder of the j > i half, single lane. # one j = 66 FLOPS - for (; j < n_p; j++) { - float r_ab_x = r_ab_x_lut[i * n_p + j]; - float r_ab_y = r_ab_y_lut[i * n_p + j]; - float r_ab_norm = r_ab_norm_lut[i * n_p + j]; - - r_ab_norm = r_ab_norm > EPS ? r_ab_norm : EPS; - - // # 1 ADD - float r_ab2_x = r_ab_x - sb_e_x[j]; - // # 1 ADD - float r_ab2_y = r_ab_y - sb_e_y[j]; - - // # 1 ADD, 2 MULTs, 1 SQRT - float r_ab2_norm = sqrt(r_ab2_x * r_ab2_x + r_ab2_y * r_ab2_y); - r_ab2_norm = r_ab2_norm > EPS ? r_ab2_norm : EPS; - - // # 1 ADD - float r_ab_norm_sum = r_ab_norm + r_ab2_norm; - - // # 1 ADD, 1 MULT - float two_b_sq = r_ab_norm_sum * r_ab_norm_sum - sb_sq[j]; - two_b_sq = two_b_sq > EPS_SQ ? two_b_sq : EPS_SQ; - // # 1 SQRT - float two_b = sqrt(two_b_sq); - // # 5 MULTs, 1 DIV, 1 EXP - float scalar_mult_common = (r_ab_norm_sum / (two_b * r_ab_norm * r_ab2_norm)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b * NEG_TWO_SIGMA_INV)); - // # 1 MULT - float scalar_mult_r_ab = scalar_mult_common * r_ab2_norm; - // # 1 MULT - float scalar_mult_r_ab2 = scalar_mult_common * r_ab_norm; - - // # 1 ADD, 2 MULTs - float f_alpha_beta_neg_x = r_ab_x * scalar_mult_r_ab + r_ab2_x * scalar_mult_r_ab2; - // # 1 ADD, 2 MULTs - float f_alpha_beta_neg_y = r_ab_y * scalar_mult_r_ab + r_ab2_y * scalar_mult_r_ab2; - - float w_val; - - // # 1 ADD, 2 MULTs - float f_norm_sq = f_alpha_beta_neg_x * f_alpha_beta_neg_x + f_alpha_beta_neg_y * f_alpha_beta_neg_y; - // # 1 MULT - float rhs = f_norm_sq * cos_phi_sq; - // # 1 ADD, 2 MULTs - float e_dot_f = e_x[i] * f_alpha_beta_neg_x + e_y[i] * f_alpha_beta_neg_y; - // # 1 MULT - float e_dot_f_sq = e_dot_f * e_dot_f; - if (e_dot_f >= 0.0 || e_dot_f_sq <= rhs) - w_val = dt_neg; - else - w_val = c_neg_times_dt; - - // # 1 ADD, 1 MULT - f_alpha_dt_x += f_alpha_beta_neg_x * w_val; - // # 1 ADD, 1 MULT - f_alpha_dt_y += f_alpha_beta_neg_y * w_val; - } - - // reduction of the j > i accumulators. # K adds per line (K=4) => 8 ADDs - f_alpha_dt_x += acc_x_0 + acc_x_1 + acc_x_2 + acc_x_3; - f_alpha_dt_y += acc_y_0 + acc_y_1 + acc_y_2 + acc_y_3; - - // force between pedestrian and obstacles - // # one obstacle = 55 FLOPS (w_val sign-based, no a*a / b_sq) - for (int k = 0; k < board.n_obstacles; k++) { - // # 1 ADD - float v1_x = pos_x[i] - board.obstacles[k].start_x; - // # 1 ADD - float v1_y = pos_y[i] - board.obstacles[k].start_y; - float v2_x = board.obstacles[k].obstacle_v_x; - float v2_y = board.obstacles[k].obstacle_v_y; - - // # 1 ADD, 3 MULTs - float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; - - if (projection < 0.0) - projection = 0.0; - else if (projection > 1.0) - projection = 1.0; - - // # 2 ADDs, 1 MULT - float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); - // # 2 ADDs, 1 MULT - float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); - - // # 1 ADD, 2 MULTs, 1 SQRT - float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); - r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; - - // # 2 MULTs, 1 DIV, 1 EXP - float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; - // # 1 MULT - float f_alpha_B_neg_x = r_aB_x * scalar_mult; - // # 1 MULT - float f_alpha_B_neg_y = r_aB_y * scalar_mult; - - float w_val; - - // sign select only, no flops - float e_dot_f = (f_alpha_B_neg_y == 0) ? 0 : (f_alpha_B_neg_y < 0 ? -e_y[i] : e_y[i]); - - if (e_dot_f >= cos_phi) - w_val = dt_neg; - else - w_val = c_neg_times_dt; - - // # 1 MULT - float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; - // # 1 MULT - float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; - - // # 1 ADD - f_alpha_dt_x += f_alpha_B_dt_x; - // # 1 ADD - f_alpha_dt_y += f_alpha_B_dt_y; - } - - // # 1 ADD - w_x[i] += f_alpha_dt_x; - // # 1 ADD - w_y[i] += f_alpha_dt_y; - } - - // update each pedestrian - // # 29 FLOPS per pedestrian - for (int i = 0; i < n_p; i++) { - - // # 1 ADD, 2 MULTs, 1 SQRT - float w_norm = sqrt(w_x[i] * w_x[i] + w_y[i] * w_y[i]); - - float w_norm2 = w_norm > EPS ? w_norm : EPS; - - // # 1 DIV - float correction_factor = min(1.0f, v_max[i] / w_norm2); - - // # 1 MULT - curr_vel_x[i] = w_x[i] * correction_factor; - // # 1 MULT - curr_vel_y[i] = w_y[i] * correction_factor; - - // # 1 ADD, 1 MULT - pos_x[i] = pos_x[i] + curr_vel_x[i] * dt; - // # 1 ADD, 1 MULT - pos_y[i] = pos_y[i] + curr_vel_y[i] * dt; - - if (color[i] == 0 && pos_x[i] > (BOARD_LENGTH - 1.5)) { - pos_x[i] = 1.0; - destination_y[i] = pos_y[i]; - w_x[i] = desired_v0[i]; - w_y[i] = 0.0; - curr_vel_x[i] = w_x[i]; - curr_vel_y[i] = w_y[i]; - } - if (color[i] == 1 && pos_x[i] < 1.5) { - pos_x[i] = BOARD_LENGTH - 1.0; - destination_y[i] = pos_y[i]; - w_x[i] = -desired_v0[i]; - w_y[i] = 0.0; - curr_vel_x[i] = w_x[i]; - curr_vel_y[i] = w_y[i]; - } - - pos_y[i] = clamp(pos_y[i], WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - - // # 1 ADD - float ex = destination_x[i] - pos_x[i]; - // # 1 ADD - float ey = destination_y[i] - pos_y[i]; - - // # 1 ADD, 2 MULTs, 1 SQRT - float e_norm = sqrt(ex * ex + ey * ey); - float e_norm2 = e_norm > EPS ? e_norm : EPS; - // # 1 DIV - float e_norm_inv = 1.0 / e_norm2; - - // # 1 MULT - e_x[i] = ex * e_norm_inv; - // # 1 MULT - e_y[i] = ey * e_norm_inv; - - // # 1 ADD, 2 MULTs - float velocity_norm_sq = curr_vel_x[i] * curr_vel_x[i] + curr_vel_y[i] * curr_vel_y[i]; - - // # 1 SQRT - float velocity_norm = sqrt(velocity_norm_sq); - - // # 1 MULT - sb_sq[i] = velocity_norm_sq * delta_t_sq; - - // # 2 MULTs (velocity_norm*delta_t written on both lines, counted as is) - sb_e_x[i] = e_x[i] * (velocity_norm * delta_t); - // # 2 MULTs - sb_e_y[i] = e_y[i] * (velocity_norm * delta_t); - -#if !BENCHMARK - if (dump_path && (t % dump_interval == 0)) { - samples.emplace_back(t + 1, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } -#endif - } - } - -#if !BENCHMARK - if (dump_path) { - ofstream out(dump_path); - out << "time,id,x,y,p.e.x,p.e.y,color\n"; - - for (auto &[t, id, x, y, e_x, e_y, c] : samples) { - out << t << ',' << id << ',' << x << ',' << y << ',' << e_x << ',' << e_y << ',' << c << '\n'; - } - } -#endif - - return 0; -} diff --git a/variants/variant_float_inlining_SoA_symmetry_ILP_8_flopcount.cpp b/variants/variant_float_inlining_SoA_symmetry_ILP_8_flopcount.cpp deleted file mode 100644 index 0ef7642..0000000 --- a/variants/variant_float_inlining_SoA_symmetry_ILP_8_flopcount.cpp +++ /dev/null @@ -1,1042 +0,0 @@ -// # Changes: Added ILP for j-loop with K = 8 -// # added flopcount -// FLOPCOUNT = n_iter * ( 69 * n_p ** 2 + 55 * n_obstacles * n_p ) // the linear n_p term cancels (4*K - 32 = 0) -// # Predecessor: variant_float_inlining_SoA_symmetry_ILP_4.cpp - -#include "../headers/board_reduced_float.hpp" -#include "../headers/constants_float.hpp" -#include "../headers/pedestrian_reduced_float.hpp" - -#include -#include -#include - -#define SEED 42 -#define BOARD_WIDTH 10.0f -#define BOARD_LENGTH 50.0f -#define WALL_EPS 1e-3f -#define BOARD_WIDTH_MINUS_WALL_EPS 9.999f - -#ifndef RANDOM_SEED -#define RANDOM_SEED 0 -#endif - -#ifndef BENCHMARK -#define BENCHMARK 0 -#endif - -using namespace std; - -vector pos_x, pos_y; -vector sb_sq; -vector sb_e_x, sb_e_y; -vector e_x, e_y; -vector curr_vel_x, curr_vel_y; -vector w_x, w_y; -vector desired_v0; -vector v_max; -vector destination_x, destination_y; -vector color; - -Pedestrian *init_pedestrians(int n_p) { -#if RANDOM_SEED - random_device rd; - mt19937 gen(rd()); -#else - mt19937 gen(SEED); -#endif - - normal_distribution velocity_gen(v0_mean, v0_std_dev); - uniform_real_distribution y_gen(0.3, BOARD_WIDTH - 0.3); - uniform_real_distribution x_gen_left(2.0, BOARD_LENGTH / 2.0); - uniform_real_distribution x_gen_right(BOARD_LENGTH / 2.0, BOARD_LENGTH - 2.0); - - pos_x.resize(n_p); - pos_y.resize(n_p); - sb_sq.resize(n_p); - sb_e_x.resize(n_p); - sb_e_y.resize(n_p); - e_x.resize(n_p); - e_y.resize(n_p); - curr_vel_x.resize(n_p); - curr_vel_y.resize(n_p); - w_x.resize(n_p); - w_y.resize(n_p); - desired_v0.resize(n_p); - v_max.resize(n_p); - destination_x.resize(n_p); - destination_y.resize(n_p); - color.resize(n_p); - - int n_p_half = n_p / 2; - - for (int i = 0; i < n_p_half; i++) { - float x = x_gen_left(gen); - float y = y_gen(gen); - - float dest_x = BOARD_LENGTH + 30.0; - float dest_y = y; - - float init_e_x = dest_x - x; - float init_e_y = dest_y - y; - float init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - float init_e_unit_x = init_e_x / init_e_norm; - float init_e_unit_y = init_e_y / init_e_norm; - - float d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1); - - float v_m = 1.3 * d_v0; - - color[i] = 0; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - w_x[i] = 0.0f; - w_y[i] = 0.0f; - curr_vel_x[i] = 0.0f; - curr_vel_y[i] = 0.0f; - sb_sq[i] = 0.0f; - sb_e_x[i] = 0.0f; - sb_e_y[i] = 0.0f; - } - - for (int i = n_p_half; i < n_p; i++) { - float x = x_gen_right(gen); - float y = y_gen(gen); - - float dest_x = -30; - float dest_y = y; - - float init_e_x = dest_x - x; - float init_e_y = dest_y - y; - float init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - float init_e_unit_x = init_e_x / init_e_norm; - float init_e_unit_y = init_e_y / init_e_norm; - - float d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1); - - float v_m = 1.3 * d_v0; - - color[i] = 1; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - w_x[i] = 0.0f; - w_y[i] = 0.0f; - curr_vel_x[i] = 0.0f; - curr_vel_y[i] = 0.0f; - sb_sq[i] = 0.0f; - sb_e_x[i] = 0.0f; - sb_e_y[i] = 0.0f; - } - - return nullptr; -} - -Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } - -int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { - (void)pedestrians; -#if BENCHMARK - (void)dump_path; -#endif - -#if !BENCHMARK - const int dump_interval = 1; - - vector> samples; - - if (dump_path) { - samples.reserve(static_cast(n_iter / dump_interval + 1) * n_p); - - for (int i = 0; i < n_p; i++) { - samples.emplace_back(0, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } - } -#endif - - vector r_ab_x_lut(n_p * n_p, 0.0); - vector r_ab_y_lut(n_p * n_p, 0.0); - vector r_ab_norm_lut(n_p * n_p, 0.0); - - // FLOPCOUNT (everything inside the t-loop). EXP kept as its own op (one real exp() per call). - // section costs: overhead 4 ADD 4 MULT (+ reductions 4*K = 32 ADD, K=8) | - // distance pair 3 ADD 2 MULT 1 SQRT | - // ped-ped j 11 ADD 22 MULT 2 SQRT 1 DIV 1 EXP | - // obstacle 10 ADD 13 MULT 1 SQRT 1 DIV 1 EXP | update 7 ADD 17 MULT 3 SQRT 2 DIV - - // # ADDs: n_iter * ( - // # n_p * 36 + - // # 0.5 * (n_p*n_p - n_p) * 3 + - // # n_p * (n_p - 1) * 11 + - // # n_p * board.n_obstacles * 10 + - // # n_p * 7 - // # ) - - // # MULTs: n_iter * ( - // # n_p * 4 + - // # 0.5 * (n_p*n_p - n_p) * 2 + - // # n_p * (n_p - 1) * 22 + - // # n_p * board.n_obstacles * 13 + - // # n_p * 17 - // # ) - - // # DIVs: n_iter * ( - // # n_p * (n_p - 1) + - // # n_p * board.n_obstacles + - // # n_p * 2 - // # ) - - // # SQRTs: n_iter * ( - // # 0.5 * (n_p*n_p - n_p) + - // # n_p * (n_p - 1) * 2 + - // # n_p * board.n_obstacles + - // # n_p * 3 - // # ) - - // # EXPs: n_iter * ( - // # n_p * (n_p - 1) + - // # n_p * board.n_obstacles - // # ) - - // total with EXP = 30: n_iter * ( 69 * n_p ** 2 + 55 * n_obstacles * n_p ) // linear term cancels - for (int t = 0; t < n_iter; t++) { - for (int i = 0; i < n_p; i++) { - - // # 1 MULT - float desired_velocity_x = e_x[i] * desired_v0[i]; - // # 1 MULT - float desired_velocity_y = e_y[i] * desired_v0[i]; - // # 1 ADD, 1 MULT - float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; - // # 1 ADD, 1 MULT - float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; - - float e_x_i = e_x[i]; - float e_y_i = e_y[i]; - float pos_x_i = pos_x[i]; - float pos_y_i = pos_y[i]; - - // distance precompute, # each pair: 6 FLOPS, total over all i = 0.5*(n_p*n_p - n_p)*6 - for (int j = i + 1; j < n_p; j++) { - // # 1 ADD - float dx = pos_x_i - pos_x[j]; - // # 1 ADD - float dy = pos_y_i - pos_y[j]; - // # 1 ADD, 2 MULTs, 1 SQRT - float norm = sqrt(dx * dx + dy * dy); - int idx = i * n_p + j; - r_ab_x_lut[idx] = dx; - r_ab_y_lut[idx] = dy; - r_ab_norm_lut[idx] = norm; - } - - int j; - - float acc_x_0 = 0.0f, acc_x_1 = 0.0f, acc_x_2 = 0.0f, acc_x_3 = 0.0f; - float acc_x_4 = 0.0f, acc_x_5 = 0.0f, acc_x_6 = 0.0f, acc_x_7 = 0.0f; - float acc_y_0 = 0.0f, acc_y_1 = 0.0f, acc_y_2 = 0.0f, acc_y_3 = 0.0f; - float acc_y_4 = 0.0f, acc_y_5 = 0.0f, acc_y_6 = 0.0f, acc_y_7 = 0.0f; - - // ILP over the j < i half. # each lane = 66 FLOPS (per-line breakdown is the - // same as the single-lane remainder loop below), K = 8 lanes per step - for (j = 0; j + 8 < i; j += 8) { - float r_ab_x_0 = -1 * r_ab_x_lut[j * n_p + i]; - float r_ab_x_1 = -1 * r_ab_x_lut[(j + 1) * n_p + i]; - float r_ab_x_2 = -1 * r_ab_x_lut[(j + 2) * n_p + i]; - float r_ab_x_3 = -1 * r_ab_x_lut[(j + 3) * n_p + i]; - float r_ab_x_4 = -1 * r_ab_x_lut[(j + 4) * n_p + i]; - float r_ab_x_5 = -1 * r_ab_x_lut[(j + 5) * n_p + i]; - float r_ab_x_6 = -1 * r_ab_x_lut[(j + 6) * n_p + i]; - float r_ab_x_7 = -1 * r_ab_x_lut[(j + 7) * n_p + i]; - - float r_ab_y_0 = -1 * r_ab_y_lut[j * n_p + i]; - float r_ab_y_1 = -1 * r_ab_y_lut[(j + 1) * n_p + i]; - float r_ab_y_2 = -1 * r_ab_y_lut[(j + 2) * n_p + i]; - float r_ab_y_3 = -1 * r_ab_y_lut[(j + 3) * n_p + i]; - float r_ab_y_4 = -1 * r_ab_y_lut[(j + 4) * n_p + i]; - float r_ab_y_5 = -1 * r_ab_y_lut[(j + 5) * n_p + i]; - float r_ab_y_6 = -1 * r_ab_y_lut[(j + 6) * n_p + i]; - float r_ab_y_7 = -1 * r_ab_y_lut[(j + 7) * n_p + i]; - - float r_ab_norm_0 = r_ab_norm_lut[j * n_p + i]; - float r_ab_norm_1 = r_ab_norm_lut[(j + 1) * n_p + i]; - float r_ab_norm_2 = r_ab_norm_lut[(j + 2) * n_p + i]; - float r_ab_norm_3 = r_ab_norm_lut[(j + 3) * n_p + i]; - float r_ab_norm_4 = r_ab_norm_lut[(j + 4) * n_p + i]; - float r_ab_norm_5 = r_ab_norm_lut[(j + 5) * n_p + i]; - float r_ab_norm_6 = r_ab_norm_lut[(j + 6) * n_p + i]; - float r_ab_norm_7 = r_ab_norm_lut[(j + 7) * n_p + i]; - - r_ab_norm_0 = r_ab_norm_0 > EPS ? r_ab_norm_0 : EPS; - r_ab_norm_1 = r_ab_norm_1 > EPS ? r_ab_norm_1 : EPS; - r_ab_norm_2 = r_ab_norm_2 > EPS ? r_ab_norm_2 : EPS; - r_ab_norm_3 = r_ab_norm_3 > EPS ? r_ab_norm_3 : EPS; - r_ab_norm_4 = r_ab_norm_4 > EPS ? r_ab_norm_4 : EPS; - r_ab_norm_5 = r_ab_norm_5 > EPS ? r_ab_norm_5 : EPS; - r_ab_norm_6 = r_ab_norm_6 > EPS ? r_ab_norm_6 : EPS; - r_ab_norm_7 = r_ab_norm_7 > EPS ? r_ab_norm_7 : EPS; - - float r_ab2_x_0 = r_ab_x_0 - sb_e_x[j]; - float r_ab2_x_1 = r_ab_x_1 - sb_e_x[j + 1]; - float r_ab2_x_2 = r_ab_x_2 - sb_e_x[j + 2]; - float r_ab2_x_3 = r_ab_x_3 - sb_e_x[j + 3]; - float r_ab2_x_4 = r_ab_x_4 - sb_e_x[j + 4]; - float r_ab2_x_5 = r_ab_x_5 - sb_e_x[j + 5]; - float r_ab2_x_6 = r_ab_x_6 - sb_e_x[j + 6]; - float r_ab2_x_7 = r_ab_x_7 - sb_e_x[j + 7]; - - float r_ab2_y_0 = r_ab_y_0 - sb_e_y[j]; - float r_ab2_y_1 = r_ab_y_1 - sb_e_y[j + 1]; - float r_ab2_y_2 = r_ab_y_2 - sb_e_y[j + 2]; - float r_ab2_y_3 = r_ab_y_3 - sb_e_y[j + 3]; - float r_ab2_y_4 = r_ab_y_4 - sb_e_y[j + 4]; - float r_ab2_y_5 = r_ab_y_5 - sb_e_y[j + 5]; - float r_ab2_y_6 = r_ab_y_6 - sb_e_y[j + 6]; - float r_ab2_y_7 = r_ab_y_7 - sb_e_y[j + 7]; - - float r_ab2_norm_0 = sqrt(r_ab2_x_0 * r_ab2_x_0 + r_ab2_y_0 * r_ab2_y_0); - float r_ab2_norm_1 = sqrt(r_ab2_x_1 * r_ab2_x_1 + r_ab2_y_1 * r_ab2_y_1); - float r_ab2_norm_2 = sqrt(r_ab2_x_2 * r_ab2_x_2 + r_ab2_y_2 * r_ab2_y_2); - float r_ab2_norm_3 = sqrt(r_ab2_x_3 * r_ab2_x_3 + r_ab2_y_3 * r_ab2_y_3); - float r_ab2_norm_4 = sqrt(r_ab2_x_4 * r_ab2_x_4 + r_ab2_y_4 * r_ab2_y_4); - float r_ab2_norm_5 = sqrt(r_ab2_x_5 * r_ab2_x_5 + r_ab2_y_5 * r_ab2_y_5); - float r_ab2_norm_6 = sqrt(r_ab2_x_6 * r_ab2_x_6 + r_ab2_y_6 * r_ab2_y_6); - float r_ab2_norm_7 = sqrt(r_ab2_x_7 * r_ab2_x_7 + r_ab2_y_7 * r_ab2_y_7); - - r_ab2_norm_0 = r_ab2_norm_0 > EPS ? r_ab2_norm_0 : EPS; - r_ab2_norm_1 = r_ab2_norm_1 > EPS ? r_ab2_norm_1 : EPS; - r_ab2_norm_2 = r_ab2_norm_2 > EPS ? r_ab2_norm_2 : EPS; - r_ab2_norm_3 = r_ab2_norm_3 > EPS ? r_ab2_norm_3 : EPS; - r_ab2_norm_4 = r_ab2_norm_4 > EPS ? r_ab2_norm_4 : EPS; - r_ab2_norm_5 = r_ab2_norm_5 > EPS ? r_ab2_norm_5 : EPS; - r_ab2_norm_6 = r_ab2_norm_6 > EPS ? r_ab2_norm_6 : EPS; - r_ab2_norm_7 = r_ab2_norm_7 > EPS ? r_ab2_norm_7 : EPS; - - float r_ab_norm_sum_0 = r_ab_norm_0 + r_ab2_norm_0; - float r_ab_norm_sum_1 = r_ab_norm_1 + r_ab2_norm_1; - float r_ab_norm_sum_2 = r_ab_norm_2 + r_ab2_norm_2; - float r_ab_norm_sum_3 = r_ab_norm_3 + r_ab2_norm_3; - float r_ab_norm_sum_4 = r_ab_norm_4 + r_ab2_norm_4; - float r_ab_norm_sum_5 = r_ab_norm_5 + r_ab2_norm_5; - float r_ab_norm_sum_6 = r_ab_norm_6 + r_ab2_norm_6; - float r_ab_norm_sum_7 = r_ab_norm_7 + r_ab2_norm_7; - - float two_b_sq_0 = r_ab_norm_sum_0 * r_ab_norm_sum_0 - sb_sq[j]; - float two_b_sq_1 = r_ab_norm_sum_1 * r_ab_norm_sum_1 - sb_sq[j + 1]; - float two_b_sq_2 = r_ab_norm_sum_2 * r_ab_norm_sum_2 - sb_sq[j + 2]; - float two_b_sq_3 = r_ab_norm_sum_3 * r_ab_norm_sum_3 - sb_sq[j + 3]; - float two_b_sq_4 = r_ab_norm_sum_4 * r_ab_norm_sum_4 - sb_sq[j + 4]; - float two_b_sq_5 = r_ab_norm_sum_5 * r_ab_norm_sum_5 - sb_sq[j + 5]; - float two_b_sq_6 = r_ab_norm_sum_6 * r_ab_norm_sum_6 - sb_sq[j + 6]; - float two_b_sq_7 = r_ab_norm_sum_7 * r_ab_norm_sum_7 - sb_sq[j + 7]; - - two_b_sq_0 = two_b_sq_0 > EPS_SQ ? two_b_sq_0 : EPS_SQ; - two_b_sq_1 = two_b_sq_1 > EPS_SQ ? two_b_sq_1 : EPS_SQ; - two_b_sq_2 = two_b_sq_2 > EPS_SQ ? two_b_sq_2 : EPS_SQ; - two_b_sq_3 = two_b_sq_3 > EPS_SQ ? two_b_sq_3 : EPS_SQ; - two_b_sq_4 = two_b_sq_4 > EPS_SQ ? two_b_sq_4 : EPS_SQ; - two_b_sq_5 = two_b_sq_5 > EPS_SQ ? two_b_sq_5 : EPS_SQ; - two_b_sq_6 = two_b_sq_6 > EPS_SQ ? two_b_sq_6 : EPS_SQ; - two_b_sq_7 = two_b_sq_7 > EPS_SQ ? two_b_sq_7 : EPS_SQ; - - float two_b_0 = sqrt(two_b_sq_0); - float two_b_1 = sqrt(two_b_sq_1); - float two_b_2 = sqrt(two_b_sq_2); - float two_b_3 = sqrt(two_b_sq_3); - float two_b_4 = sqrt(two_b_sq_4); - float two_b_5 = sqrt(two_b_sq_5); - float two_b_6 = sqrt(two_b_sq_6); - float two_b_7 = sqrt(two_b_sq_7); - - float scalar_mult_common_0 = (r_ab_norm_sum_0 / (two_b_0 * r_ab_norm_0 * r_ab2_norm_0)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_0 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_1 = (r_ab_norm_sum_1 / (two_b_1 * r_ab_norm_1 * r_ab2_norm_1)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_1 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_2 = (r_ab_norm_sum_2 / (two_b_2 * r_ab_norm_2 * r_ab2_norm_2)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_2 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_3 = (r_ab_norm_sum_3 / (two_b_3 * r_ab_norm_3 * r_ab2_norm_3)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_3 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_4 = (r_ab_norm_sum_4 / (two_b_4 * r_ab_norm_4 * r_ab2_norm_4)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_4 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_5 = (r_ab_norm_sum_5 / (two_b_5 * r_ab_norm_5 * r_ab2_norm_5)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_5 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_6 = (r_ab_norm_sum_6 / (two_b_6 * r_ab_norm_6 * r_ab2_norm_6)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_6 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_7 = (r_ab_norm_sum_7 / (two_b_7 * r_ab_norm_7 * r_ab2_norm_7)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_7 * NEG_TWO_SIGMA_INV)); - - float scalar_mult_r_ab_0 = scalar_mult_common_0 * r_ab2_norm_0; - float scalar_mult_r_ab_1 = scalar_mult_common_1 * r_ab2_norm_1; - float scalar_mult_r_ab_2 = scalar_mult_common_2 * r_ab2_norm_2; - float scalar_mult_r_ab_3 = scalar_mult_common_3 * r_ab2_norm_3; - float scalar_mult_r_ab_4 = scalar_mult_common_4 * r_ab2_norm_4; - float scalar_mult_r_ab_5 = scalar_mult_common_5 * r_ab2_norm_5; - float scalar_mult_r_ab_6 = scalar_mult_common_6 * r_ab2_norm_6; - float scalar_mult_r_ab_7 = scalar_mult_common_7 * r_ab2_norm_7; - - float scalar_mult_r_ab2_0 = scalar_mult_common_0 * r_ab_norm_0; - float scalar_mult_r_ab2_1 = scalar_mult_common_1 * r_ab_norm_1; - float scalar_mult_r_ab2_2 = scalar_mult_common_2 * r_ab_norm_2; - float scalar_mult_r_ab2_3 = scalar_mult_common_3 * r_ab_norm_3; - float scalar_mult_r_ab2_4 = scalar_mult_common_4 * r_ab_norm_4; - float scalar_mult_r_ab2_5 = scalar_mult_common_5 * r_ab_norm_5; - float scalar_mult_r_ab2_6 = scalar_mult_common_6 * r_ab_norm_6; - float scalar_mult_r_ab2_7 = scalar_mult_common_7 * r_ab_norm_7; - - float f_alpha_beta_neg_x_0 = r_ab_x_0 * scalar_mult_r_ab_0 + r_ab2_x_0 * scalar_mult_r_ab2_0; - float f_alpha_beta_neg_x_1 = r_ab_x_1 * scalar_mult_r_ab_1 + r_ab2_x_1 * scalar_mult_r_ab2_1; - float f_alpha_beta_neg_x_2 = r_ab_x_2 * scalar_mult_r_ab_2 + r_ab2_x_2 * scalar_mult_r_ab2_2; - float f_alpha_beta_neg_x_3 = r_ab_x_3 * scalar_mult_r_ab_3 + r_ab2_x_3 * scalar_mult_r_ab2_3; - float f_alpha_beta_neg_x_4 = r_ab_x_4 * scalar_mult_r_ab_4 + r_ab2_x_4 * scalar_mult_r_ab2_4; - float f_alpha_beta_neg_x_5 = r_ab_x_5 * scalar_mult_r_ab_5 + r_ab2_x_5 * scalar_mult_r_ab2_5; - float f_alpha_beta_neg_x_6 = r_ab_x_6 * scalar_mult_r_ab_6 + r_ab2_x_6 * scalar_mult_r_ab2_6; - float f_alpha_beta_neg_x_7 = r_ab_x_7 * scalar_mult_r_ab_7 + r_ab2_x_7 * scalar_mult_r_ab2_7; - - float f_alpha_beta_neg_y_0 = r_ab_y_0 * scalar_mult_r_ab_0 + r_ab2_y_0 * scalar_mult_r_ab2_0; - float f_alpha_beta_neg_y_1 = r_ab_y_1 * scalar_mult_r_ab_1 + r_ab2_y_1 * scalar_mult_r_ab2_1; - float f_alpha_beta_neg_y_2 = r_ab_y_2 * scalar_mult_r_ab_2 + r_ab2_y_2 * scalar_mult_r_ab2_2; - float f_alpha_beta_neg_y_3 = r_ab_y_3 * scalar_mult_r_ab_3 + r_ab2_y_3 * scalar_mult_r_ab2_3; - float f_alpha_beta_neg_y_4 = r_ab_y_4 * scalar_mult_r_ab_4 + r_ab2_y_4 * scalar_mult_r_ab2_4; - float f_alpha_beta_neg_y_5 = r_ab_y_5 * scalar_mult_r_ab_5 + r_ab2_y_5 * scalar_mult_r_ab2_5; - float f_alpha_beta_neg_y_6 = r_ab_y_6 * scalar_mult_r_ab_6 + r_ab2_y_6 * scalar_mult_r_ab2_6; - float f_alpha_beta_neg_y_7 = r_ab_y_7 * scalar_mult_r_ab_7 + r_ab2_y_7 * scalar_mult_r_ab2_7; - - float w_val_0, w_val_1, w_val_2, w_val_3, w_val_4, w_val_5, w_val_6, w_val_7; - - float f_norm_sq_0 = f_alpha_beta_neg_x_0 * f_alpha_beta_neg_x_0 + f_alpha_beta_neg_y_0 * f_alpha_beta_neg_y_0; - float f_norm_sq_1 = f_alpha_beta_neg_x_1 * f_alpha_beta_neg_x_1 + f_alpha_beta_neg_y_1 * f_alpha_beta_neg_y_1; - float f_norm_sq_2 = f_alpha_beta_neg_x_2 * f_alpha_beta_neg_x_2 + f_alpha_beta_neg_y_2 * f_alpha_beta_neg_y_2; - float f_norm_sq_3 = f_alpha_beta_neg_x_3 * f_alpha_beta_neg_x_3 + f_alpha_beta_neg_y_3 * f_alpha_beta_neg_y_3; - float f_norm_sq_4 = f_alpha_beta_neg_x_4 * f_alpha_beta_neg_x_4 + f_alpha_beta_neg_y_4 * f_alpha_beta_neg_y_4; - float f_norm_sq_5 = f_alpha_beta_neg_x_5 * f_alpha_beta_neg_x_5 + f_alpha_beta_neg_y_5 * f_alpha_beta_neg_y_5; - float f_norm_sq_6 = f_alpha_beta_neg_x_6 * f_alpha_beta_neg_x_6 + f_alpha_beta_neg_y_6 * f_alpha_beta_neg_y_6; - float f_norm_sq_7 = f_alpha_beta_neg_x_7 * f_alpha_beta_neg_x_7 + f_alpha_beta_neg_y_7 * f_alpha_beta_neg_y_7; - - float rhs_0 = f_norm_sq_0 * cos_phi_sq; - float rhs_1 = f_norm_sq_1 * cos_phi_sq; - float rhs_2 = f_norm_sq_2 * cos_phi_sq; - float rhs_3 = f_norm_sq_3 * cos_phi_sq; - float rhs_4 = f_norm_sq_4 * cos_phi_sq; - float rhs_5 = f_norm_sq_5 * cos_phi_sq; - float rhs_6 = f_norm_sq_6 * cos_phi_sq; - float rhs_7 = f_norm_sq_7 * cos_phi_sq; - - float e_dot_f_0 = e_x_i * f_alpha_beta_neg_x_0 + e_y_i * f_alpha_beta_neg_y_0; - float e_dot_f_1 = e_x_i * f_alpha_beta_neg_x_1 + e_y_i * f_alpha_beta_neg_y_1; - float e_dot_f_2 = e_x_i * f_alpha_beta_neg_x_2 + e_y_i * f_alpha_beta_neg_y_2; - float e_dot_f_3 = e_x_i * f_alpha_beta_neg_x_3 + e_y_i * f_alpha_beta_neg_y_3; - float e_dot_f_4 = e_x_i * f_alpha_beta_neg_x_4 + e_y_i * f_alpha_beta_neg_y_4; - float e_dot_f_5 = e_x_i * f_alpha_beta_neg_x_5 + e_y_i * f_alpha_beta_neg_y_5; - float e_dot_f_6 = e_x_i * f_alpha_beta_neg_x_6 + e_y_i * f_alpha_beta_neg_y_6; - float e_dot_f_7 = e_x_i * f_alpha_beta_neg_x_7 + e_y_i * f_alpha_beta_neg_y_7; - - float e_dot_f_sq_0 = e_dot_f_0 * e_dot_f_0; - float e_dot_f_sq_1 = e_dot_f_1 * e_dot_f_1; - float e_dot_f_sq_2 = e_dot_f_2 * e_dot_f_2; - float e_dot_f_sq_3 = e_dot_f_3 * e_dot_f_3; - float e_dot_f_sq_4 = e_dot_f_4 * e_dot_f_4; - float e_dot_f_sq_5 = e_dot_f_5 * e_dot_f_5; - float e_dot_f_sq_6 = e_dot_f_6 * e_dot_f_6; - float e_dot_f_sq_7 = e_dot_f_7 * e_dot_f_7; - - if (e_dot_f_0 >= 0.0 || e_dot_f_sq_0 <= rhs_0) - w_val_0 = dt_neg; - else - w_val_0 = c_neg_times_dt; - if (e_dot_f_1 >= 0.0 || e_dot_f_sq_1 <= rhs_1) - w_val_1 = dt_neg; - else - w_val_1 = c_neg_times_dt; - if (e_dot_f_2 >= 0.0 || e_dot_f_sq_2 <= rhs_2) - w_val_2 = dt_neg; - else - w_val_2 = c_neg_times_dt; - if (e_dot_f_3 >= 0.0 || e_dot_f_sq_3 <= rhs_3) - w_val_3 = dt_neg; - else - w_val_3 = c_neg_times_dt; - if (e_dot_f_4 >= 0.0 || e_dot_f_sq_4 <= rhs_4) - w_val_4 = dt_neg; - else - w_val_4 = c_neg_times_dt; - if (e_dot_f_5 >= 0.0 || e_dot_f_sq_5 <= rhs_5) - w_val_5 = dt_neg; - else - w_val_5 = c_neg_times_dt; - if (e_dot_f_6 >= 0.0 || e_dot_f_sq_6 <= rhs_6) - w_val_6 = dt_neg; - else - w_val_6 = c_neg_times_dt; - if (e_dot_f_7 >= 0.0 || e_dot_f_sq_7 <= rhs_7) - w_val_7 = dt_neg; - else - w_val_7 = c_neg_times_dt; - - acc_x_0 += f_alpha_beta_neg_x_0 * w_val_0; - acc_x_1 += f_alpha_beta_neg_x_1 * w_val_1; - acc_x_2 += f_alpha_beta_neg_x_2 * w_val_2; - acc_x_3 += f_alpha_beta_neg_x_3 * w_val_3; - acc_x_4 += f_alpha_beta_neg_x_4 * w_val_4; - acc_x_5 += f_alpha_beta_neg_x_5 * w_val_5; - acc_x_6 += f_alpha_beta_neg_x_6 * w_val_6; - acc_x_7 += f_alpha_beta_neg_x_7 * w_val_7; - acc_y_0 += f_alpha_beta_neg_y_0 * w_val_0; - acc_y_1 += f_alpha_beta_neg_y_1 * w_val_1; - acc_y_2 += f_alpha_beta_neg_y_2 * w_val_2; - acc_y_3 += f_alpha_beta_neg_y_3 * w_val_3; - acc_y_4 += f_alpha_beta_neg_y_4 * w_val_4; - acc_y_5 += f_alpha_beta_neg_y_5 * w_val_5; - acc_y_6 += f_alpha_beta_neg_y_6 * w_val_6; - acc_y_7 += f_alpha_beta_neg_y_7 * w_val_7; - } - - // remainder of the j < i half, single lane. # one j = 66 FLOPS - for (; j < i; j++) { - // lut lookup + -1* sign flip: not counted - float r_ab_x = -1 * r_ab_x_lut[j * n_p + i]; - float r_ab_y = -1 * r_ab_y_lut[j * n_p + i]; - float r_ab_norm = r_ab_norm_lut[j * n_p + i]; - - r_ab_norm = r_ab_norm > EPS ? r_ab_norm : EPS; - - // # 1 ADD - float r_ab2_x = r_ab_x - sb_e_x[j]; - // # 1 ADD - float r_ab2_y = r_ab_y - sb_e_y[j]; - - // # 1 ADD, 2 MULTs, 1 SQRT - float r_ab2_norm = sqrt(r_ab2_x * r_ab2_x + r_ab2_y * r_ab2_y); - r_ab2_norm = r_ab2_norm > EPS ? r_ab2_norm : EPS; - - // # 1 ADD - float r_ab_norm_sum = r_ab_norm + r_ab2_norm; - - // # 1 ADD, 1 MULT - float two_b_sq = r_ab_norm_sum * r_ab_norm_sum - sb_sq[j]; - two_b_sq = two_b_sq > EPS_SQ ? two_b_sq : EPS_SQ; - // # 1 SQRT - float two_b = sqrt(two_b_sq); - // # 5 MULTs, 1 DIV, 1 EXP (= 36 FLOPS with EXP=30) - float scalar_mult_common = (r_ab_norm_sum / (two_b * r_ab_norm * r_ab2_norm)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b * NEG_TWO_SIGMA_INV)); - // # 1 MULT - float scalar_mult_r_ab = scalar_mult_common * r_ab2_norm; - // # 1 MULT - float scalar_mult_r_ab2 = scalar_mult_common * r_ab_norm; - - // # 1 ADD, 2 MULTs - float f_alpha_beta_neg_x = r_ab_x * scalar_mult_r_ab + r_ab2_x * scalar_mult_r_ab2; - // # 1 ADD, 2 MULTs - float f_alpha_beta_neg_y = r_ab_y * scalar_mult_r_ab + r_ab2_y * scalar_mult_r_ab2; - - float w_val; - - // # 1 ADD, 2 MULTs - float f_norm_sq = f_alpha_beta_neg_x * f_alpha_beta_neg_x + f_alpha_beta_neg_y * f_alpha_beta_neg_y; - // # 1 MULT - float rhs = f_norm_sq * cos_phi_sq; - // # 1 ADD, 2 MULTs - float e_dot_f = e_x[i] * f_alpha_beta_neg_x + e_y[i] * f_alpha_beta_neg_y; - // # 1 MULT - float e_dot_f_sq = e_dot_f * e_dot_f; - if (e_dot_f >= 0.0 || e_dot_f_sq <= rhs) - w_val = dt_neg; - else - w_val = c_neg_times_dt; - - // # 1 ADD, 1 MULT - f_alpha_dt_x += f_alpha_beta_neg_x * w_val; - // # 1 ADD, 1 MULT - f_alpha_dt_y += f_alpha_beta_neg_y * w_val; - } - - // reduction of the j < i accumulators. # K adds per line (K=8) => 16 ADDs - f_alpha_dt_x += acc_x_0 + acc_x_1 + acc_x_2 + acc_x_3 + acc_x_4 + acc_x_5 + acc_x_6 + acc_x_7; - f_alpha_dt_y += acc_y_0 + acc_y_1 + acc_y_2 + acc_y_3 + acc_y_4 + acc_y_5 + acc_y_6 + acc_y_7; - - acc_x_0 = 0.0f; - acc_x_1 = 0.0f; - acc_x_2 = 0.0f; - acc_x_3 = 0.0f; - acc_x_4 = 0.0f; - acc_x_5 = 0.0f; - acc_x_6 = 0.0f; - acc_x_7 = 0.0f; - acc_y_0 = 0.0f; - acc_y_1 = 0.0f; - acc_y_2 = 0.0f; - acc_y_3 = 0.0f; - acc_y_4 = 0.0f; - acc_y_5 = 0.0f; - acc_y_6 = 0.0f; - acc_y_7 = 0.0f; - - // ILP over the j > i half. # each lane = 66 FLOPS, K = 8 lanes per step - for (j = i + 1; j + 8 < n_p; j += 8) { - float r_ab_x_0 = r_ab_x_lut[i * n_p + j]; - float r_ab_x_1 = r_ab_x_lut[i * n_p + j + 1]; - float r_ab_x_2 = r_ab_x_lut[i * n_p + j + 2]; - float r_ab_x_3 = r_ab_x_lut[i * n_p + j + 3]; - float r_ab_x_4 = r_ab_x_lut[i * n_p + j + 4]; - float r_ab_x_5 = r_ab_x_lut[i * n_p + j + 5]; - float r_ab_x_6 = r_ab_x_lut[i * n_p + j + 6]; - float r_ab_x_7 = r_ab_x_lut[i * n_p + j + 7]; - - float r_ab_y_0 = r_ab_y_lut[i * n_p + j]; - float r_ab_y_1 = r_ab_y_lut[i * n_p + j + 1]; - float r_ab_y_2 = r_ab_y_lut[i * n_p + j + 2]; - float r_ab_y_3 = r_ab_y_lut[i * n_p + j + 3]; - float r_ab_y_4 = r_ab_y_lut[i * n_p + j + 4]; - float r_ab_y_5 = r_ab_y_lut[i * n_p + j + 5]; - float r_ab_y_6 = r_ab_y_lut[i * n_p + j + 6]; - float r_ab_y_7 = r_ab_y_lut[i * n_p + j + 7]; - - float r_ab_norm_0 = r_ab_norm_lut[i * n_p + j]; - float r_ab_norm_1 = r_ab_norm_lut[i * n_p + j + 1]; - float r_ab_norm_2 = r_ab_norm_lut[i * n_p + j + 2]; - float r_ab_norm_3 = r_ab_norm_lut[i * n_p + j + 3]; - float r_ab_norm_4 = r_ab_norm_lut[i * n_p + j + 4]; - float r_ab_norm_5 = r_ab_norm_lut[i * n_p + j + 5]; - float r_ab_norm_6 = r_ab_norm_lut[i * n_p + j + 6]; - float r_ab_norm_7 = r_ab_norm_lut[i * n_p + j + 7]; - - r_ab_norm_0 = r_ab_norm_0 > EPS ? r_ab_norm_0 : EPS; - r_ab_norm_1 = r_ab_norm_1 > EPS ? r_ab_norm_1 : EPS; - r_ab_norm_2 = r_ab_norm_2 > EPS ? r_ab_norm_2 : EPS; - r_ab_norm_3 = r_ab_norm_3 > EPS ? r_ab_norm_3 : EPS; - r_ab_norm_4 = r_ab_norm_4 > EPS ? r_ab_norm_4 : EPS; - r_ab_norm_5 = r_ab_norm_5 > EPS ? r_ab_norm_5 : EPS; - r_ab_norm_6 = r_ab_norm_6 > EPS ? r_ab_norm_6 : EPS; - r_ab_norm_7 = r_ab_norm_7 > EPS ? r_ab_norm_7 : EPS; - - float r_ab2_x_0 = r_ab_x_0 - sb_e_x[j]; - float r_ab2_x_1 = r_ab_x_1 - sb_e_x[j + 1]; - float r_ab2_x_2 = r_ab_x_2 - sb_e_x[j + 2]; - float r_ab2_x_3 = r_ab_x_3 - sb_e_x[j + 3]; - float r_ab2_x_4 = r_ab_x_4 - sb_e_x[j + 4]; - float r_ab2_x_5 = r_ab_x_5 - sb_e_x[j + 5]; - float r_ab2_x_6 = r_ab_x_6 - sb_e_x[j + 6]; - float r_ab2_x_7 = r_ab_x_7 - sb_e_x[j + 7]; - - float r_ab2_y_0 = r_ab_y_0 - sb_e_y[j]; - float r_ab2_y_1 = r_ab_y_1 - sb_e_y[j + 1]; - float r_ab2_y_2 = r_ab_y_2 - sb_e_y[j + 2]; - float r_ab2_y_3 = r_ab_y_3 - sb_e_y[j + 3]; - float r_ab2_y_4 = r_ab_y_4 - sb_e_y[j + 4]; - float r_ab2_y_5 = r_ab_y_5 - sb_e_y[j + 5]; - float r_ab2_y_6 = r_ab_y_6 - sb_e_y[j + 6]; - float r_ab2_y_7 = r_ab_y_7 - sb_e_y[j + 7]; - - float r_ab2_norm_0 = sqrt(r_ab2_x_0 * r_ab2_x_0 + r_ab2_y_0 * r_ab2_y_0); - float r_ab2_norm_1 = sqrt(r_ab2_x_1 * r_ab2_x_1 + r_ab2_y_1 * r_ab2_y_1); - float r_ab2_norm_2 = sqrt(r_ab2_x_2 * r_ab2_x_2 + r_ab2_y_2 * r_ab2_y_2); - float r_ab2_norm_3 = sqrt(r_ab2_x_3 * r_ab2_x_3 + r_ab2_y_3 * r_ab2_y_3); - float r_ab2_norm_4 = sqrt(r_ab2_x_4 * r_ab2_x_4 + r_ab2_y_4 * r_ab2_y_4); - float r_ab2_norm_5 = sqrt(r_ab2_x_5 * r_ab2_x_5 + r_ab2_y_5 * r_ab2_y_5); - float r_ab2_norm_6 = sqrt(r_ab2_x_6 * r_ab2_x_6 + r_ab2_y_6 * r_ab2_y_6); - float r_ab2_norm_7 = sqrt(r_ab2_x_7 * r_ab2_x_7 + r_ab2_y_7 * r_ab2_y_7); - - r_ab2_norm_0 = r_ab2_norm_0 > EPS ? r_ab2_norm_0 : EPS; - r_ab2_norm_1 = r_ab2_norm_1 > EPS ? r_ab2_norm_1 : EPS; - r_ab2_norm_2 = r_ab2_norm_2 > EPS ? r_ab2_norm_2 : EPS; - r_ab2_norm_3 = r_ab2_norm_3 > EPS ? r_ab2_norm_3 : EPS; - r_ab2_norm_4 = r_ab2_norm_4 > EPS ? r_ab2_norm_4 : EPS; - r_ab2_norm_5 = r_ab2_norm_5 > EPS ? r_ab2_norm_5 : EPS; - r_ab2_norm_6 = r_ab2_norm_6 > EPS ? r_ab2_norm_6 : EPS; - r_ab2_norm_7 = r_ab2_norm_7 > EPS ? r_ab2_norm_7 : EPS; - - float r_ab_norm_sum_0 = r_ab_norm_0 + r_ab2_norm_0; - float r_ab_norm_sum_1 = r_ab_norm_1 + r_ab2_norm_1; - float r_ab_norm_sum_2 = r_ab_norm_2 + r_ab2_norm_2; - float r_ab_norm_sum_3 = r_ab_norm_3 + r_ab2_norm_3; - float r_ab_norm_sum_4 = r_ab_norm_4 + r_ab2_norm_4; - float r_ab_norm_sum_5 = r_ab_norm_5 + r_ab2_norm_5; - float r_ab_norm_sum_6 = r_ab_norm_6 + r_ab2_norm_6; - float r_ab_norm_sum_7 = r_ab_norm_7 + r_ab2_norm_7; - - float two_b_sq_0 = r_ab_norm_sum_0 * r_ab_norm_sum_0 - sb_sq[j]; - float two_b_sq_1 = r_ab_norm_sum_1 * r_ab_norm_sum_1 - sb_sq[j + 1]; - float two_b_sq_2 = r_ab_norm_sum_2 * r_ab_norm_sum_2 - sb_sq[j + 2]; - float two_b_sq_3 = r_ab_norm_sum_3 * r_ab_norm_sum_3 - sb_sq[j + 3]; - float two_b_sq_4 = r_ab_norm_sum_4 * r_ab_norm_sum_4 - sb_sq[j + 4]; - float two_b_sq_5 = r_ab_norm_sum_5 * r_ab_norm_sum_5 - sb_sq[j + 5]; - float two_b_sq_6 = r_ab_norm_sum_6 * r_ab_norm_sum_6 - sb_sq[j + 6]; - float two_b_sq_7 = r_ab_norm_sum_7 * r_ab_norm_sum_7 - sb_sq[j + 7]; - - two_b_sq_0 = two_b_sq_0 > EPS_SQ ? two_b_sq_0 : EPS_SQ; - two_b_sq_1 = two_b_sq_1 > EPS_SQ ? two_b_sq_1 : EPS_SQ; - two_b_sq_2 = two_b_sq_2 > EPS_SQ ? two_b_sq_2 : EPS_SQ; - two_b_sq_3 = two_b_sq_3 > EPS_SQ ? two_b_sq_3 : EPS_SQ; - two_b_sq_4 = two_b_sq_4 > EPS_SQ ? two_b_sq_4 : EPS_SQ; - two_b_sq_5 = two_b_sq_5 > EPS_SQ ? two_b_sq_5 : EPS_SQ; - two_b_sq_6 = two_b_sq_6 > EPS_SQ ? two_b_sq_6 : EPS_SQ; - two_b_sq_7 = two_b_sq_7 > EPS_SQ ? two_b_sq_7 : EPS_SQ; - - float two_b_0 = sqrt(two_b_sq_0); - float two_b_1 = sqrt(two_b_sq_1); - float two_b_2 = sqrt(two_b_sq_2); - float two_b_3 = sqrt(two_b_sq_3); - float two_b_4 = sqrt(two_b_sq_4); - float two_b_5 = sqrt(two_b_sq_5); - float two_b_6 = sqrt(two_b_sq_6); - float two_b_7 = sqrt(two_b_sq_7); - - float scalar_mult_common_0 = (r_ab_norm_sum_0 / (two_b_0 * r_ab_norm_0 * r_ab2_norm_0)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_0 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_1 = (r_ab_norm_sum_1 / (two_b_1 * r_ab_norm_1 * r_ab2_norm_1)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_1 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_2 = (r_ab_norm_sum_2 / (two_b_2 * r_ab_norm_2 * r_ab2_norm_2)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_2 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_3 = (r_ab_norm_sum_3 / (two_b_3 * r_ab_norm_3 * r_ab2_norm_3)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_3 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_4 = (r_ab_norm_sum_4 / (two_b_4 * r_ab_norm_4 * r_ab2_norm_4)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_4 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_5 = (r_ab_norm_sum_5 / (two_b_5 * r_ab_norm_5 * r_ab2_norm_5)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_5 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_6 = (r_ab_norm_sum_6 / (two_b_6 * r_ab_norm_6 * r_ab2_norm_6)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_6 * NEG_TWO_SIGMA_INV)); - float scalar_mult_common_7 = (r_ab_norm_sum_7 / (two_b_7 * r_ab_norm_7 * r_ab2_norm_7)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_7 * NEG_TWO_SIGMA_INV)); - - float scalar_mult_r_ab_0 = scalar_mult_common_0 * r_ab2_norm_0; - float scalar_mult_r_ab_1 = scalar_mult_common_1 * r_ab2_norm_1; - float scalar_mult_r_ab_2 = scalar_mult_common_2 * r_ab2_norm_2; - float scalar_mult_r_ab_3 = scalar_mult_common_3 * r_ab2_norm_3; - float scalar_mult_r_ab_4 = scalar_mult_common_4 * r_ab2_norm_4; - float scalar_mult_r_ab_5 = scalar_mult_common_5 * r_ab2_norm_5; - float scalar_mult_r_ab_6 = scalar_mult_common_6 * r_ab2_norm_6; - float scalar_mult_r_ab_7 = scalar_mult_common_7 * r_ab2_norm_7; - - float scalar_mult_r_ab2_0 = scalar_mult_common_0 * r_ab_norm_0; - float scalar_mult_r_ab2_1 = scalar_mult_common_1 * r_ab_norm_1; - float scalar_mult_r_ab2_2 = scalar_mult_common_2 * r_ab_norm_2; - float scalar_mult_r_ab2_3 = scalar_mult_common_3 * r_ab_norm_3; - float scalar_mult_r_ab2_4 = scalar_mult_common_4 * r_ab_norm_4; - float scalar_mult_r_ab2_5 = scalar_mult_common_5 * r_ab_norm_5; - float scalar_mult_r_ab2_6 = scalar_mult_common_6 * r_ab_norm_6; - float scalar_mult_r_ab2_7 = scalar_mult_common_7 * r_ab_norm_7; - - float f_alpha_beta_neg_x_0 = r_ab_x_0 * scalar_mult_r_ab_0 + r_ab2_x_0 * scalar_mult_r_ab2_0; - float f_alpha_beta_neg_x_1 = r_ab_x_1 * scalar_mult_r_ab_1 + r_ab2_x_1 * scalar_mult_r_ab2_1; - float f_alpha_beta_neg_x_2 = r_ab_x_2 * scalar_mult_r_ab_2 + r_ab2_x_2 * scalar_mult_r_ab2_2; - float f_alpha_beta_neg_x_3 = r_ab_x_3 * scalar_mult_r_ab_3 + r_ab2_x_3 * scalar_mult_r_ab2_3; - float f_alpha_beta_neg_x_4 = r_ab_x_4 * scalar_mult_r_ab_4 + r_ab2_x_4 * scalar_mult_r_ab2_4; - float f_alpha_beta_neg_x_5 = r_ab_x_5 * scalar_mult_r_ab_5 + r_ab2_x_5 * scalar_mult_r_ab2_5; - float f_alpha_beta_neg_x_6 = r_ab_x_6 * scalar_mult_r_ab_6 + r_ab2_x_6 * scalar_mult_r_ab2_6; - float f_alpha_beta_neg_x_7 = r_ab_x_7 * scalar_mult_r_ab_7 + r_ab2_x_7 * scalar_mult_r_ab2_7; - - float f_alpha_beta_neg_y_0 = r_ab_y_0 * scalar_mult_r_ab_0 + r_ab2_y_0 * scalar_mult_r_ab2_0; - float f_alpha_beta_neg_y_1 = r_ab_y_1 * scalar_mult_r_ab_1 + r_ab2_y_1 * scalar_mult_r_ab2_1; - float f_alpha_beta_neg_y_2 = r_ab_y_2 * scalar_mult_r_ab_2 + r_ab2_y_2 * scalar_mult_r_ab2_2; - float f_alpha_beta_neg_y_3 = r_ab_y_3 * scalar_mult_r_ab_3 + r_ab2_y_3 * scalar_mult_r_ab2_3; - float f_alpha_beta_neg_y_4 = r_ab_y_4 * scalar_mult_r_ab_4 + r_ab2_y_4 * scalar_mult_r_ab2_4; - float f_alpha_beta_neg_y_5 = r_ab_y_5 * scalar_mult_r_ab_5 + r_ab2_y_5 * scalar_mult_r_ab2_5; - float f_alpha_beta_neg_y_6 = r_ab_y_6 * scalar_mult_r_ab_6 + r_ab2_y_6 * scalar_mult_r_ab2_6; - float f_alpha_beta_neg_y_7 = r_ab_y_7 * scalar_mult_r_ab_7 + r_ab2_y_7 * scalar_mult_r_ab2_7; - - float w_val_0, w_val_1, w_val_2, w_val_3, w_val_4, w_val_5, w_val_6, w_val_7; - - float f_norm_sq_0 = f_alpha_beta_neg_x_0 * f_alpha_beta_neg_x_0 + f_alpha_beta_neg_y_0 * f_alpha_beta_neg_y_0; - float f_norm_sq_1 = f_alpha_beta_neg_x_1 * f_alpha_beta_neg_x_1 + f_alpha_beta_neg_y_1 * f_alpha_beta_neg_y_1; - float f_norm_sq_2 = f_alpha_beta_neg_x_2 * f_alpha_beta_neg_x_2 + f_alpha_beta_neg_y_2 * f_alpha_beta_neg_y_2; - float f_norm_sq_3 = f_alpha_beta_neg_x_3 * f_alpha_beta_neg_x_3 + f_alpha_beta_neg_y_3 * f_alpha_beta_neg_y_3; - float f_norm_sq_4 = f_alpha_beta_neg_x_4 * f_alpha_beta_neg_x_4 + f_alpha_beta_neg_y_4 * f_alpha_beta_neg_y_4; - float f_norm_sq_5 = f_alpha_beta_neg_x_5 * f_alpha_beta_neg_x_5 + f_alpha_beta_neg_y_5 * f_alpha_beta_neg_y_5; - float f_norm_sq_6 = f_alpha_beta_neg_x_6 * f_alpha_beta_neg_x_6 + f_alpha_beta_neg_y_6 * f_alpha_beta_neg_y_6; - float f_norm_sq_7 = f_alpha_beta_neg_x_7 * f_alpha_beta_neg_x_7 + f_alpha_beta_neg_y_7 * f_alpha_beta_neg_y_7; - - float rhs_0 = f_norm_sq_0 * cos_phi_sq; - float rhs_1 = f_norm_sq_1 * cos_phi_sq; - float rhs_2 = f_norm_sq_2 * cos_phi_sq; - float rhs_3 = f_norm_sq_3 * cos_phi_sq; - float rhs_4 = f_norm_sq_4 * cos_phi_sq; - float rhs_5 = f_norm_sq_5 * cos_phi_sq; - float rhs_6 = f_norm_sq_6 * cos_phi_sq; - float rhs_7 = f_norm_sq_7 * cos_phi_sq; - - float e_dot_f_0 = e_x_i * f_alpha_beta_neg_x_0 + e_y_i * f_alpha_beta_neg_y_0; - float e_dot_f_1 = e_x_i * f_alpha_beta_neg_x_1 + e_y_i * f_alpha_beta_neg_y_1; - float e_dot_f_2 = e_x_i * f_alpha_beta_neg_x_2 + e_y_i * f_alpha_beta_neg_y_2; - float e_dot_f_3 = e_x_i * f_alpha_beta_neg_x_3 + e_y_i * f_alpha_beta_neg_y_3; - float e_dot_f_4 = e_x_i * f_alpha_beta_neg_x_4 + e_y_i * f_alpha_beta_neg_y_4; - float e_dot_f_5 = e_x_i * f_alpha_beta_neg_x_5 + e_y_i * f_alpha_beta_neg_y_5; - float e_dot_f_6 = e_x_i * f_alpha_beta_neg_x_6 + e_y_i * f_alpha_beta_neg_y_6; - float e_dot_f_7 = e_x_i * f_alpha_beta_neg_x_7 + e_y_i * f_alpha_beta_neg_y_7; - - float e_dot_f_sq_0 = e_dot_f_0 * e_dot_f_0; - float e_dot_f_sq_1 = e_dot_f_1 * e_dot_f_1; - float e_dot_f_sq_2 = e_dot_f_2 * e_dot_f_2; - float e_dot_f_sq_3 = e_dot_f_3 * e_dot_f_3; - float e_dot_f_sq_4 = e_dot_f_4 * e_dot_f_4; - float e_dot_f_sq_5 = e_dot_f_5 * e_dot_f_5; - float e_dot_f_sq_6 = e_dot_f_6 * e_dot_f_6; - float e_dot_f_sq_7 = e_dot_f_7 * e_dot_f_7; - - if (e_dot_f_0 >= 0.0 || e_dot_f_sq_0 <= rhs_0) - w_val_0 = dt_neg; - else - w_val_0 = c_neg_times_dt; - if (e_dot_f_1 >= 0.0 || e_dot_f_sq_1 <= rhs_1) - w_val_1 = dt_neg; - else - w_val_1 = c_neg_times_dt; - if (e_dot_f_2 >= 0.0 || e_dot_f_sq_2 <= rhs_2) - w_val_2 = dt_neg; - else - w_val_2 = c_neg_times_dt; - if (e_dot_f_3 >= 0.0 || e_dot_f_sq_3 <= rhs_3) - w_val_3 = dt_neg; - else - w_val_3 = c_neg_times_dt; - if (e_dot_f_4 >= 0.0 || e_dot_f_sq_4 <= rhs_4) - w_val_4 = dt_neg; - else - w_val_4 = c_neg_times_dt; - if (e_dot_f_5 >= 0.0 || e_dot_f_sq_5 <= rhs_5) - w_val_5 = dt_neg; - else - w_val_5 = c_neg_times_dt; - if (e_dot_f_6 >= 0.0 || e_dot_f_sq_6 <= rhs_6) - w_val_6 = dt_neg; - else - w_val_6 = c_neg_times_dt; - if (e_dot_f_7 >= 0.0 || e_dot_f_sq_7 <= rhs_7) - w_val_7 = dt_neg; - else - w_val_7 = c_neg_times_dt; - - acc_x_0 += f_alpha_beta_neg_x_0 * w_val_0; - acc_x_1 += f_alpha_beta_neg_x_1 * w_val_1; - acc_x_2 += f_alpha_beta_neg_x_2 * w_val_2; - acc_x_3 += f_alpha_beta_neg_x_3 * w_val_3; - acc_x_4 += f_alpha_beta_neg_x_4 * w_val_4; - acc_x_5 += f_alpha_beta_neg_x_5 * w_val_5; - acc_x_6 += f_alpha_beta_neg_x_6 * w_val_6; - acc_x_7 += f_alpha_beta_neg_x_7 * w_val_7; - acc_y_0 += f_alpha_beta_neg_y_0 * w_val_0; - acc_y_1 += f_alpha_beta_neg_y_1 * w_val_1; - acc_y_2 += f_alpha_beta_neg_y_2 * w_val_2; - acc_y_3 += f_alpha_beta_neg_y_3 * w_val_3; - acc_y_4 += f_alpha_beta_neg_y_4 * w_val_4; - acc_y_5 += f_alpha_beta_neg_y_5 * w_val_5; - acc_y_6 += f_alpha_beta_neg_y_6 * w_val_6; - acc_y_7 += f_alpha_beta_neg_y_7 * w_val_7; - } - - // remainder of the j > i half, single lane. # one j = 66 FLOPS - for (; j < n_p; j++) { - float r_ab_x = r_ab_x_lut[i * n_p + j]; - float r_ab_y = r_ab_y_lut[i * n_p + j]; - float r_ab_norm = r_ab_norm_lut[i * n_p + j]; - - r_ab_norm = r_ab_norm > EPS ? r_ab_norm : EPS; - - // # 1 ADD - float r_ab2_x = r_ab_x - sb_e_x[j]; - // # 1 ADD - float r_ab2_y = r_ab_y - sb_e_y[j]; - - // # 1 ADD, 2 MULTs, 1 SQRT - float r_ab2_norm = sqrt(r_ab2_x * r_ab2_x + r_ab2_y * r_ab2_y); - r_ab2_norm = r_ab2_norm > EPS ? r_ab2_norm : EPS; - - // # 1 ADD - float r_ab_norm_sum = r_ab_norm + r_ab2_norm; - - // # 1 ADD, 1 MULT - float two_b_sq = r_ab_norm_sum * r_ab_norm_sum - sb_sq[j]; - two_b_sq = two_b_sq > EPS_SQ ? two_b_sq : EPS_SQ; - // # 1 SQRT - float two_b = sqrt(two_b_sq); - // # 5 MULTs, 1 DIV, 1 EXP - float scalar_mult_common = (r_ab_norm_sum / (two_b * r_ab_norm * r_ab2_norm)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b * NEG_TWO_SIGMA_INV)); - // # 1 MULT - float scalar_mult_r_ab = scalar_mult_common * r_ab2_norm; - // # 1 MULT - float scalar_mult_r_ab2 = scalar_mult_common * r_ab_norm; - - // # 1 ADD, 2 MULTs - float f_alpha_beta_neg_x = r_ab_x * scalar_mult_r_ab + r_ab2_x * scalar_mult_r_ab2; - // # 1 ADD, 2 MULTs - float f_alpha_beta_neg_y = r_ab_y * scalar_mult_r_ab + r_ab2_y * scalar_mult_r_ab2; - - float w_val; - - // # 1 ADD, 2 MULTs - float f_norm_sq = f_alpha_beta_neg_x * f_alpha_beta_neg_x + f_alpha_beta_neg_y * f_alpha_beta_neg_y; - // # 1 MULT - float rhs = f_norm_sq * cos_phi_sq; - // # 1 ADD, 2 MULTs - float e_dot_f = e_x[i] * f_alpha_beta_neg_x + e_y[i] * f_alpha_beta_neg_y; - // # 1 MULT - float e_dot_f_sq = e_dot_f * e_dot_f; - if (e_dot_f >= 0.0 || e_dot_f_sq <= rhs) - w_val = dt_neg; - else - w_val = c_neg_times_dt; - - // # 1 ADD, 1 MULT - f_alpha_dt_x += f_alpha_beta_neg_x * w_val; - // # 1 ADD, 1 MULT - f_alpha_dt_y += f_alpha_beta_neg_y * w_val; - } - - // reduction of the j > i accumulators. # K adds per line (K=8) => 16 ADDs - f_alpha_dt_x += acc_x_0 + acc_x_1 + acc_x_2 + acc_x_3 + acc_x_4 + acc_x_5 + acc_x_6 + acc_x_7; - f_alpha_dt_y += acc_y_0 + acc_y_1 + acc_y_2 + acc_y_3 + acc_y_4 + acc_y_5 + acc_y_6 + acc_y_7; - - // force between pedestrian and obstacles - // # one obstacle = 55 FLOPS (w_val sign-based, no a*a / b_sq) - for (int k = 0; k < board.n_obstacles; k++) { - // # 1 ADD - float v1_x = pos_x[i] - board.obstacles[k].start_x; - // # 1 ADD - float v1_y = pos_y[i] - board.obstacles[k].start_y; - float v2_x = board.obstacles[k].obstacle_v_x; - float v2_y = board.obstacles[k].obstacle_v_y; - - // # 1 ADD, 3 MULTs - float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; - - if (projection < 0.0) - projection = 0.0; - else if (projection > 1.0) - projection = 1.0; - - // # 2 ADDs, 1 MULT - float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); - // # 2 ADDs, 1 MULT - float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); - - // # 1 ADD, 2 MULTs, 1 SQRT - float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); - r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; - - // # 2 MULTs, 1 DIV, 1 EXP - float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; - // # 1 MULT - float f_alpha_B_neg_x = r_aB_x * scalar_mult; - // # 1 MULT - float f_alpha_B_neg_y = r_aB_y * scalar_mult; - - float w_val; - - // sign select only, no flops - float e_dot_f = (f_alpha_B_neg_y == 0) ? 0 : (f_alpha_B_neg_y < 0 ? -e_y[i] : e_y[i]); - - if (e_dot_f >= cos_phi) - w_val = dt_neg; - else - w_val = c_neg_times_dt; - - // # 1 MULT - float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; - // # 1 MULT - float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; - - // # 1 ADD - f_alpha_dt_x += f_alpha_B_dt_x; - // # 1 ADD - f_alpha_dt_y += f_alpha_B_dt_y; - } - - // # 1 ADD - w_x[i] += f_alpha_dt_x; - // # 1 ADD - w_y[i] += f_alpha_dt_y; - } - - // update each pedestrian - // # 29 FLOPS per pedestrian - for (int i = 0; i < n_p; i++) { - - // # 1 ADD, 2 MULTs, 1 SQRT - float w_norm = sqrt(w_x[i] * w_x[i] + w_y[i] * w_y[i]); - - float w_norm2 = w_norm > EPS ? w_norm : EPS; - - // # 1 DIV - float correction_factor = min(1.0f, v_max[i] / w_norm2); - - // # 1 MULT - curr_vel_x[i] = w_x[i] * correction_factor; - // # 1 MULT - curr_vel_y[i] = w_y[i] * correction_factor; - - // # 1 ADD, 1 MULT - pos_x[i] = pos_x[i] + curr_vel_x[i] * dt; - // # 1 ADD, 1 MULT - pos_y[i] = pos_y[i] + curr_vel_y[i] * dt; - - if (color[i] == 0 && pos_x[i] > (BOARD_LENGTH - 1.5)) { - pos_x[i] = 1.0; - destination_y[i] = pos_y[i]; - w_x[i] = desired_v0[i]; - w_y[i] = 0.0; - curr_vel_x[i] = w_x[i]; - curr_vel_y[i] = w_y[i]; - } - if (color[i] == 1 && pos_x[i] < 1.5) { - pos_x[i] = BOARD_LENGTH - 1.0; - destination_y[i] = pos_y[i]; - w_x[i] = -desired_v0[i]; - w_y[i] = 0.0; - curr_vel_x[i] = w_x[i]; - curr_vel_y[i] = w_y[i]; - } - - pos_y[i] = clamp(pos_y[i], WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - - // # 1 ADD - float ex = destination_x[i] - pos_x[i]; - // # 1 ADD - float ey = destination_y[i] - pos_y[i]; - - // # 1 ADD, 2 MULTs, 1 SQRT - float e_norm = sqrt(ex * ex + ey * ey); - float e_norm2 = e_norm > EPS ? e_norm : EPS; - // # 1 DIV - float e_norm_inv = 1.0 / e_norm2; - - // # 1 MULT - e_x[i] = ex * e_norm_inv; - // # 1 MULT - e_y[i] = ey * e_norm_inv; - - // # 1 ADD, 2 MULTs - float velocity_norm_sq = curr_vel_x[i] * curr_vel_x[i] + curr_vel_y[i] * curr_vel_y[i]; - - // # 1 SQRT - float velocity_norm = sqrt(velocity_norm_sq); - - // # 1 MULT - sb_sq[i] = velocity_norm_sq * delta_t_sq; - - // # 2 MULTs (velocity_norm*delta_t written on both lines, counted as is) - sb_e_x[i] = e_x[i] * (velocity_norm * delta_t); - // # 2 MULTs - sb_e_y[i] = e_y[i] * (velocity_norm * delta_t); - -#if !BENCHMARK - if (dump_path && (t % dump_interval == 0)) { - samples.emplace_back(t + 1, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } -#endif - } - } - -#if !BENCHMARK - if (dump_path) { - ofstream out(dump_path); - out << "time,id,x,y,p.e.x,p.e.y,color\n"; - - for (auto &[t, id, x, y, e_x, e_y, c] : samples) { - out << t << ',' << id << ',' << x << ',' << y << ',' << e_x << ',' << e_y << ',' << c << '\n'; - } - } -#endif - - return 0; -} diff --git a/variants/variant_float_inlining_SoA_symmetry_flopcount.cpp b/variants/variant_float_inlining_SoA_symmetry_flopcount.cpp deleted file mode 100644 index c50f977..0000000 --- a/variants/variant_float_inlining_SoA_symmetry_flopcount.cpp +++ /dev/null @@ -1,489 +0,0 @@ -// # Changes: SoA layout for pedestrians (file-scope arrays instead of struct fields) -// # added flopcount -// FLOPCOUNT = n_iter * ( 69 * n_p ** 2 - 32 * n_p + 55 * n_obstacles * n_p ) -// # Predecessor: variant_float_inlining.cpp - -#include "../headers/board_reduced_float.hpp" -#include "../headers/constants_float.hpp" -#include "../headers/pedestrian_reduced_float.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - -#define SEED 42 -#define BOARD_WIDTH 10.0f -#define BOARD_LENGTH 50.0f -#define WALL_EPS 1e-3f -#define BOARD_WIDTH_MINUS_WALL_EPS 9.999f - -#ifndef RANDOM_SEED -#define RANDOM_SEED 0 -#endif - -#ifndef BENCHMARK -#define BENCHMARK 0 -#endif - -using namespace std; - -// we wanna use arrays so we can implement SoA, one array per pedestrian field -vector pos_x, pos_y; -vector sb_sq; -vector sb_e_x, sb_e_y; -vector e_x, e_y; -vector curr_vel_x, curr_vel_y; -vector w_x, w_y; -vector desired_v0; -vector v_max; -vector destination_x, destination_y; -vector color; - -Pedestrian *init_pedestrians(int n_p) { -#if RANDOM_SEED - random_device rd; - mt19937 gen(rd()); -#else - mt19937 gen(SEED); -#endif - - normal_distribution velocity_gen(v0_mean, v0_std_dev); - uniform_real_distribution y_gen(0.3, BOARD_WIDTH - 0.3); - uniform_real_distribution x_gen_left(2.0, BOARD_LENGTH / 2.0); - uniform_real_distribution x_gen_right(BOARD_LENGTH / 2.0, BOARD_LENGTH - 2.0); - - // resize all arrays for this run - pos_x.resize(n_p); - pos_y.resize(n_p); - sb_sq.resize(n_p); - sb_e_x.resize(n_p); - sb_e_y.resize(n_p); - e_x.resize(n_p); - e_y.resize(n_p); - curr_vel_x.resize(n_p); - curr_vel_y.resize(n_p); - w_x.resize(n_p); - w_y.resize(n_p); - desired_v0.resize(n_p); - v_max.resize(n_p); - destination_x.resize(n_p); - destination_y.resize(n_p); - color.resize(n_p); - - int n_p_half = n_p / 2; - - for (int i = 0; i < n_p_half; i++) { - float x = x_gen_left(gen); - float y = y_gen(gen); - - float dest_x = BOARD_LENGTH + 30.0; // renamed to avoid shadowing destination_x[] - float dest_y = y; - - float init_e_x = dest_x - x; - float init_e_y = dest_y - y; - float init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - float init_e_unit_x = init_e_x / init_e_norm; - float init_e_unit_y = init_e_y / init_e_norm; - - float d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1); - - float v_m = 1.3 * d_v0; - - color[i] = 0; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - // Fields the Pedestrian constructor would have zero-initialized (c_v_x=c_v_y=0): - w_x[i] = 0.0f; - w_y[i] = 0.0f; - curr_vel_x[i] = 0.0f; - curr_vel_y[i] = 0.0f; - sb_sq[i] = 0.0f; - sb_e_x[i] = 0.0f; - sb_e_y[i] = 0.0f; - } - - for (int i = n_p_half; i < n_p; i++) { - float x = x_gen_right(gen); - float y = y_gen(gen); - - float dest_x = -30; - float dest_y = y; - - float init_e_x = dest_x - x; - float init_e_y = dest_y - y; - float init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - float init_e_unit_x = init_e_x / init_e_norm; - float init_e_unit_y = init_e_y / init_e_norm; - - float d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1); - - float v_m = 1.3 * d_v0; - - color[i] = 1; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - w_x[i] = 0.0f; - w_y[i] = 0.0f; - curr_vel_x[i] = 0.0f; - curr_vel_y[i] = 0.0f; - sb_sq[i] = 0.0f; - sb_e_x[i] = 0.0f; - sb_e_y[i] = 0.0f; - } - - return nullptr; -} - -Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } - -int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { - (void)pedestrians; -#if BENCHMARK - (void)dump_path; -#endif - -#if !BENCHMARK - const int dump_interval = 1; - - vector> samples; - - if (dump_path) { - samples.reserve(static_cast(n_iter / dump_interval + 1) * n_p); - - for (int i = 0; i < n_p; i++) { - samples.emplace_back(0, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } - } -#endif - - // here we have real (simple) symmetry - std::vector r_ab_x_lut(n_p * n_p, 0.0); - std::vector r_ab_y_lut(n_p * n_p, 0.0); - std::vector r_ab_norm_lut(n_p * n_p, 0.0); - // use NAME[i * n_p + j] - - // FLOPCOUNT (everything inside the t-loop). EXP kept as its own op (one real exp() per call). - // section costs: overhead 4 ADD 4 MULT | distance pair 3 ADD 2 MULT 1 SQRT | - // ped-ped j 11 ADD 22 MULT 2 SQRT 1 DIV 1 EXP | - // obstacle 10 ADD 13 MULT 1 SQRT 1 DIV 1 EXP | update 7 ADD 17 MULT 3 SQRT 2 DIV - - // # ADDs: n_iter * ( - // # n_p * 4 + - // # 0.5 * (n_p*n_p - n_p) * 3 + - // # n_p * (n_p - 1) * 11 + - // # n_p * board.n_obstacles * 10 + - // # n_p * 7 - // # ) - - // # MULTs: n_iter * ( - // # n_p * 4 + - // # 0.5 * (n_p*n_p - n_p) * 2 + - // # n_p * (n_p - 1) * 22 + - // # n_p * board.n_obstacles * 13 + - // # n_p * 17 - // # ) - - // # DIVs: n_iter * ( - // # n_p * (n_p - 1) + - // # n_p * board.n_obstacles + - // # n_p * 2 - // # ) - - // # SQRTs: n_iter * ( - // # 0.5 * (n_p*n_p - n_p) + - // # n_p * (n_p - 1) * 2 + - // # n_p * board.n_obstacles + - // # n_p * 3 - // # ) - - // # EXPs: n_iter * ( - // # n_p * (n_p - 1) + - // # n_p * board.n_obstacles - // # ) - - // total with EXP = 30: n_iter * ( 69 * n_p ** 2 - 32 * n_p + 55 * n_obstacles * n_p ) - for (int t = 0; t < n_iter; t++) { - for (int i = 0; i < n_p; i++) { - - // # 1 MULT - float desired_velocity_x = e_x[i] * desired_v0[i]; - // # 1 MULT - float desired_velocity_y = e_y[i] * desired_v0[i]; - // # 1 ADD, 1 MULT - float f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; - // # 1 ADD, 1 MULT - float f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; - - // lut for distances - // get all distances first - // # each pair: 6 FLOPS, total over all i = 0.5*(n_p*n_p - n_p) * 6 - for (int j = i + 1; j < n_p; j++) { - // # 1 ADD - float dx = pos_x[i] - pos_x[j]; - // # 1 ADD - float dy = pos_y[i] - pos_y[j]; - // # 1 ADD, 2 MULTs, 1 SQRT - float norm = sqrt(dx * dx + dy * dy); - int idx = i * n_p + j; - r_ab_x_lut[idx] = dx; - r_ab_y_lut[idx] = dy; - r_ab_norm_lut[idx] = norm; - } - - - // force between pedestrians - // # one j (the i==j case is skipped) = 66 FLOPS, runs (n_p-1) times per i - for (int j = 0; j < n_p; j++) { - if (i == j) continue; - - // symmetry: lut lookup is for free, the -1* sign flip is not counted - float r_ab_x, r_ab_y, r_ab_norm; - if (i < j) { - r_ab_x = r_ab_x_lut[i * n_p + j]; - r_ab_y = r_ab_y_lut[i * n_p + j]; - r_ab_norm = r_ab_norm_lut[i * n_p + j]; - } else { - // other direction - r_ab_x = -1 * r_ab_x_lut[j * n_p + i]; - r_ab_y = -1 * r_ab_y_lut[j * n_p + i]; - r_ab_norm = r_ab_norm_lut[j * n_p + i]; - } - - - - - //float r_ab_x = pos_x[i] - pos_x[j]; - //float r_ab_y = pos_y[i] - pos_y[j]; - - //float r_ab_norm = sqrt(r_ab_x * r_ab_x + r_ab_y * r_ab_y); - r_ab_norm = r_ab_norm > EPS ? r_ab_norm : EPS; - - // # 1 ADD - float r_ab2_x = r_ab_x - sb_e_x[j]; - // # 1 ADD - float r_ab2_y = r_ab_y - sb_e_y[j]; - - // # 1 ADD, 2 MULTs, 1 SQRT - float r_ab2_norm = sqrt(r_ab2_x * r_ab2_x + r_ab2_y * r_ab2_y); - r_ab2_norm = r_ab2_norm > EPS ? r_ab2_norm : EPS; - - // # 1 ADD - float r_ab_norm_sum = r_ab_norm + r_ab2_norm; - - // # 1 ADD, 1 MULT - float two_b_sq = r_ab_norm_sum * r_ab_norm_sum - sb_sq[j]; - two_b_sq = two_b_sq > EPS_SQ ? two_b_sq : EPS_SQ; - // # 1 SQRT - float two_b = sqrt(two_b_sq); - // # 5 MULTs, 1 DIV, 1 EXP - float scalar_mult_common = (r_ab_norm_sum / (two_b * r_ab_norm * r_ab2_norm)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b * NEG_TWO_SIGMA_INV)); - // # 1 MULT - float scalar_mult_r_ab = scalar_mult_common * r_ab2_norm; - // # 1 MULT - float scalar_mult_r_ab2 = scalar_mult_common * r_ab_norm; - - // # 1 ADD, 2 MULTs - float f_alpha_beta_neg_x = r_ab_x * scalar_mult_r_ab + r_ab2_x * scalar_mult_r_ab2; - // # 1 ADD, 2 MULTs - float f_alpha_beta_neg_y = r_ab_y * scalar_mult_r_ab + r_ab2_y * scalar_mult_r_ab2; - - float w_val; - - // # 1 ADD, 2 MULTs - float f_norm_sq = f_alpha_beta_neg_x * f_alpha_beta_neg_x + f_alpha_beta_neg_y * f_alpha_beta_neg_y; - // # 1 MULT - float rhs = f_norm_sq * cos_phi_sq; - // # 1 ADD, 2 MULTs - float e_dot_f = e_x[i] * f_alpha_beta_neg_x + e_y[i] * f_alpha_beta_neg_y; - // # 1 MULT - float e_dot_f_sq = e_dot_f * e_dot_f; - if (e_dot_f >= 0.0 || e_dot_f_sq <= rhs) - w_val = dt_neg; - else - w_val = c_neg_times_dt; - - // # 1 ADD, 1 MULT - f_alpha_dt_x = f_alpha_dt_x + f_alpha_beta_neg_x * w_val; - // # 1 ADD, 1 MULT - f_alpha_dt_y = f_alpha_dt_y + f_alpha_beta_neg_y * w_val; - } - - // force between pedestrian and obstacles - // # one obstacle = 55 FLOPS (w_val here is sign-based, no a*a / b_sq) - for (int k = 0; k < board.n_obstacles; k++) { - - // # 1 ADD - float v1_x = pos_x[i] - board.obstacles[k].start_x; - // # 1 ADD - float v1_y = pos_y[i] - board.obstacles[k].start_y; - float v2_x = board.obstacles[k].obstacle_v_x; - float v2_y = board.obstacles[k].obstacle_v_y; - - // # 1 ADD, 3 MULTs - float projection = (v1_x * v2_x + v1_y * v2_y) * board.obstacles[k].length_sq_inv; - - if (projection < 0.0) - projection = 0.0; - else if (projection > 1.0) - projection = 1.0; - - // # 2 ADDs, 1 MULT - float r_aB_x = pos_x[i] - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); - // # 2 ADDs, 1 MULT - float r_aB_y = pos_y[i] - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); - - // # 1 ADD, 2 MULTs, 1 SQRT - float r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); - r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; - - // # 2 MULTs, 1 DIV, 1 EXP - float scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; - // # 1 MULT - float f_alpha_B_neg_x = r_aB_x * scalar_mult; - // # 1 MULT - float f_alpha_B_neg_y = r_aB_y * scalar_mult; - - float w_val; - - // sign select only, no flops - float e_dot_f = (f_alpha_B_neg_y == 0) ? 0 : (f_alpha_B_neg_y < 0 ? -e_y[i] : e_y[i]); - - if (e_dot_f >= cos_phi) - w_val = dt_neg; - else - w_val = c_neg_times_dt; - - // # 1 MULT - float f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; - // # 1 MULT - float f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; - - // # 1 ADD - f_alpha_dt_x += f_alpha_B_dt_x; - // # 1 ADD - f_alpha_dt_y += f_alpha_B_dt_y; - } - - // # 1 ADD - w_x[i] += f_alpha_dt_x; - // # 1 ADD - w_y[i] += f_alpha_dt_y; - } - - // update each pedestrian - // # 29 FLOPS per pedestrian - for (int i = 0; i < n_p; i++) { - - // # 1 ADD, 2 MULTs, 1 SQRT - float w_norm = sqrt(w_x[i] * w_x[i] + w_y[i] * w_y[i]); - - float w_norm2 = w_norm > EPS ? w_norm : EPS; - - // # 1 DIV - float correction_factor = min(1.0f, v_max[i] / w_norm2); - - // # 1 MULT - curr_vel_x[i] = w_x[i] * correction_factor; - // # 1 MULT - curr_vel_y[i] = w_y[i] * correction_factor; - - // # 1 ADD, 1 MULT - pos_x[i] = pos_x[i] + curr_vel_x[i] * dt; - // # 1 ADD, 1 MULT - pos_y[i] = pos_y[i] + curr_vel_y[i] * dt; - - if (color[i] == 0 && pos_x[i] > (BOARD_LENGTH - 1.5)) { - pos_x[i] = 1.0; - destination_y[i] = pos_y[i]; - w_x[i] = desired_v0[i]; - w_y[i] = 0.0; - curr_vel_x[i] = w_x[i]; - curr_vel_y[i] = w_y[i]; - } - if (color[i] == 1 && pos_x[i] < 1.5) { - pos_x[i] = BOARD_LENGTH - 1.0; - destination_y[i] = pos_y[i]; - w_x[i] = -desired_v0[i]; - w_y[i] = 0.0; - curr_vel_x[i] = w_x[i]; - curr_vel_y[i] = w_y[i]; - } - - pos_y[i] = clamp(pos_y[i], WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - - // # 1 ADD - float ex = destination_x[i] - pos_x[i]; - // # 1 ADD - float ey = destination_y[i] - pos_y[i]; - - // # 1 ADD, 2 MULTs, 1 SQRT - float e_norm = sqrt(ex * ex + ey * ey); - float e_norm2 = e_norm > EPS ? e_norm : EPS; - // # 1 DIV - float e_norm_inv = 1.0 / e_norm2; - - // # 1 MULT - e_x[i] = ex * e_norm_inv; - // # 1 MULT - e_y[i] = ey * e_norm_inv; - - // # 1 ADD, 2 MULTs - float velocity_norm_sq = curr_vel_x[i] * curr_vel_x[i] + curr_vel_y[i] * curr_vel_y[i]; - - // # 1 SQRT - float velocity_norm = sqrt(velocity_norm_sq); - - // # 1 MULT - sb_sq[i] = velocity_norm_sq * delta_t_sq; - - // # 2 MULTs (velocity_norm*delta_t written on both lines, counted as is) - sb_e_x[i] = e_x[i] * (velocity_norm * delta_t); - // # 2 MULTs - sb_e_y[i] = e_y[i] * (velocity_norm * delta_t); - -#if !BENCHMARK - if (dump_path && (t % dump_interval == 0)) { - samples.emplace_back(t + 1, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } -#endif - } - } - -#if !BENCHMARK - if (dump_path) { - ofstream out(dump_path); - out << "time,id,x,y,p.e.x,p.e.y,color\n"; - - for (auto &[t, id, x, y, e_x, e_y, c] : samples) { - out << t << ',' << id << ',' << x << ',' << y << ',' << e_x << ',' << e_y << ',' << c << '\n'; - } - } -#endif - - return 0; -} diff --git a/variants/variant_inlining_7_SoA_AVX2_flopcount.cpp b/variants/variant_inlining_7_SoA_AVX2_flopcount.cpp deleted file mode 100644 index 1445034..0000000 --- a/variants/variant_inlining_7_SoA_AVX2_flopcount.cpp +++ /dev/null @@ -1,458 +0,0 @@ -// # This file uses avx2 -// # This is the first variant and should serve as a base for further avx2 optimizations - -// Okay our first step is to use a SoA instead of an AoS -// We only do SoA for the pedestrian struct, there we wanna optimize such that we access for the ped-ped forces adjacent pedestrians (in the arrays) -// Now in a second step we wanna really use AVX2 for the mainloop (where we wana optimize the most innerloop first) - -#include "../headers/board.hpp" -#include "../headers/constants.hpp" -#include "../headers/pedestrian_reduced.hpp" - -#include // to use avx2 - -#include -#include -#include -#include -#include -#include -#include -#include - -#define SEED 42 -#define BOARD_WIDTH 10.0 -#define BOARD_LENGTH 50.0 -#define WALL_EPS 1e-3 -#define BOARD_WIDTH_MINUS_WALL_EPS 9.999 - -#ifndef RANDOM_SEED -#define RANDOM_SEED 0 -#endif - -#ifndef BENCHMARK -#define BENCHMARK 0 -#endif - -using namespace std; - -// we wanna use arrays so we can implement SOA, we create arrays for all the data we need and access -vector pos_x, pos_y; -vector sb_sq; -vector sb_e_x, sb_e_y; -vector e_x, e_y; -vector curr_vel_x, curr_vel_y; -vector w_x, w_y; -vector desired_v0; -vector v_max; -vector destination_x, destination_y; -vector color; - -Pedestrian *init_pedestrians(int n_p) { - -#if RANDOM_SEED - random_device rd; - mt19937 gen(rd()); -#else - mt19937 gen(SEED); -#endif - - normal_distribution velocity_gen(v0_mean, v0_std_dev); - uniform_real_distribution y_gen(0.3, BOARD_WIDTH - 0.3); - uniform_real_distribution x_gen_left(2.0, BOARD_LENGTH / 2.0); - uniform_real_distribution x_gen_right(BOARD_LENGTH / 2.0, BOARD_LENGTH - 2.0); - - const int n_p_pad = (n_p + 3) & ~3; // round up to a multiple of 4 (so its easy to use avx) - - // resize all our arrays for this run - pos_x.resize(n_p_pad); - pos_y.resize(n_p_pad); - sb_sq.resize(n_p_pad); - sb_e_x.resize(n_p_pad); - sb_e_y.resize(n_p_pad); - e_x.resize(n_p_pad); - e_y.resize(n_p_pad); - curr_vel_x.resize(n_p_pad); - curr_vel_y.resize(n_p_pad); - w_x.resize(n_p_pad); - w_y.resize(n_p_pad); - desired_v0.resize(n_p_pad); - v_max.resize(n_p_pad); - destination_x.resize(n_p_pad); - destination_y.resize(n_p_pad); - color.resize(n_p_pad); - - int n_p_half = n_p / 2; - - for (int i = 0; i < n_p_half; i++) { - double x = x_gen_left(gen); - double y = y_gen(gen); - - double dest_x = BOARD_LENGTH + 30.0; // renamed to avoid shadowing destination_x[] - double dest_y = y; // same idea for destination_y[] - - double init_e_x = dest_x - x; - double init_e_y = dest_y - y; - double init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - double init_e_unit_x = init_e_x / init_e_norm; - double init_e_unit_y = init_e_y / init_e_norm; - - double d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1); - - double v_m = 1.3 * d_v0; - - color[i] = 0; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - // Fields the Pedestrian constructor would have zero-initialized: - w_x[i] = 0.0; - w_y[i] = 0.0; - curr_vel_x[i] = 0.0; - curr_vel_y[i] = 0.0; - sb_sq[i] = 0.0; - sb_e_x[i] = 0.0; - sb_e_y[i] = 0.0; - } - - for (int i = n_p_half; i < n_p; i++) { - double x = x_gen_right(gen); - double y = y_gen(gen); - - double dest_x = -30; - double dest_y = y; - - double init_e_x = dest_x - x; - double init_e_y = dest_y - y; - double init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - double init_e_unit_x = init_e_x / init_e_norm; - double init_e_unit_y = init_e_y / init_e_norm; - - double d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1); - - double v_m = 1.3 * d_v0; - - color[i] = 1; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - // Fields the Pedestrian constructor would have zero-initialized: - w_x[i] = 0.0; - w_y[i] = 0.0; - curr_vel_x[i] = 0.0; - curr_vel_y[i] = 0.0; - sb_sq[i] = 0.0; - sb_e_x[i] = 0.0; - sb_e_y[i] = 0.0; - } - - // Padding lanes: positions far away, everything else zero. Any unmasked SIMD - // contribution from these lanes will vanish through exp(very negative) roughly 0. - for (int j = n_p; j < n_p_pad; j++) { - pos_x[j] = 1e9; - pos_y[j] = 1e9; - sb_sq[j] = 0.0; - sb_e_x[j] = 0.0; - sb_e_y[j] = 0.0; - } - return nullptr; -} - -Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } - -int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { - -#if BENCHMARK - (void)dump_path; -#endif - -#if !BENCHMARK - const int dump_interval = 1; - - vector> samples; - - if (dump_path) { - samples.reserve(static_cast(n_iter / dump_interval + 1) * n_p); - - for (int i = 0; i < n_p; i++) { - // Pedestrian &p = pedestrians[i]; - samples.emplace_back(0, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } - } -#endif - - // all the constants for the AVX2 setup - - const int n_p_pad = (n_p + 3) & ~3; - - alignas(32) const double lane_offset_arr[4] = {0.0, 1.0, 2.0, 3.0}; - const __m256d lane_off = _mm256_load_pd(lane_offset_arr); - - const __m256d v_neg_v0_div_2s = _mm256_set1_pd(NEG_V0_AB_div_TWO_SIGMA); - const __m256d v_neg_2s_inv = _mm256_set1_pd(NEG_TWO_SIGMA_INV); - const __m256d v_cos_phi_inv = _mm256_set1_pd(cos_phi_inv); - const __m256d v_dt_neg = _mm256_set1_pd(dt_neg); - const __m256d v_c_neg_dt = _mm256_set1_pd(c_neg_times_dt); - const __m256d v_zero = _mm256_setzero_pd(); - const __m256d v_np = _mm256_set1_pd((double)n_p); - - // # flops per iteration (one pass of the outer time loop): - // # ADDs: n_p * 12 + n_p * n_p_pad * 15 + n_p * board.n_obstacles * 12 + n_p * 7 - // # MULTs: n_p * 4 + n_p * n_p_pad * 24 + n_p * board.n_obstacles * 19 + n_p * 16 - // # DIVs: n_p * n_p_pad * 1 + n_p * board.n_obstacles + n_p * 2 - // # SQRTs: n_p * n_p_pad * 3 + n_p * board.n_obstacles + n_p * 3 - // # EXPs: n_p * n_p_pad * 1 + n_p * board.n_obstacles - for (int t = 0; t < n_iter; t++) { - - for (int i = 0; i < n_p; i++) { - - double desired_velocity_x = e_x[i] * desired_v0[i]; // # 1 MULT - double desired_velocity_y = e_y[i] * desired_v0[i]; // # 1 MULT - - double f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; // # 1 MULT, 1 ADD - double f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; // # 1 MULT, 1 ADD - - // since i is fixed for the innermost loops we now wanna set all those variables - const __m256d pix = _mm256_set1_pd(pos_x[i]); - const __m256d piy = _mm256_set1_pd(pos_y[i]); - const __m256d eix = _mm256_set1_pd(e_x[i]); - const __m256d eiy = _mm256_set1_pd(e_y[i]); - const __m256d v_i = _mm256_set1_pd((double)i); - - __m256d acc_x = _mm256_setzero_pd(); - __m256d acc_y = _mm256_setzero_pd(); - - for (int j = 0; j < n_p_pad; j += 4) { - // 4 lanes at once, lane k maps to pedestrian j+k - __m256d j_idx = _mm256_add_pd(_mm256_set1_pd((double)j), lane_off); // # 4 ADDs - - // active = (j+k != i) AND (j+k < n_p), zero in lanes we wanna skip - __m256d m_neq_i = _mm256_cmp_pd(j_idx, v_i, _CMP_NEQ_OQ); - __m256d m_in_range = _mm256_cmp_pd(j_idx, v_np, _CMP_LT_OQ); - __m256d active = _mm256_and_pd(m_neq_i, m_in_range); - - // j-side loads, SoA contiguous. loadu because std::vector only guarantees 16B align. - __m256d pjx = _mm256_loadu_pd(&pos_x[j]); - __m256d pjy = _mm256_loadu_pd(&pos_y[j]); - __m256d sbe_jx = _mm256_loadu_pd(&sb_e_x[j]); - __m256d sbe_jy = _mm256_loadu_pd(&sb_e_y[j]); - __m256d sb_jsq = _mm256_loadu_pd(&sb_sq[j]); - - // double r_ab_x = pos_x[i] - pos_x[j]; - // double r_ab_y = pos_y[i] - pos_y[j]; - // - // double r_ab_norm = sqrt(r_ab_x * r_ab_x + r_ab_y * r_ab_y); - - // r_ab = pos_i - pos_j ; |r_ab| - __m256d r_ab_x = _mm256_sub_pd(pix, pjx); // # 4 ADDs - __m256d r_ab_y = _mm256_sub_pd(piy, pjy); // # 4 ADDs - __m256d r_ab_n2 = _mm256_fmadd_pd(r_ab_x, r_ab_x, _mm256_mul_pd(r_ab_y, r_ab_y)); // # 8 MULTs, 4 ADDs - __m256d r_ab_n = _mm256_sqrt_pd(r_ab_n2); // # 4 SQRTs - - // double r_ab2_x = r_ab_x - sb_e_x[j]; - // double r_ab2_y = r_ab_y - sb_e_y[j]; - // - // double r_ab2_norm = sqrt(r_ab2_x * r_ab2_x + r_ab2_y * r_ab2_y); - - // r_ab2 = r_ab - sb_e_j ; |r_ab2| - __m256d r_ab2_x = _mm256_sub_pd(r_ab_x, sbe_jx); // # 4 ADDs - __m256d r_ab2_y = _mm256_sub_pd(r_ab_y, sbe_jy); // # 4 ADDs - __m256d r_ab2_n2 = _mm256_fmadd_pd(r_ab2_x, r_ab2_x, _mm256_mul_pd(r_ab2_y, r_ab2_y)); // # 8 MULTs, 4 ADDs - __m256d r_ab2_n = _mm256_sqrt_pd(r_ab2_n2); // # 4 SQRTs - - // double r_ab_norm_sum = r_ab_norm + r_ab2_norm; - // double two_b_sq = r_ab_norm_sum * r_ab_norm_sum - sb_sq[j]; - // double two_b = sqrt(two_b_sq); - - // 2b = sqrt((|r_ab| + |r_ab2|)^2 - sb_sq_j) - __m256d r_sum = _mm256_add_pd(r_ab_n, r_ab2_n); // # 4 ADDs - __m256d two_b_sq = _mm256_fmsub_pd(r_sum, r_sum, sb_jsq); // # 4 MULTs, 4 ADDs - __m256d two_b = _mm256_sqrt_pd(two_b_sq); // # 4 SQRTs - - // exp scalar fallback for now, we vectorize in a later step. probably the biggest perf win left. - __m256d e_arg = _mm256_mul_pd(two_b, v_neg_2s_inv); // # 4 MULTs - alignas(32) double tmp_arg[4], tmp_val[4]; - _mm256_store_pd(tmp_arg, e_arg); - tmp_val[0] = exp(tmp_arg[0]); - tmp_val[1] = exp(tmp_arg[1]); - tmp_val[2] = exp(tmp_arg[2]); - tmp_val[3] = exp(tmp_arg[3]); // # 4 EXPs (1 per lane, scalar) - __m256d e_val = _mm256_load_pd(tmp_val); - - // double scalar_mult_common = (r_ab_norm_sum / (two_b * r_ab_norm * r_ab2_norm)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b * NEG_TWO_SIGMA_INV)); - - // smc = (r_sum * NEG_V0_AB_div_TWO_SIGMA * e_val) / (two_b * r_ab_n * r_ab2_n) - // the i==j lane collapses denom to 0, so we swap in 1.0 there to keep smc finite. - // the AND with active zeroes the contribution from that lane anyway. - __m256d numer = _mm256_mul_pd(_mm256_mul_pd(r_sum, v_neg_v0_div_2s), e_val); // # 8 MULTs - __m256d denom = _mm256_mul_pd(_mm256_mul_pd(two_b, r_ab_n), r_ab2_n); // # 8 MULTs - __m256d denom_safe = _mm256_blendv_pd(_mm256_set1_pd(1.0), denom, active); // bitwise, no flop - __m256d smc = _mm256_div_pd(numer, denom_safe); // # 4 DIVs - - // double scalar_mult_r_ab = scalar_mult_common * r_ab2_norm; - // double scalar_mult_r_ab2 = scalar_mult_common * r_ab_norm; - __m256d sm_r_ab = _mm256_mul_pd(smc, r_ab2_n); // # 4 MULTs - __m256d sm_r_ab2 = _mm256_mul_pd(smc, r_ab_n); // # 4 MULTs - - // double f_alpha_beta_neg_x = r_ab_x * scalar_mult_r_ab + r_ab2_x * scalar_mult_r_ab2; - // double f_alpha_beta_neg_y = r_ab_y * scalar_mult_r_ab + r_ab2_y * scalar_mult_r_ab2; - - // scalar wants r_ab * sm_r_ab + r_ab2 * sm_r_ab2, the previous fma had the layout wrong - __m256d f_x = _mm256_fmadd_pd(r_ab2_x, sm_r_ab2, _mm256_mul_pd(r_ab_x, sm_r_ab)); // # 8 MULTs, 4 ADDs - __m256d f_y = _mm256_fmadd_pd(r_ab2_y, sm_r_ab2, _mm256_mul_pd(r_ab_y, sm_r_ab)); // # 8 MULTs, 4 ADDs - - // w_val = dt_neg by default, c_neg_times_dt when (a >= 0 && a*a > b_sq) - __m256d a = _mm256_mul_pd(_mm256_fmadd_pd(eix, f_x, _mm256_mul_pd(eiy, f_y)), v_cos_phi_inv); // # 12 MULTs, 4 ADDs - __m256d b_sq = _mm256_fmadd_pd(f_x, f_x, _mm256_mul_pd(f_y, f_y)); // # 8 MULTs, 4 ADDs - __m256d a_sq = _mm256_mul_pd(a, a); // # 4 MULTs - - __m256d c1 = _mm256_cmp_pd(a, v_zero, _CMP_GE_OQ); - __m256d c2 = _mm256_cmp_pd(a_sq, b_sq, _CMP_GT_OQ); - __m256d cond = _mm256_and_pd(c1, c2); - __m256d w_val = _mm256_blendv_pd(v_dt_neg, v_c_neg_dt, cond); - - // zero out inactive lanes (i==j and padding) before accumulating. - // AND with all-zero mask = 0, AND with all-one mask passes through. cheaper than blendv here. - __m256d f_x_safe = _mm256_and_pd(f_x, active); // bitwise, no flop - __m256d f_y_safe = _mm256_and_pd(f_y, active); // bitwise, no flop - acc_x = _mm256_fmadd_pd(f_x_safe, w_val, acc_x); // # 4 MULTs, 4 ADDs - acc_y = _mm256_fmadd_pd(f_y_safe, w_val, acc_y); // # 4 MULTs, 4 ADDs - } - - // horizontal sum acc_x, acc_y into the scalar f_alpha_dt - __m256d hsum_xy = _mm256_hadd_pd(acc_x, acc_y); // [x0+x1, y0+y1, x2+x3, y2+y3] // # 4 ADDs - __m128d lo = _mm256_castpd256_pd128(hsum_xy); - __m128d hi = _mm256_extractf128_pd(hsum_xy, 1); - __m128d sum_xy = _mm_add_pd(lo, hi); // [x_total, y_total] // # 2 ADDs - alignas(16) double sum_out[2]; - _mm_store_pd(sum_out, sum_xy); - f_alpha_dt_x += sum_out[0]; // # 1 ADD - f_alpha_dt_y += sum_out[1]; // # 1 ADD - - for (int k = 0; k < board.n_obstacles; k++) { - - double v1_x = pos_x[i] - board.obstacles[k].start.x; // # 1 ADD - double v1_y = pos_y[i] - board.obstacles[k].start.y; // # 1 ADD - - double projection = (v1_x * board.obstacles[k].obstacle_v.x + v1_y * board.obstacles[k].obstacle_v.y) * board.obstacles[k].length_sq_inv; // # 3 MULTs, 1 ADD - - if (projection < 0.0) - projection = 0.0; - else if (projection > 1.0) - projection = 1.0; - - double r_aB_x = pos_x[i] - (board.obstacles[k].start.x + board.obstacles[k].obstacle_v.x * projection); // # 1 MULT, 2 ADDs - double r_aB_y = pos_y[i] - (board.obstacles[k].start.y + board.obstacles[k].obstacle_v.y * projection); // # 1 MULT, 2 ADDs - - double r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); // # 2 MULTs, 1 ADD, 1 SQRT - double scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; // # 2 MULTs, 1 EXP, 1 DIV - double f_alpha_B_neg_x = r_aB_x * scalar_mult; // # 1 MULT - double f_alpha_B_neg_y = r_aB_y * scalar_mult; // # 1 MULT - - double w_val; - double a = (e_x[i] * f_alpha_B_neg_x + e_y[i] * f_alpha_B_neg_y) * cos_phi_inv; // # 3 MULTs, 1 ADD - double b_sq = f_alpha_B_neg_x * f_alpha_B_neg_x + f_alpha_B_neg_y * f_alpha_B_neg_y; // # 2 MULTs, 1 ADD - - w_val = dt_neg; - if (a >= 0 && (a * a > b_sq)) { // # 1 MULT for a*a - w_val = c_neg_times_dt; - } - - double f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; // # 1 MULT - double f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; // # 1 MULT - - f_alpha_dt_x += f_alpha_B_dt_x; // # 1 ADD - f_alpha_dt_y += f_alpha_B_dt_y; // # 1 ADD - } - - w_x[i] += f_alpha_dt_x; // 1 ADD - w_y[i] += f_alpha_dt_y; // 1 ADD - } - - for (int i = 0; i < n_p; i++) { - - double w_norm = sqrt(w_x[i] * w_x[i] + w_y[i] * w_y[i]); // # 2 MULTs, 1 ADD, 1 SQRT - - double correction_factor = min(1.0, v_max[i] / w_norm); // # 1 DIV - - curr_vel_x[i] = w_x[i] * correction_factor; // # 1 MULT - curr_vel_y[i] = w_y[i] * correction_factor; // # 1 MULT - - pos_x[i] = pos_x[i] + curr_vel_x[i] * dt; // # 1 MULT,1 ADD - pos_y[i] = pos_y[i] + curr_vel_y[i] * dt; // # 1 MULT, 1 ADD - - if (color[i] == 0 && pos_x[i] > (BOARD_LENGTH - 1.5)) { - pos_x[i] = 1.0; - destination_y[i] = pos_y[i]; - w_x[i] = desired_v0[i]; - w_y[i] = 0.0; - curr_vel_x[i] = w_x[i]; - curr_vel_y[i] = w_y[i]; - } - if (color[i] == 1 && pos_x[i] < 1.5) { - pos_x[i] = BOARD_LENGTH - 1.0; - destination_y[i] = pos_y[i]; - w_x[i] = -desired_v0[i]; - w_y[i] = 0.0; - curr_vel_x[i] = w_x[i]; - curr_vel_y[i] = w_y[i]; - } - - pos_y[i] = clamp(pos_y[i], WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - - double ex = destination_x[i] - pos_x[i]; // # 1 ADD - double ey = destination_y[i] - pos_y[i]; // # 1 ADD - - double e_norm_inv = 1.0 / sqrt(ex * ex + ey * ey); // # 2 MULTs, 1 ADD, 1 SQRT, 1 DIV - - e_x[i] = ex * e_norm_inv; // # 1 MULT - e_y[i] = ey * e_norm_inv; // # 1 MULT - - double velocity_norm_sq = curr_vel_x[i] * curr_vel_x[i] + curr_vel_y[i] * curr_vel_y[i]; // # 2 MULTs, 1 ADD - - double velocity_norm = sqrt(velocity_norm_sq); // # 1 SQRT - - sb_sq[i] = velocity_norm_sq * delta_t_sq; // # 1 MULT - - sb_e_x[i] = e_x[i] * (velocity_norm * delta_t); // # 2 MULTs (vel_norm*delta_t shared with next line) - sb_e_y[i] = e_y[i] * (velocity_norm * delta_t); // # 1 MULT - -#if !BENCHMARK - if (dump_path && (t % dump_interval == 0)) { - samples.emplace_back(t + 1, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } -#endif - } - } - -#if !BENCHMARK - if (dump_path) { - ofstream out(dump_path); - out << "time,id,x,y,p.e.x,p.e.y,color\n"; - - for (auto &[t, id, x, y, e_x, e_y, c] : samples) { - out << t << ',' << id << ',' << x << ',' << y << ',' << e_x << ',' << e_y << ',' << c << '\n'; - } - } -#endif - - return 0; -} diff --git a/variants/variant_inlining_7_SoA_AVX2_polyexp.cpp b/variants/variant_inlining_7_SoA_AVX2_polyexp.cpp index 717cd71..003e984 100644 --- a/variants/variant_inlining_7_SoA_AVX2_polyexp.cpp +++ b/variants/variant_inlining_7_SoA_AVX2_polyexp.cpp @@ -180,35 +180,41 @@ Pedestrian *init_pedestrians(int n_p) { Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } -// vectorized exp for a __m256d, no libm call. -// idea: exp(x) = 2^n * exp(r), where n = round(x / ln2) and r = x - n*ln2. -// after the range reduce, r lives in [-ln(2)/2, ln(2)/2] ~ [-0.347, 0.347], small enough -// that degree-7 taylor is accurate to ~1e-9 absolute, way under the 1e-3 verify.py tolerance. -// the 2^n part is free: in ieee 754 doubles, 2^n is just (n + 1023) << 52 in the bit pattern. -// Schraudolph 1999 for the 2^n bit trick. -// ieee 754 double layout (bias 1023, exp slot at bit 52): https://en.wikipedia.org/wiki/Double-precision_floating-point_format -// Horner's method for the poly eval: https://en.wikipedia.org/wiki/Horner%27s_method +// simd expd, degree-12 taylor on the [-ln2/2, ln2/2] reduced range, +// schraudolph 2^n bit trick on the exponent slot. +// # 64 MULTs, 56 ADDs static inline __m256d exp256_pd(__m256d x) { - // n = round(x / ln(2)) - const __m256d log2e = _mm256_set1_pd(1.4426950408889634); // 1/ln(2) - __m256d nf = _mm256_round_pd(_mm256_mul_pd(x, log2e), - _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); + const __m256d log2e = _mm256_set1_pd(1.4426950408889634); + __m256d nf = _mm256_round_pd(_mm256_mul_pd(x, log2e), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); // # 4 MULTs - // r = x - n * ln(2) const __m256d ln2 = _mm256_set1_pd(0.6931471805599453); - __m256d r = _mm256_fnmadd_pd(nf, ln2, x); // r = x - nf*ln2 + __m256d r = _mm256_fnmadd_pd(nf, ln2, x); // # 4 MULTs, 4 ADDs - // poly(r) ~ exp(r). degree-7 taylor, horner from highest coeff downwards. - const __m256d c7 = _mm256_set1_pd(1.0 / 5040.0); - const __m256d c6 = _mm256_set1_pd(1.0 / 720.0); - const __m256d c5 = _mm256_set1_pd(1.0 / 120.0); - const __m256d c4 = _mm256_set1_pd(1.0 / 24.0); - const __m256d c3 = _mm256_set1_pd(1.0 / 6.0); - const __m256d c2 = _mm256_set1_pd(0.5); - const __m256d c1 = _mm256_set1_pd(1.0); - const __m256d c0 = _mm256_set1_pd(1.0); + const __m256d c13 = _mm256_set1_pd(c13_scalar); + const __m256d c12 = _mm256_set1_pd(c12_scalar); + const __m256d c11 = _mm256_set1_pd(c11_scalar); + const __m256d c10 = _mm256_set1_pd(c10_scalar); + const __m256d c9 = _mm256_set1_pd(c9_scalar); + const __m256d c8 = _mm256_set1_pd(c8_scalar); + const __m256d c7 = _mm256_set1_pd(c7_scalar); + const __m256d c6 = _mm256_set1_pd(c6_scalar); + const __m256d c5 = _mm256_set1_pd(c5_scalar); + const __m256d c4 = _mm256_set1_pd(c4_scalar); + const __m256d c3 = _mm256_set1_pd(c3_scalar); + const __m256d c2 = _mm256_set1_pd(c2_scalar); + const __m256d c1 = _mm256_set1_pd(c1_scalar); + const __m256d c0 = _mm256_set1_pd(c0_scalar); - __m256d p = c7; + __m256d p = c13; + + // # 13 * (4 MULTs, 4 ADDs) + // # = 52 MULTs, 52 ADDs + p = _mm256_fmadd_pd(p, r, c12); + p = _mm256_fmadd_pd(p, r, c11); + p = _mm256_fmadd_pd(p, r, c10); + p = _mm256_fmadd_pd(p, r, c9); + p = _mm256_fmadd_pd(p, r, c8); + p = _mm256_fmadd_pd(p, r, c7); p = _mm256_fmadd_pd(p, r, c6); p = _mm256_fmadd_pd(p, r, c5); p = _mm256_fmadd_pd(p, r, c4); @@ -217,18 +223,13 @@ static inline __m256d exp256_pd(__m256d x) { p = _mm256_fmadd_pd(p, r, c1); p = _mm256_fmadd_pd(p, r, c0); - // scale by 2^n via bit trick on the exponent field. - // nf is already integer-valued from the round above, cvt to int32, sign-extend to int64, - // add ieee bias 1023, shift left 52 to land in the exponent slot of a double. - // note: for padding lanes (sb_e=0, pos=1e9) n can overflow int32, the resulting pow2n is garbage - // but the active mask in the j loop zeroes that lane out before accumulation so it doesn't matter. - __m128i ni32 = _mm256_cvtpd_epi32(nf); - __m256i ni64 = _mm256_cvtepi32_epi64(ni32); + __m128i ni32 = _mm256_cvtpd_epi32(nf); + __m256i ni64 = _mm256_cvtepi32_epi64(ni32); __m256i biased = _mm256_add_epi64(ni64, _mm256_set1_epi64x(1023)); __m256i scaled = _mm256_slli_epi64(biased, 52); - __m256d pow2n = _mm256_castsi256_pd(scaled); + __m256d pow2n = _mm256_castsi256_pd(scaled); - return _mm256_mul_pd(p, pow2n); + return _mm256_mul_pd(p, pow2n); // # 4 MULTs } int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { @@ -267,15 +268,21 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c const __m256d v_zero = _mm256_setzero_pd(); const __m256d v_np = _mm256_set1_pd((double)n_p); + // # flops per iteration (one pass of the outer time loop): + // # ADDs: n_p * 12 + n_p * n_p_pad * 29 + n_p * board.n_obstacles * 12 + n_p * 7 + // # MULTs: n_p * 4 + n_p * n_p_pad * 40 + n_p * board.n_obstacles * 19 + n_p * 16 + // # DIVs: n_p * n_p_pad * 1 + n_p * board.n_obstacles + n_p * 2 + // # SQRTs: n_p * n_p_pad * 3 + n_p * board.n_obstacles + n_p * 3 + // # EXPs: n_p * board.n_obstacles for (int t = 0; t < n_iter; t++) { for (int i = 0; i < n_p; i++) { - double desired_velocity_x = e_x[i] * desired_v0[i]; - double desired_velocity_y = e_y[i] * desired_v0[i]; + double desired_velocity_x = e_x[i] * desired_v0[i]; // # 1 MULT + double desired_velocity_y = e_y[i] * desired_v0[i]; // # 1 MULT - double f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; - double f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; + double f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; // # 1 MULT, 1 ADD + double f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; // # 1 MULT, 1 ADD // since i is fixed for the innermost loops we now wanna set all those variables const __m256d pix = _mm256_set1_pd(pos_x[i]); @@ -289,16 +296,16 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c for (int j = 0; j < n_p_pad; j += 4) { // 4 lanes at once, lane k maps to pedestrian j+k - __m256d j_idx = _mm256_add_pd(_mm256_set1_pd((double)j), lane_off); + __m256d j_idx = _mm256_add_pd(_mm256_set1_pd((double)j), lane_off); // # 4 ADDs // active = (j+k != i) AND (j+k < n_p), zero in lanes we wanna skip - __m256d m_neq_i = _mm256_cmp_pd(j_idx, v_i, _CMP_NEQ_OQ); + __m256d m_neq_i = _mm256_cmp_pd(j_idx, v_i, _CMP_NEQ_OQ); __m256d m_in_range = _mm256_cmp_pd(j_idx, v_np, _CMP_LT_OQ); - __m256d active = _mm256_and_pd(m_neq_i, m_in_range); + __m256d active = _mm256_and_pd(m_neq_i, m_in_range); // j-side loads, SoA contiguous. loadu because std::vector only guarantees 16B align. - __m256d pjx = _mm256_loadu_pd(&pos_x[j]); - __m256d pjy = _mm256_loadu_pd(&pos_y[j]); + __m256d pjx = _mm256_loadu_pd(&pos_x[j]); + __m256d pjy = _mm256_loadu_pd(&pos_y[j]); __m256d sbe_jx = _mm256_loadu_pd(&sb_e_x[j]); __m256d sbe_jy = _mm256_loadu_pd(&sb_e_y[j]); __m256d sb_jsq = _mm256_loadu_pd(&sb_sq[j]); @@ -309,10 +316,10 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c // double r_ab_norm = sqrt(r_ab_x * r_ab_x + r_ab_y * r_ab_y); // r_ab = pos_i - pos_j ; |r_ab| - __m256d r_ab_x = _mm256_sub_pd(pix, pjx); - __m256d r_ab_y = _mm256_sub_pd(piy, pjy); - __m256d r_ab_n2 = _mm256_fmadd_pd(r_ab_x, r_ab_x, _mm256_mul_pd(r_ab_y, r_ab_y)); - __m256d r_ab_n = _mm256_sqrt_pd(r_ab_n2); + __m256d r_ab_x = _mm256_sub_pd(pix, pjx); // # 4 ADDs + __m256d r_ab_y = _mm256_sub_pd(piy, pjy); // # 4 ADDs + __m256d r_ab_n2 = _mm256_fmadd_pd(r_ab_x, r_ab_x, _mm256_mul_pd(r_ab_y, r_ab_y)); // # 8 MULTs, 4 ADDs + __m256d r_ab_n = _mm256_sqrt_pd(r_ab_n2); // # 4 SQRTs // double r_ab2_x = r_ab_x - sb_e_x[j]; // double r_ab2_y = r_ab_y - sb_e_y[j]; @@ -320,21 +327,21 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c // double r_ab2_norm = sqrt(r_ab2_x * r_ab2_x + r_ab2_y * r_ab2_y); // r_ab2 = r_ab - sb_e_j ; |r_ab2| - __m256d r_ab2_x = _mm256_sub_pd(r_ab_x, sbe_jx); - __m256d r_ab2_y = _mm256_sub_pd(r_ab_y, sbe_jy); - __m256d r_ab2_n2 = _mm256_fmadd_pd(r_ab2_x, r_ab2_x, _mm256_mul_pd(r_ab2_y, r_ab2_y)); - __m256d r_ab2_n = _mm256_sqrt_pd(r_ab2_n2); + __m256d r_ab2_x = _mm256_sub_pd(r_ab_x, sbe_jx); // # 4 ADDs + __m256d r_ab2_y = _mm256_sub_pd(r_ab_y, sbe_jy); // # 4 ADDs + __m256d r_ab2_n2 = _mm256_fmadd_pd(r_ab2_x, r_ab2_x, _mm256_mul_pd(r_ab2_y, r_ab2_y)); // # 8 MULTs, 4 ADDs + __m256d r_ab2_n = _mm256_sqrt_pd(r_ab2_n2); // # 4 SQRTs // double r_ab_norm_sum = r_ab_norm + r_ab2_norm; // double two_b_sq = r_ab_norm_sum * r_ab_norm_sum - sb_sq[j]; // double two_b = sqrt(two_b_sq); // 2b = sqrt((|r_ab| + |r_ab2|)^2 - sb_sq_j) - __m256d r_sum = _mm256_add_pd(r_ab_n, r_ab2_n); - __m256d two_b_sq = _mm256_fmsub_pd(r_sum, r_sum, sb_jsq); - __m256d two_b = _mm256_sqrt_pd(two_b_sq); + __m256d r_sum = _mm256_add_pd(r_ab_n, r_ab2_n); // # 4 ADDs + __m256d two_b_sq = _mm256_fmsub_pd(r_sum, r_sum, sb_jsq); // # 4 MULTs, 4 ADDs + __m256d two_b = _mm256_sqrt_pd(two_b_sq); // # 4 SQRTs - __m256d e_arg = _mm256_mul_pd(two_b, v_neg_2s_inv); + __m256d e_arg = _mm256_mul_pd(two_b, v_neg_2s_inv); // # 4 MULTs // we used to call libm exp() 4 times into a scratch array here, now do it in simd // alignas(32) double tmp_arg[4], tmp_val[4]; // _mm256_store_pd(tmp_arg, e_arg); @@ -343,109 +350,109 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c // tmp_val[2] = exp(tmp_arg[2]); // tmp_val[3] = exp(tmp_arg[3]); // __m256d e_val = _mm256_load_pd(tmp_val); - __m256d e_val = exp256_pd(e_arg); + __m256d e_val = exp256_pd(e_arg); // # 64 MULTs, 56 ADDs // double scalar_mult_common = (r_ab_norm_sum / (two_b * r_ab_norm * r_ab2_norm)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b * NEG_TWO_SIGMA_INV)); // smc = (r_sum * NEG_V0_AB_div_TWO_SIGMA * e_val) / (two_b * r_ab_n * r_ab2_n) // the i==j lane collapses denom to 0, so we swap in 1.0 there to keep smc finite. // the AND with active zeroes the contribution from that lane anyway. - __m256d numer = _mm256_mul_pd(_mm256_mul_pd(r_sum, v_neg_v0_div_2s), e_val); - __m256d denom = _mm256_mul_pd(_mm256_mul_pd(two_b, r_ab_n), r_ab2_n); - __m256d denom_safe = _mm256_blendv_pd(_mm256_set1_pd(1.0), denom, active); - __m256d smc = _mm256_div_pd(numer, denom_safe); + __m256d numer = _mm256_mul_pd(_mm256_mul_pd(r_sum, v_neg_v0_div_2s), e_val); // # 8 MULTs + __m256d denom = _mm256_mul_pd(_mm256_mul_pd(two_b, r_ab_n), r_ab2_n); // # 8 MULTs + __m256d denom_safe = _mm256_blendv_pd(_mm256_set1_pd(1.0), denom, active); // bitwise, no flop + __m256d smc = _mm256_div_pd(numer, denom_safe); // # 4 DIVs // double scalar_mult_r_ab = scalar_mult_common * r_ab2_norm; // double scalar_mult_r_ab2 = scalar_mult_common * r_ab_norm; - __m256d sm_r_ab = _mm256_mul_pd(smc, r_ab2_n); - __m256d sm_r_ab2 = _mm256_mul_pd(smc, r_ab_n); + __m256d sm_r_ab = _mm256_mul_pd(smc, r_ab2_n); // # 4 MULTs + __m256d sm_r_ab2 = _mm256_mul_pd(smc, r_ab_n); // # 4 MULTs // double f_alpha_beta_neg_x = r_ab_x * scalar_mult_r_ab + r_ab2_x * scalar_mult_r_ab2; // double f_alpha_beta_neg_y = r_ab_y * scalar_mult_r_ab + r_ab2_y * scalar_mult_r_ab2; // scalar wants r_ab * sm_r_ab + r_ab2 * sm_r_ab2, the previous fma had the layout wrong - __m256d f_x = _mm256_fmadd_pd(r_ab2_x, sm_r_ab2, _mm256_mul_pd(r_ab_x, sm_r_ab)); - __m256d f_y = _mm256_fmadd_pd(r_ab2_y, sm_r_ab2, _mm256_mul_pd(r_ab_y, sm_r_ab)); + __m256d f_x = _mm256_fmadd_pd(r_ab2_x, sm_r_ab2, _mm256_mul_pd(r_ab_x, sm_r_ab)); // # 8 MULTs, 4 ADDs + __m256d f_y = _mm256_fmadd_pd(r_ab2_y, sm_r_ab2, _mm256_mul_pd(r_ab_y, sm_r_ab)); // # 8 MULTs, 4 ADDs // w_val = dt_neg by default, c_neg_times_dt when (a >= 0 && a*a > b_sq) - __m256d a = _mm256_mul_pd(_mm256_fmadd_pd(eix, f_x, _mm256_mul_pd(eiy, f_y)), v_cos_phi_inv); - __m256d b_sq = _mm256_fmadd_pd(f_x, f_x, _mm256_mul_pd(f_y, f_y)); - __m256d a_sq = _mm256_mul_pd(a, a); + __m256d a = _mm256_mul_pd(_mm256_fmadd_pd(eix, f_x, _mm256_mul_pd(eiy, f_y)), v_cos_phi_inv); // # 12 MULTs, 4 ADDs + __m256d b_sq = _mm256_fmadd_pd(f_x, f_x, _mm256_mul_pd(f_y, f_y)); // # 8 MULTs, 4 ADDs + __m256d a_sq = _mm256_mul_pd(a, a); // # 4 MULTs - __m256d c1 = _mm256_cmp_pd(a, v_zero, _CMP_GE_OQ); - __m256d c2 = _mm256_cmp_pd(a_sq, b_sq, _CMP_GT_OQ); - __m256d cond = _mm256_and_pd(c1, c2); + __m256d c1 = _mm256_cmp_pd(a, v_zero, _CMP_GE_OQ); + __m256d c2 = _mm256_cmp_pd(a_sq, b_sq, _CMP_GT_OQ); + __m256d cond = _mm256_and_pd(c1, c2); __m256d w_val = _mm256_blendv_pd(v_dt_neg, v_c_neg_dt, cond); // zero out inactive lanes (i==j and padding) before accumulating. // AND with all-zero mask = 0, AND with all-one mask passes through. cheaper than blendv here. - __m256d f_x_safe = _mm256_and_pd(f_x, active); - __m256d f_y_safe = _mm256_and_pd(f_y, active); - acc_x = _mm256_fmadd_pd(f_x_safe, w_val, acc_x); - acc_y = _mm256_fmadd_pd(f_y_safe, w_val, acc_y); + __m256d f_x_safe = _mm256_and_pd(f_x, active); // bitwise, no flop + __m256d f_y_safe = _mm256_and_pd(f_y, active); // bitwise, no flop + acc_x = _mm256_fmadd_pd(f_x_safe, w_val, acc_x); // # 4 MULTs, 4 ADDs + acc_y = _mm256_fmadd_pd(f_y_safe, w_val, acc_y); // # 4 MULTs, 4 ADDs } // horizontal sum acc_x, acc_y into the scalar f_alpha_dt - __m256d hsum_xy = _mm256_hadd_pd(acc_x, acc_y); // [x0+x1, y0+y1, x2+x3, y2+y3] - __m128d lo = _mm256_castpd256_pd128(hsum_xy); - __m128d hi = _mm256_extractf128_pd(hsum_xy, 1); - __m128d sum_xy = _mm_add_pd(lo, hi); // [x_total, y_total] + __m256d hsum_xy = _mm256_hadd_pd(acc_x, acc_y); // [x0+x1, y0+y1, x2+x3, y2+y3] // # 4 ADDs + __m128d lo = _mm256_castpd256_pd128(hsum_xy); + __m128d hi = _mm256_extractf128_pd(hsum_xy, 1); + __m128d sum_xy = _mm_add_pd(lo, hi); // [x_total, y_total] // # 2 ADDs alignas(16) double sum_out[2]; _mm_store_pd(sum_out, sum_xy); - f_alpha_dt_x += sum_out[0]; - f_alpha_dt_y += sum_out[1]; + f_alpha_dt_x += sum_out[0]; // # 1 ADD + f_alpha_dt_y += sum_out[1]; // # 1 ADD for (int k = 0; k < board.n_obstacles; k++) { - double v1_x = pos_x[i] - board.obstacles[k].start.x; - double v1_y = pos_y[i] - board.obstacles[k].start.y; + double v1_x = pos_x[i] - board.obstacles[k].start.x; // # 1 ADD + double v1_y = pos_y[i] - board.obstacles[k].start.y; // # 1 ADD - double projection = (v1_x * board.obstacles[k].obstacle_v.x + v1_y * board.obstacles[k].obstacle_v.y) * board.obstacles[k].length_sq_inv; + double projection = (v1_x * board.obstacles[k].obstacle_v.x + v1_y * board.obstacles[k].obstacle_v.y) * board.obstacles[k].length_sq_inv; // # 3 MULTs, 1 ADD if (projection < 0.0) projection = 0.0; else if (projection > 1.0) projection = 1.0; - double r_aB_x = pos_x[i] - (board.obstacles[k].start.x + board.obstacles[k].obstacle_v.x * projection); - double r_aB_y = pos_y[i] - (board.obstacles[k].start.y + board.obstacles[k].obstacle_v.y * projection); + double r_aB_x = pos_x[i] - (board.obstacles[k].start.x + board.obstacles[k].obstacle_v.x * projection); // # 1 MULT, 2 ADDs + double r_aB_y = pos_y[i] - (board.obstacles[k].start.y + board.obstacles[k].obstacle_v.y * projection); // # 1 MULT, 2 ADDs - double r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); - double scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; - double f_alpha_B_neg_x = r_aB_x * scalar_mult; - double f_alpha_B_neg_y = r_aB_y * scalar_mult; + double r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); // # 2 MULTs, 1 ADD, 1 SQRT + double scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; // # 2 MULTs, 1 EXP, 1 DIV + double f_alpha_B_neg_x = r_aB_x * scalar_mult; // # 1 MULT + double f_alpha_B_neg_y = r_aB_y * scalar_mult; // # 1 MULT double w_val; - double a = (e_x[i] * f_alpha_B_neg_x + e_y[i] * f_alpha_B_neg_y) * cos_phi_inv; - double b_sq = f_alpha_B_neg_x * f_alpha_B_neg_x + f_alpha_B_neg_y * f_alpha_B_neg_y; + double a = (e_x[i] * f_alpha_B_neg_x + e_y[i] * f_alpha_B_neg_y) * cos_phi_inv; // # 3 MULTs, 1 ADD + double b_sq = f_alpha_B_neg_x * f_alpha_B_neg_x + f_alpha_B_neg_y * f_alpha_B_neg_y; // # 2 MULTs, 1 ADD w_val = dt_neg; - if (a >= 0 && (a * a > b_sq)) { + if (a >= 0 && (a * a > b_sq)) { // # 1 MULT for a*a w_val = c_neg_times_dt; } - double f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; - double f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; + double f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; // # 1 MULT + double f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; // # 1 MULT - f_alpha_dt_x += f_alpha_B_dt_x; - f_alpha_dt_y += f_alpha_B_dt_y; + f_alpha_dt_x += f_alpha_B_dt_x; // # 1 ADD + f_alpha_dt_y += f_alpha_B_dt_y; // # 1 ADD } - w_x[i] += f_alpha_dt_x; - w_y[i] += f_alpha_dt_y; + w_x[i] += f_alpha_dt_x; // # 1 ADD + w_y[i] += f_alpha_dt_y; // # 1 ADD } for (int i = 0; i < n_p; i++) { - double w_norm = sqrt(w_x[i] * w_x[i] + w_y[i] * w_y[i]); + double w_norm = sqrt(w_x[i] * w_x[i] + w_y[i] * w_y[i]); // # 2 MULTs, 1 ADD, 1 SQRT - double correction_factor = min(1.0, v_max[i] / w_norm); + double correction_factor = min(1.0, v_max[i] / w_norm); // # 1 DIV - curr_vel_x[i] = w_x[i] * correction_factor; - curr_vel_y[i] = w_y[i] * correction_factor; + curr_vel_x[i] = w_x[i] * correction_factor; // # 1 MULT + curr_vel_y[i] = w_y[i] * correction_factor; // # 1 MULT - pos_x[i] = pos_x[i] + curr_vel_x[i] * dt; - pos_y[i] = pos_y[i] + curr_vel_y[i] * dt; + pos_x[i] = pos_x[i] + curr_vel_x[i] * dt; // # 1 MULT, 1 ADD + pos_y[i] = pos_y[i] + curr_vel_y[i] * dt; // # 1 MULT, 1 ADD if (color[i] == 0 && pos_x[i] > (BOARD_LENGTH - 1.5)) { pos_x[i] = 1.0; @@ -466,22 +473,22 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c pos_y[i] = clamp(pos_y[i], WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - double ex = destination_x[i] - pos_x[i]; - double ey = destination_y[i] - pos_y[i]; + double ex = destination_x[i] - pos_x[i]; // # 1 ADD + double ey = destination_y[i] - pos_y[i]; // # 1 ADD - double e_norm_inv = 1.0 / sqrt(ex * ex + ey * ey); + double e_norm_inv = 1.0 / sqrt(ex * ex + ey * ey); // # 2 MULTs, 1 ADD, 1 SQRT, 1 DIV - e_x[i] = ex * e_norm_inv; - e_y[i] = ey * e_norm_inv; + e_x[i] = ex * e_norm_inv; // # 1 MULT + e_y[i] = ey * e_norm_inv; // # 1 MULT - double velocity_norm_sq = curr_vel_x[i] * curr_vel_x[i] + curr_vel_y[i] * curr_vel_y[i]; + double velocity_norm_sq = curr_vel_x[i] * curr_vel_x[i] + curr_vel_y[i] * curr_vel_y[i]; // # 2 MULTs, 1 ADD - double velocity_norm = sqrt(velocity_norm_sq); + double velocity_norm = sqrt(velocity_norm_sq); // # 1 SQRT - sb_sq[i] = velocity_norm_sq * delta_t_sq; + sb_sq[i] = velocity_norm_sq * delta_t_sq; // # 1 MULT - sb_e_x[i] = e_x[i] * (velocity_norm * delta_t); - sb_e_y[i] = e_y[i] * (velocity_norm * delta_t); + sb_e_x[i] = e_x[i] * (velocity_norm * delta_t); // # 2 MULTs (vel_norm*delta_t shared with next line) + sb_e_y[i] = e_y[i] * (velocity_norm * delta_t); // # 1 MULT #if !BENCHMARK if (dump_path && (t % dump_interval == 0)) { diff --git a/variants/variant_inlining_7_SoA_AVX2_polyexp_expfix.cpp b/variants/variant_inlining_7_SoA_AVX2_polyexp_expfix.cpp deleted file mode 100644 index a5c93b8..0000000 --- a/variants/variant_inlining_7_SoA_AVX2_polyexp_expfix.cpp +++ /dev/null @@ -1,513 +0,0 @@ -// # This file uses avx2 -// # builds on variant_inlining_7_SoA_AVX2 by killing the 4 scalar libm exp() calls -// # in the j loop and doing it in simd with a polynomial approximation instead. - -// Okay our first step is to use a SoA instead of an AoS -// We only do SoA for the pedestrian struct, there we wanna optimize such that we access for the ped-ped forces adjacent pedestrians (in the arrays) -// Now in a second step we wanna really use AVX2 for the mainloop (where we wana optimize the most innerloop first) -// next step now: the scalar exp() inside the j loop was ~54% of inner-loop cycles, we replace with one simd call. - -#include "../headers/board.hpp" -#include "../headers/constants.hpp" -#include "../headers/pedestrian_reduced.hpp" - -#include // to use avx2 - -#include -#include -#include -#include -#include -#include -#include -#include - -#define SEED 42 -#define BOARD_WIDTH 10.0 -#define BOARD_LENGTH 50.0 -#define WALL_EPS 1e-3 -#define BOARD_WIDTH_MINUS_WALL_EPS 9.999 - -#ifndef RANDOM_SEED -#define RANDOM_SEED 0 -#endif - -#ifndef BENCHMARK -#define BENCHMARK 0 -#endif - -using namespace std; - -// we wanna use arrays so we can implement SOA, we create arrays for all the data we need and access -vector pos_x, pos_y; -vector sb_sq; -vector sb_e_x, sb_e_y; -vector e_x, e_y; -vector curr_vel_x, curr_vel_y; -vector w_x, w_y; -vector desired_v0; -vector v_max; -vector destination_x, destination_y; -vector color; - -Pedestrian *init_pedestrians(int n_p) { - -#if RANDOM_SEED - random_device rd; - mt19937 gen(rd()); -#else - mt19937 gen(SEED); -#endif - - normal_distribution velocity_gen(v0_mean, v0_std_dev); - uniform_real_distribution y_gen(0.3, BOARD_WIDTH - 0.3); - uniform_real_distribution x_gen_left(2.0, BOARD_LENGTH / 2.0); - uniform_real_distribution x_gen_right(BOARD_LENGTH / 2.0, BOARD_LENGTH - 2.0); - - const int n_p_pad = (n_p + 3) & ~3; // round up to a multiple of 4 (so its easy to use avx) - - // resize all our arrays for this run - pos_x.resize(n_p_pad); - pos_y.resize(n_p_pad); - sb_sq.resize(n_p_pad); - sb_e_x.resize(n_p_pad); - sb_e_y.resize(n_p_pad); - e_x.resize(n_p_pad); - e_y.resize(n_p_pad); - curr_vel_x.resize(n_p_pad); - curr_vel_y.resize(n_p_pad); - w_x.resize(n_p_pad); - w_y.resize(n_p_pad); - desired_v0.resize(n_p_pad); - v_max.resize(n_p_pad); - destination_x.resize(n_p_pad); - destination_y.resize(n_p_pad); - color.resize(n_p_pad); - - int n_p_half = n_p / 2; - - for (int i = 0; i < n_p_half; i++) { - double x = x_gen_left(gen); - double y = y_gen(gen); - - double dest_x = BOARD_LENGTH + 30.0; // renamed to avoid shadowing destination_x[] - double dest_y = y; // same idea for destination_y[] - - double init_e_x = dest_x - x; - double init_e_y = dest_y - y; - double init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - double init_e_unit_x = init_e_x / init_e_norm; - double init_e_unit_y = init_e_y / init_e_norm; - - double d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1); - - double v_m = 1.3 * d_v0; - - color[i] = 0; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - // Fields the Pedestrian constructor would have zero-initialized: - w_x[i] = 0.0; - w_y[i] = 0.0; - curr_vel_x[i] = 0.0; - curr_vel_y[i] = 0.0; - sb_sq[i] = 0.0; - sb_e_x[i] = 0.0; - sb_e_y[i] = 0.0; - } - - for (int i = n_p_half; i < n_p; i++) { - double x = x_gen_right(gen); - double y = y_gen(gen); - - double dest_x = -30; - double dest_y = y; - - double init_e_x = dest_x - x; - double init_e_y = dest_y - y; - double init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - double init_e_unit_x = init_e_x / init_e_norm; - double init_e_unit_y = init_e_y / init_e_norm; - - double d_v0; - do { - d_v0 = velocity_gen(gen); - } while (d_v0 <= 0.1); - - double v_m = 1.3 * d_v0; - - color[i] = 1; - pos_x[i] = x; - pos_y[i] = y; - e_x[i] = init_e_unit_x; - e_y[i] = init_e_unit_y; - v_max[i] = v_m; - desired_v0[i] = d_v0; - destination_x[i] = dest_x; - destination_y[i] = dest_y; - - // Fields the Pedestrian constructor would have zero-initialized: - w_x[i] = 0.0; - w_y[i] = 0.0; - curr_vel_x[i] = 0.0; - curr_vel_y[i] = 0.0; - sb_sq[i] = 0.0; - sb_e_x[i] = 0.0; - sb_e_y[i] = 0.0; - } - - // Padding lanes: positions far away, everything else zero. Any unmasked SIMD - // contribution from these lanes will vanish through exp(very negative) roughly 0. - for (int j = n_p; j < n_p_pad; j++) { - pos_x[j] = 1e9; - pos_y[j] = 1e9; - sb_sq[j] = 0.0; - sb_e_x[j] = 0.0; - sb_e_y[j] = 0.0; - } - return nullptr; -} - -Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } - -// simd expd, degree-12 taylor on the [-ln2/2, ln2/2] reduced range, -// schraudolph 2^n bit trick on the exponent slot. -// # 64 MULTs, 56 ADDs -static inline __m256d exp256_pd(__m256d x) { - const __m256d log2e = _mm256_set1_pd(1.4426950408889634); - __m256d nf = _mm256_round_pd(_mm256_mul_pd(x, log2e), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); // # 4 MULTs - - const __m256d ln2 = _mm256_set1_pd(0.6931471805599453); - __m256d r = _mm256_fnmadd_pd(nf, ln2, x); // # 4 MULTs, 4 ADDs - - const __m256d c13 = _mm256_set1_pd(c13_scalar); - const __m256d c12 = _mm256_set1_pd(c12_scalar); - const __m256d c11 = _mm256_set1_pd(c11_scalar); - const __m256d c10 = _mm256_set1_pd(c10_scalar); - const __m256d c9 = _mm256_set1_pd(c9_scalar); - const __m256d c8 = _mm256_set1_pd(c8_scalar); - const __m256d c7 = _mm256_set1_pd(c7_scalar); - const __m256d c6 = _mm256_set1_pd(c6_scalar); - const __m256d c5 = _mm256_set1_pd(c5_scalar); - const __m256d c4 = _mm256_set1_pd(c4_scalar); - const __m256d c3 = _mm256_set1_pd(c3_scalar); - const __m256d c2 = _mm256_set1_pd(c2_scalar); - const __m256d c1 = _mm256_set1_pd(c1_scalar); - const __m256d c0 = _mm256_set1_pd(c0_scalar); - - __m256d p = c13; - - // # 13 * (4 MULTs, 4 ADDs) - // # = 52 MULTs, 52 ADDs - p = _mm256_fmadd_pd(p, r, c12); - p = _mm256_fmadd_pd(p, r, c11); - p = _mm256_fmadd_pd(p, r, c10); - p = _mm256_fmadd_pd(p, r, c9); - p = _mm256_fmadd_pd(p, r, c8); - p = _mm256_fmadd_pd(p, r, c7); - p = _mm256_fmadd_pd(p, r, c6); - p = _mm256_fmadd_pd(p, r, c5); - p = _mm256_fmadd_pd(p, r, c4); - p = _mm256_fmadd_pd(p, r, c3); - p = _mm256_fmadd_pd(p, r, c2); - p = _mm256_fmadd_pd(p, r, c1); - p = _mm256_fmadd_pd(p, r, c0); - - __m128i ni32 = _mm256_cvtpd_epi32(nf); - __m256i ni64 = _mm256_cvtepi32_epi64(ni32); - __m256i biased = _mm256_add_epi64(ni64, _mm256_set1_epi64x(1023)); - __m256i scaled = _mm256_slli_epi64(biased, 52); - __m256d pow2n = _mm256_castsi256_pd(scaled); - - return _mm256_mul_pd(p, pow2n); // # 4 MULTs -} - -int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { - -#if BENCHMARK - (void)dump_path; -#endif - -#if !BENCHMARK - const int dump_interval = 1; - - vector> samples; - - if (dump_path) { - samples.reserve(static_cast(n_iter / dump_interval + 1) * n_p); - - for (int i = 0; i < n_p; i++) { - // Pedestrian &p = pedestrians[i]; - samples.emplace_back(0, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } - } -#endif - - // all the constants for the AVX2 setup - - const int n_p_pad = (n_p + 3) & ~3; - - alignas(32) const double lane_offset_arr[4] = {0.0, 1.0, 2.0, 3.0}; - const __m256d lane_off = _mm256_load_pd(lane_offset_arr); - - const __m256d v_neg_v0_div_2s = _mm256_set1_pd(NEG_V0_AB_div_TWO_SIGMA); - const __m256d v_neg_2s_inv = _mm256_set1_pd(NEG_TWO_SIGMA_INV); - const __m256d v_cos_phi_inv = _mm256_set1_pd(cos_phi_inv); - const __m256d v_dt_neg = _mm256_set1_pd(dt_neg); - const __m256d v_c_neg_dt = _mm256_set1_pd(c_neg_times_dt); - const __m256d v_zero = _mm256_setzero_pd(); - const __m256d v_np = _mm256_set1_pd((double)n_p); - - // # flops per iteration (one pass of the outer time loop): - // # ADDs: n_p * 12 + n_p * n_p_pad * 29 + n_p * board.n_obstacles * 12 + n_p * 7 - // # MULTs: n_p * 4 + n_p * n_p_pad * 40 + n_p * board.n_obstacles * 19 + n_p * 16 - // # DIVs: n_p * n_p_pad * 1 + n_p * board.n_obstacles + n_p * 2 - // # SQRTs: n_p * n_p_pad * 3 + n_p * board.n_obstacles + n_p * 3 - // # EXPs: n_p * board.n_obstacles - for (int t = 0; t < n_iter; t++) { - - for (int i = 0; i < n_p; i++) { - - double desired_velocity_x = e_x[i] * desired_v0[i]; // # 1 MULT - double desired_velocity_y = e_y[i] * desired_v0[i]; // # 1 MULT - - double f_alpha_dt_x = (desired_velocity_x - curr_vel_x[i]) * dt_times_tau_alpha_inv; // # 1 MULT, 1 ADD - double f_alpha_dt_y = (desired_velocity_y - curr_vel_y[i]) * dt_times_tau_alpha_inv; // # 1 MULT, 1 ADD - - // since i is fixed for the innermost loops we now wanna set all those variables - const __m256d pix = _mm256_set1_pd(pos_x[i]); - const __m256d piy = _mm256_set1_pd(pos_y[i]); - const __m256d eix = _mm256_set1_pd(e_x[i]); - const __m256d eiy = _mm256_set1_pd(e_y[i]); - const __m256d v_i = _mm256_set1_pd((double)i); - - __m256d acc_x = _mm256_setzero_pd(); - __m256d acc_y = _mm256_setzero_pd(); - - for (int j = 0; j < n_p_pad; j += 4) { - // 4 lanes at once, lane k maps to pedestrian j+k - __m256d j_idx = _mm256_add_pd(_mm256_set1_pd((double)j), lane_off); // # 4 ADDs - - // active = (j+k != i) AND (j+k < n_p), zero in lanes we wanna skip - __m256d m_neq_i = _mm256_cmp_pd(j_idx, v_i, _CMP_NEQ_OQ); - __m256d m_in_range = _mm256_cmp_pd(j_idx, v_np, _CMP_LT_OQ); - __m256d active = _mm256_and_pd(m_neq_i, m_in_range); - - // j-side loads, SoA contiguous. loadu because std::vector only guarantees 16B align. - __m256d pjx = _mm256_loadu_pd(&pos_x[j]); - __m256d pjy = _mm256_loadu_pd(&pos_y[j]); - __m256d sbe_jx = _mm256_loadu_pd(&sb_e_x[j]); - __m256d sbe_jy = _mm256_loadu_pd(&sb_e_y[j]); - __m256d sb_jsq = _mm256_loadu_pd(&sb_sq[j]); - - // double r_ab_x = pos_x[i] - pos_x[j]; - // double r_ab_y = pos_y[i] - pos_y[j]; - // - // double r_ab_norm = sqrt(r_ab_x * r_ab_x + r_ab_y * r_ab_y); - - // r_ab = pos_i - pos_j ; |r_ab| - __m256d r_ab_x = _mm256_sub_pd(pix, pjx); // # 4 ADDs - __m256d r_ab_y = _mm256_sub_pd(piy, pjy); // # 4 ADDs - __m256d r_ab_n2 = _mm256_fmadd_pd(r_ab_x, r_ab_x, _mm256_mul_pd(r_ab_y, r_ab_y)); // # 8 MULTs, 4 ADDs - __m256d r_ab_n = _mm256_sqrt_pd(r_ab_n2); // # 4 SQRTs - - // double r_ab2_x = r_ab_x - sb_e_x[j]; - // double r_ab2_y = r_ab_y - sb_e_y[j]; - // - // double r_ab2_norm = sqrt(r_ab2_x * r_ab2_x + r_ab2_y * r_ab2_y); - - // r_ab2 = r_ab - sb_e_j ; |r_ab2| - __m256d r_ab2_x = _mm256_sub_pd(r_ab_x, sbe_jx); // # 4 ADDs - __m256d r_ab2_y = _mm256_sub_pd(r_ab_y, sbe_jy); // # 4 ADDs - __m256d r_ab2_n2 = _mm256_fmadd_pd(r_ab2_x, r_ab2_x, _mm256_mul_pd(r_ab2_y, r_ab2_y)); // # 8 MULTs, 4 ADDs - __m256d r_ab2_n = _mm256_sqrt_pd(r_ab2_n2); // # 4 SQRTs - - // double r_ab_norm_sum = r_ab_norm + r_ab2_norm; - // double two_b_sq = r_ab_norm_sum * r_ab_norm_sum - sb_sq[j]; - // double two_b = sqrt(two_b_sq); - - // 2b = sqrt((|r_ab| + |r_ab2|)^2 - sb_sq_j) - __m256d r_sum = _mm256_add_pd(r_ab_n, r_ab2_n); // # 4 ADDs - __m256d two_b_sq = _mm256_fmsub_pd(r_sum, r_sum, sb_jsq); // # 4 MULTs, 4 ADDs - __m256d two_b = _mm256_sqrt_pd(two_b_sq); // # 4 SQRTs - - __m256d e_arg = _mm256_mul_pd(two_b, v_neg_2s_inv); // # 4 MULTs - // we used to call libm exp() 4 times into a scratch array here, now do it in simd - // alignas(32) double tmp_arg[4], tmp_val[4]; - // _mm256_store_pd(tmp_arg, e_arg); - // tmp_val[0] = exp(tmp_arg[0]); - // tmp_val[1] = exp(tmp_arg[1]); - // tmp_val[2] = exp(tmp_arg[2]); - // tmp_val[3] = exp(tmp_arg[3]); - // __m256d e_val = _mm256_load_pd(tmp_val); - __m256d e_val = exp256_pd(e_arg); // # 64 MULTs, 56 ADDs - - // double scalar_mult_common = (r_ab_norm_sum / (two_b * r_ab_norm * r_ab2_norm)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b * NEG_TWO_SIGMA_INV)); - - // smc = (r_sum * NEG_V0_AB_div_TWO_SIGMA * e_val) / (two_b * r_ab_n * r_ab2_n) - // the i==j lane collapses denom to 0, so we swap in 1.0 there to keep smc finite. - // the AND with active zeroes the contribution from that lane anyway. - __m256d numer = _mm256_mul_pd(_mm256_mul_pd(r_sum, v_neg_v0_div_2s), e_val); // # 8 MULTs - __m256d denom = _mm256_mul_pd(_mm256_mul_pd(two_b, r_ab_n), r_ab2_n); // # 8 MULTs - __m256d denom_safe = _mm256_blendv_pd(_mm256_set1_pd(1.0), denom, active); // bitwise, no flop - __m256d smc = _mm256_div_pd(numer, denom_safe); // # 4 DIVs - - // double scalar_mult_r_ab = scalar_mult_common * r_ab2_norm; - // double scalar_mult_r_ab2 = scalar_mult_common * r_ab_norm; - __m256d sm_r_ab = _mm256_mul_pd(smc, r_ab2_n); // # 4 MULTs - __m256d sm_r_ab2 = _mm256_mul_pd(smc, r_ab_n); // # 4 MULTs - - // double f_alpha_beta_neg_x = r_ab_x * scalar_mult_r_ab + r_ab2_x * scalar_mult_r_ab2; - // double f_alpha_beta_neg_y = r_ab_y * scalar_mult_r_ab + r_ab2_y * scalar_mult_r_ab2; - - // scalar wants r_ab * sm_r_ab + r_ab2 * sm_r_ab2, the previous fma had the layout wrong - __m256d f_x = _mm256_fmadd_pd(r_ab2_x, sm_r_ab2, _mm256_mul_pd(r_ab_x, sm_r_ab)); // # 8 MULTs, 4 ADDs - __m256d f_y = _mm256_fmadd_pd(r_ab2_y, sm_r_ab2, _mm256_mul_pd(r_ab_y, sm_r_ab)); // # 8 MULTs, 4 ADDs - - // w_val = dt_neg by default, c_neg_times_dt when (a >= 0 && a*a > b_sq) - __m256d a = _mm256_mul_pd(_mm256_fmadd_pd(eix, f_x, _mm256_mul_pd(eiy, f_y)), v_cos_phi_inv); // # 12 MULTs, 4 ADDs - __m256d b_sq = _mm256_fmadd_pd(f_x, f_x, _mm256_mul_pd(f_y, f_y)); // # 8 MULTs, 4 ADDs - __m256d a_sq = _mm256_mul_pd(a, a); // # 4 MULTs - - __m256d c1 = _mm256_cmp_pd(a, v_zero, _CMP_GE_OQ); - __m256d c2 = _mm256_cmp_pd(a_sq, b_sq, _CMP_GT_OQ); - __m256d cond = _mm256_and_pd(c1, c2); - __m256d w_val = _mm256_blendv_pd(v_dt_neg, v_c_neg_dt, cond); - - // zero out inactive lanes (i==j and padding) before accumulating. - // AND with all-zero mask = 0, AND with all-one mask passes through. cheaper than blendv here. - __m256d f_x_safe = _mm256_and_pd(f_x, active); // bitwise, no flop - __m256d f_y_safe = _mm256_and_pd(f_y, active); // bitwise, no flop - acc_x = _mm256_fmadd_pd(f_x_safe, w_val, acc_x); // # 4 MULTs, 4 ADDs - acc_y = _mm256_fmadd_pd(f_y_safe, w_val, acc_y); // # 4 MULTs, 4 ADDs - } - - // horizontal sum acc_x, acc_y into the scalar f_alpha_dt - __m256d hsum_xy = _mm256_hadd_pd(acc_x, acc_y); // [x0+x1, y0+y1, x2+x3, y2+y3] // # 4 ADDs - __m128d lo = _mm256_castpd256_pd128(hsum_xy); - __m128d hi = _mm256_extractf128_pd(hsum_xy, 1); - __m128d sum_xy = _mm_add_pd(lo, hi); // [x_total, y_total] // # 2 ADDs - alignas(16) double sum_out[2]; - _mm_store_pd(sum_out, sum_xy); - f_alpha_dt_x += sum_out[0]; // # 1 ADD - f_alpha_dt_y += sum_out[1]; // # 1 ADD - - for (int k = 0; k < board.n_obstacles; k++) { - - double v1_x = pos_x[i] - board.obstacles[k].start.x; // # 1 ADD - double v1_y = pos_y[i] - board.obstacles[k].start.y; // # 1 ADD - - double projection = (v1_x * board.obstacles[k].obstacle_v.x + v1_y * board.obstacles[k].obstacle_v.y) * board.obstacles[k].length_sq_inv; // # 3 MULTs, 1 ADD - - if (projection < 0.0) - projection = 0.0; - else if (projection > 1.0) - projection = 1.0; - - double r_aB_x = pos_x[i] - (board.obstacles[k].start.x + board.obstacles[k].obstacle_v.x * projection); // # 1 MULT, 2 ADDs - double r_aB_y = pos_y[i] - (board.obstacles[k].start.y + board.obstacles[k].obstacle_v.y * projection); // # 1 MULT, 2 ADDs - - double r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); // # 2 MULTs, 1 ADD, 1 SQRT - double scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; // # 2 MULTs, 1 EXP, 1 DIV - double f_alpha_B_neg_x = r_aB_x * scalar_mult; // # 1 MULT - double f_alpha_B_neg_y = r_aB_y * scalar_mult; // # 1 MULT - - double w_val; - double a = (e_x[i] * f_alpha_B_neg_x + e_y[i] * f_alpha_B_neg_y) * cos_phi_inv; // # 3 MULTs, 1 ADD - double b_sq = f_alpha_B_neg_x * f_alpha_B_neg_x + f_alpha_B_neg_y * f_alpha_B_neg_y; // # 2 MULTs, 1 ADD - - w_val = dt_neg; - if (a >= 0 && (a * a > b_sq)) { // # 1 MULT for a*a - w_val = c_neg_times_dt; - } - - double f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; // # 1 MULT - double f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; // # 1 MULT - - f_alpha_dt_x += f_alpha_B_dt_x; // # 1 ADD - f_alpha_dt_y += f_alpha_B_dt_y; // # 1 ADD - } - - w_x[i] += f_alpha_dt_x; // # 1 ADD - w_y[i] += f_alpha_dt_y; // # 1 ADD - } - - for (int i = 0; i < n_p; i++) { - - double w_norm = sqrt(w_x[i] * w_x[i] + w_y[i] * w_y[i]); // # 2 MULTs, 1 ADD, 1 SQRT - - double correction_factor = min(1.0, v_max[i] / w_norm); // # 1 DIV - - curr_vel_x[i] = w_x[i] * correction_factor; // # 1 MULT - curr_vel_y[i] = w_y[i] * correction_factor; // # 1 MULT - - pos_x[i] = pos_x[i] + curr_vel_x[i] * dt; // # 1 MULT, 1 ADD - pos_y[i] = pos_y[i] + curr_vel_y[i] * dt; // # 1 MULT, 1 ADD - - if (color[i] == 0 && pos_x[i] > (BOARD_LENGTH - 1.5)) { - pos_x[i] = 1.0; - destination_y[i] = pos_y[i]; - w_x[i] = desired_v0[i]; - w_y[i] = 0.0; - curr_vel_x[i] = w_x[i]; - curr_vel_y[i] = w_y[i]; - } - if (color[i] == 1 && pos_x[i] < 1.5) { - pos_x[i] = BOARD_LENGTH - 1.0; - destination_y[i] = pos_y[i]; - w_x[i] = -desired_v0[i]; - w_y[i] = 0.0; - curr_vel_x[i] = w_x[i]; - curr_vel_y[i] = w_y[i]; - } - - pos_y[i] = clamp(pos_y[i], WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - - double ex = destination_x[i] - pos_x[i]; // # 1 ADD - double ey = destination_y[i] - pos_y[i]; // # 1 ADD - - double e_norm_inv = 1.0 / sqrt(ex * ex + ey * ey); // # 2 MULTs, 1 ADD, 1 SQRT, 1 DIV - - e_x[i] = ex * e_norm_inv; // # 1 MULT - e_y[i] = ey * e_norm_inv; // # 1 MULT - - double velocity_norm_sq = curr_vel_x[i] * curr_vel_x[i] + curr_vel_y[i] * curr_vel_y[i]; // # 2 MULTs, 1 ADD - - double velocity_norm = sqrt(velocity_norm_sq); // # 1 SQRT - - sb_sq[i] = velocity_norm_sq * delta_t_sq; // # 1 MULT - - sb_e_x[i] = e_x[i] * (velocity_norm * delta_t); // # 2 MULTs (vel_norm*delta_t shared with next line) - sb_e_y[i] = e_y[i] * (velocity_norm * delta_t); // # 1 MULT - -#if !BENCHMARK - if (dump_path && (t % dump_interval == 0)) { - samples.emplace_back(t + 1, i, pos_x[i], pos_y[i], e_x[i], e_y[i], color[i]); - } -#endif - } - } - -#if !BENCHMARK - if (dump_path) { - ofstream out(dump_path); - out << "time,id,x,y,p.e.x,p.e.y,color\n"; - - for (auto &[t, id, x, y, e_x, e_y, c] : samples) { - out << t << ',' << id << ',' << x << ',' << y << ',' << e_x << ',' << e_y << ',' << c << '\n'; - } - } -#endif - - return 0; -} diff --git a/variants/variant_inlining_7_symmetry_1_flopcount.cpp b/variants/variant_inlining_7_symmetry_1_flopcount.cpp deleted file mode 100644 index b0888a8..0000000 --- a/variants/variant_inlining_7_symmetry_1_flopcount.cpp +++ /dev/null @@ -1,423 +0,0 @@ -// # Use symmetrical properties to reduce flop count -// # Changes: flopcount -// FLOPCOUNT = n_iter * ( 69 * n_p ** 2 - 32 * n_p + 63 * n_obstacles * n_p ) -// n_iter * [ n_p ** 2 * (12.5 ADD + 23 MULT + 1 DIV + 1 EXP + 2.5 SQRT) + n_p * (- 1.5 ADD + 0.5 SQRT - 2 MULT - 1 EXP + 1 DIV) + n_obstacles * n_p * (12 ADD + 19 MULT + 1 SQRT + 1 DIV + 1 EXP) ] -// # Predecessor: variant_inlining_7_symmetry_1.cpp - -#include "../headers/board.hpp" -#include "../headers/constants.hpp" -#include "../headers/pedestrian_reduced.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - -#define SEED 42 -#define BOARD_WIDTH 10.0 -#define BOARD_LENGTH 50.0 -#define WALL_EPS 1e-3 -#define BOARD_WIDTH_MINUS_WALL_EPS 9.999 - -#ifndef RANDOM_SEED -#define RANDOM_SEED 0 -#endif - -#ifndef BENCHMARK -#define BENCHMARK 0 -#endif - -using namespace std; - -Pedestrian *init_pedestrians(int n_p) { -#if RANDOM_SEED - random_device rd; - mt19937 gen(rd()); -#else - mt19937 gen(SEED); -#endif - - normal_distribution velocity_gen(v0_mean, v0_std_dev); - uniform_real_distribution y_gen(0.3, BOARD_WIDTH - 0.3); - uniform_real_distribution x_gen_left(2.0, BOARD_LENGTH / 2.0); - uniform_real_distribution x_gen_right(BOARD_LENGTH / 2.0, BOARD_LENGTH - 2.0); - - Pedestrian *P = new Pedestrian[n_p]; - - int n_p_half = n_p / 2; - - for (int i = 0; i < n_p_half; i++) { - double x = x_gen_left(gen); - double y = y_gen(gen); - - double start_pos_x = x; - double start_pos_y = y; - - double destination_x = BOARD_LENGTH + 30.0; - double destination_y = y; - - double init_e_x = destination_x - start_pos_x; - double init_e_y = destination_y - start_pos_y; - double init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - double init_e_unit_x = init_e_x / init_e_norm; - double init_e_unit_y = init_e_y / init_e_norm; - - double desired_v0; - do { - desired_v0 = velocity_gen(gen); - } while (desired_v0 <= 0.1); - - double v_max = 1.3 * desired_v0; - - P[i] = Pedestrian(0, 0, 0, start_pos_x, start_pos_y, init_e_unit_x, init_e_unit_y, v_max, desired_v0, destination_x, destination_y); - } - - for (int i = n_p_half; i < n_p; i++) { - double x = x_gen_right(gen); - double y = y_gen(gen); - - double start_pos_x = x; - double start_pos_y = y; - double destination_x = -30; - double destination_y = y; - - double init_e_x = destination_x - start_pos_x; - double init_e_y = destination_y - start_pos_y; - double init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - double init_e_unit_x = init_e_x / init_e_norm; - double init_e_unit_y = init_e_y / init_e_norm; - - double desired_v0; - do { - desired_v0 = velocity_gen(gen); - } while (desired_v0 <= 0.1); - - double v_max = 1.3 * desired_v0; - - P[i] = Pedestrian(1, 0, 0, start_pos_x, start_pos_y, init_e_unit_x, init_e_unit_y, v_max, desired_v0, destination_x, destination_y); - } - - return P; -} - -Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } - -int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { - -#if BENCHMARK - (void)dump_path; -#endif - -#if !BENCHMARK - const int dump_interval = 1; - - vector> samples; - - if (dump_path) { - samples.reserve(static_cast(n_iter / dump_interval + 1) * n_p); - - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - samples.emplace_back(0, i, p.curr_pos_x, p.curr_pos_y, p.e_x, p.e_y, p.color); - } - } -#endif - - // here we have real (simple) symmetry - std::vector r_ab_x_lut(n_p * n_p, 0.0); - std::vector r_ab_y_lut(n_p * n_p, 0.0); - std::vector r_ab_norm_lut(n_p * n_p, 0.0); - // use NAME[i * n_p + j] - - // FLOPCOUNT = n_iter * ( {0.5 * (n_p * n_p - n_p) * 6 FLOPS} + {n_p * [ (8 FLOPS) + ((n_p - 1) * 66 FLOPS) + (n_obstacles * 63 FLOPS) ]} + {n_p * 29 FLOPS} ) - // FLOPCOUNT = n_iter * ( {3 * n_p ** 2 - 3 * n_p} + {66 * n_p ** 2 - 58 * n_p + 63 * n_obstacles * n_p} + {29 * n_p} ) - // FLOPCOUNT = n_iter * ( 3 * n_p ** 2 - 3 * n_p + 66 * n_p ** 2 - 58 * n_p + 63 * n_obstacles * n_p + 29 * n_p) - // FLOPCOUNT = n_iter * ( [3 * n_p ** 2 + 66 * n_p ** 2] + [- 3 * n_p - 58 * n_p + 29 * n_p] + [63 * n_obstacles * n_p] ) - // FLOPCOUNT = n_iter * ( 69 * n_p ** 2 - 32 * n_p + 63 * n_obstacles * n_p ) - - // n_iter * {0.5 * (n_p * n_p - n_p) * (3 ADD + 1 SQRT + 2 MULT) + n_p * [(4 MULT + 4 ADD) + ((n_p - 1) * (11 ADD + 22 MULT + 1 DIV + 1 EXP + 2 SQRT)) + (n_obstacles * (12 ADD + 19 MULT + 1 SQRT + 1 DIV + 1 EXP))] + n_p * [ 7 ADD + 17 MULT + 3 SQRT + 2 DIV ]} - - - - // 0.5 * (n_p * n_p - n_p) * (3 ADD + 1 SQRT + 2 MULT) - // n_p ** 2 * (1.5 ADD + 0.5 SQRT + 1 MULT) + n_p * (- 1.5 ADD - 0.5 SQRT - 1 MULT) - - - - // n_p * [(4 MULT + 4 ADD) + ((n_p - 1) * (11 ADD + 22 MULT + 1 DIV + 1 EXP + 2 SQRT)) + (n_obstacles * (12 ADD + 19 MULT + 1 SQRT + 1 DIV + 1 EXP))] - // n_p * [n_p * (11 ADD + 22 MULT + 1 DIV + 1 EXP + 2 SQRT) - 1 * (7 ADD + 18 MULT + 1 DIV + 1 EXP + 2 SQRT) + n_obstacles * (12 ADD + 19 MULT + 1 SQRT + 1 DIV + 1 EXP)] - // n_p ** 2 * (11 ADD + 22 MULT + 1 DIV + 1 EXP + 2 SQRT) - n_p * (7 ADD + 18 MULT + 1 DIV + 1 EXP + 2 SQRT) + n_obstacles * n_p * (12 ADD + 19 MULT + 1 SQRT + 1 DIV + 1 EXP) - - - - // n_p * (7 ADD + 17 MULT + 3 SQRT + 2 DIV) - - - - // n_p ** 2 * (1.5 ADD + 0.5 SQRT + 1 MULT) + n_p * (- 1.5 ADD - 0.5 SQRT - 1 MULT) + n_p ** 2 * (11 ADD + 22 MULT + 1 DIV + 1 EXP + 2 SQRT) - n_p * (7 ADD + 18 MULT + 1 DIV + 1 EXP + 2 SQRT) + n_obstacles * n_p * (12 ADD + 19 MULT + 1 SQRT + 1 DIV + 1 EXP) + n_p * (7 ADD + 17 MULT + 3 SQRT + 2 DIV) - // n_p ** 2 * (12.5 ADD + 23 MULT + 1 DIV + 1 EXP + 2.5 SQRT) + n_p * (- 1.5 ADD + 0.5 SQRT - 2 MULT - 1 EXP + 1 DIV) + n_obstacles * n_p * (12 ADD + 19 MULT + 1 SQRT + 1 DIV + 1 EXP) - // n_p ** 2 * (12.5 A + 23 M + 1 D + 1 E + 2.5 S) + n_p * (- 1.5 A + 0.5 S - 2 M - 1 E + 1 D) + n_obstacles * n_p * (12 A + 19 M + 1 S + 1 D + 1 E) - - for (int t = 0; t < n_iter; t++) { - - // get all distances first - // total iterations = 0.5 * (n_p * n_p - n_p) - // flops per iter = 6 FLOPS - // FLOPCOUNT = 0.5 * (n_p * n_p - n_p) * 6 FLOPS - // 0.5 * (n_p * n_p - n_p) * (3 ADD + 1 SQRT + 2 MULT) - for (int i = 0; i < n_p; i++) { - for (int j = i + 1; j < n_p; j++) { - // 1 FLOP = 1 ADD - double dx = pedestrians[i].curr_pos_x - pedestrians[j].curr_pos_x; - // 1 FLOP = 1 ADD - double dy = pedestrians[i].curr_pos_y - pedestrians[j].curr_pos_y; - // 4 FLOPS = 1 SQRT + 2 MULT + 1 ADD - double norm = sqrt(dx * dx + dy * dy); - r_ab_x_lut[i * n_p + j] = dx; - r_ab_y_lut[i * n_p + j] = dy; - r_ab_norm_lut[i * n_p + j] = norm; - } - } - - // FLOPCOUNT = n_p * [ (8 FLOPS) + ((n_p - 1) * 66 FLOPS) + (n_obstacles * 63 FLOPS) ] - // n_p * [(4 MULT + 4 ADD) + ((n_p - 1) * (11 ADD + 22 MULT + 1 DIV + 1 EXP + 2 SQRT)) + (n_obstacles * (12 ADD + 19 MULT + 1 SQRT + 1 DIV + 1 EXP))] - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - - // 1 FLOP = 1 MULT - double desired_velocity_x = p.e_x * p.desired_v0; - // 1 FLOP = 1 MULT - double desired_velocity_y = p.e_y * p.desired_v0; - - // 2 FLOPS = 1 ADD + 1 MULT - double f_alpha_dt_x = (desired_velocity_x - p.curr_vel_x) * dt_times_tau_alpha_inv; - // 2 FLOPS = 1 ADD + 1 MULT - double f_alpha_dt_y = (desired_velocity_y - p.curr_vel_y) * dt_times_tau_alpha_inv; - - // force between pedestrians - // FLOPS = ((n_p - 1) * 66 FLOPS) - for (int j = 0; j < n_p; j++) { - if (i == j) - continue; - - // symmetry - //double r_ab_x = p.curr_pos_x - pedestrians[j].curr_pos_x; - //double r_ab_y = p.curr_pos_y - pedestrians[j].curr_pos_y; - //double r_ab_norm = sqrt(r_ab_x * r_ab_x + r_ab_y * r_ab_y); - double r_ab_x, r_ab_y, r_ab_norm; - if (i < j) { - r_ab_x = r_ab_x_lut[i * n_p + j]; - r_ab_y = r_ab_y_lut[i * n_p + j]; - r_ab_norm = r_ab_norm_lut[i * n_p + j]; - } else { - // other direction - r_ab_x = -1 * r_ab_x_lut[j * n_p + i]; - r_ab_y = -1 * r_ab_y_lut[j * n_p + i]; - r_ab_norm = r_ab_norm_lut[j * n_p + i]; - } - - // ---- - - // 1 FLOP = 1 ADD - double r_ab2_x = r_ab_x - pedestrians[j].s_b_e_x; - // 1 FLOP = 1 ADD - double r_ab2_y = r_ab_y - pedestrians[j].s_b_e_y; - - // 4 FLOPS = 1 SQRT + 2 MULT + 1 ADD - double r_ab2_norm = sqrt(r_ab2_x * r_ab2_x + r_ab2_y * r_ab2_y); - - // 1 FLOP = 1 ADD - double r_ab_norm_sum = r_ab_norm + r_ab2_norm; - - // 2 FLOPS = 1 MULT + 1 ADD - double two_b_sq = r_ab_norm_sum * r_ab_norm_sum - pedestrians[j].s_b_sq; - - // 1 FLOP = 1 SQRT - double two_b = sqrt(two_b_sq); - - // 36 FLOPS = 1 DIV + 5 MULTS + 1 EXP - double scalar_mult_common = (r_ab_norm_sum / (two_b * r_ab_norm * r_ab2_norm)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b * NEG_TWO_SIGMA_INV)); - - // 1 FLOP = 1 MULT - double scalar_mult_r_ab = scalar_mult_common * r_ab2_norm; - - // 1 FLOP = 1 MULT - double scalar_mult_r_ab2 = scalar_mult_common * r_ab_norm; - - // 3 FLOPS = 2 MULT + 1 ADD - double f_alpha_beta_neg_x = r_ab_x * scalar_mult_r_ab + r_ab2_x * scalar_mult_r_ab2; - // 3 FLOPS = 2 MULT + 1 ADD - double f_alpha_beta_neg_y = r_ab_y * scalar_mult_r_ab + r_ab2_y * scalar_mult_r_ab2; - - double w_val; - // 4 FLOPS = 3 MULT + 1 ADD - double a = (p.e_x * f_alpha_beta_neg_x + p.e_y * f_alpha_beta_neg_y) * cos_phi_inv; - // 3 FLOPS = 2 MULT + 1 ADD - double b_sq = f_alpha_beta_neg_x * f_alpha_beta_neg_x + f_alpha_beta_neg_y * f_alpha_beta_neg_y; - - w_val = dt_neg; - // 1 FLOP = 1 MULT - if (a >= 0 && (a * a > b_sq)) { - w_val = c_neg_times_dt; - } - - // 2 FLOPS = 1 ADD + 1 MULT - f_alpha_dt_x = f_alpha_dt_x + f_alpha_beta_neg_x * w_val; - // 2 FLOPS = 1 ADD + 1 MULT - f_alpha_dt_y = f_alpha_dt_y + f_alpha_beta_neg_y * w_val; - } - - // force between pedestrian and obstacles - // FLOPS = n_obstacles * 63 FLOPS - for (int k = 0; k < board.n_obstacles; k++) { - - // 1 FLOP = 1 ADD - double v1_x = p.curr_pos_x - board.obstacles[k].start.x; - // 1 FLOP = 1 ADD - double v1_y = p.curr_pos_y - board.obstacles[k].start.y; - - // 4 FLOPS = 3 MULT + 1 ADD - double projection = (v1_x * board.obstacles[k].obstacle_v.x + v1_y * board.obstacles[k].obstacle_v.y) * board.obstacles[k].length_sq_inv; - - if (projection < 0.0) - projection = 0.0; - else if (projection > 1.0) - projection = 1.0; - - // 3 FLOPS = 1 MULT + 2 ADD - double r_aB_x = p.curr_pos_x - (board.obstacles[k].start.x + board.obstacles[k].obstacle_v.x * projection); - // 3 FLOPS = 1 MULT + 2 ADD - double r_aB_y = p.curr_pos_y - (board.obstacles[k].start.y + board.obstacles[k].obstacle_v.y * projection); - - // 4 FLOPS = 1 SQRT + 2 MULT + 1 ADD - double r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); - // 33 FLOPS = 2 MULT + 1 DIV + 1 EXP - double scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; - // 1 FLOP = 1 MULT - double f_alpha_B_neg_x = r_aB_x * scalar_mult; - // 1 FLOP = 1 MULT - double f_alpha_B_neg_y = r_aB_y * scalar_mult; - - double w_val; - // 4 FLOPS = 3 MULTS + 1 ADD - double a = (p.e_x * f_alpha_B_neg_x + p.e_y * f_alpha_B_neg_y) * cos_phi_inv; - // 3 FLOPS = 2 MULT + 1 ADD - double b_sq = f_alpha_B_neg_x * f_alpha_B_neg_x + f_alpha_B_neg_y * f_alpha_B_neg_y; - - w_val = dt_neg; - // 1 FLOP = 1 MULT - if (a >= 0 && (a * a > b_sq)) { - w_val = c_neg_times_dt; - } - - // 1 FLOP = 1 MULT - double f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; - // 1 FLOP = 1 MULT - double f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; - - // 1 FLOP = 1 ADD - f_alpha_dt_x += f_alpha_B_dt_x; - // 1 FLOP = 1 ADD - f_alpha_dt_y += f_alpha_B_dt_y; - } - - // 1 FLOP = 1 ADD - p.w_x += f_alpha_dt_x; - // 1 FLOP = 1 ADD - p.w_y += f_alpha_dt_y; - } - - // update the positions etc. - // FLOPCOUNT = n_p * 29 FLOPS - // n_p * [ 7 ADD + 17 MULT + 3 SQRT + 2 DIV ] - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - - // 4 FLOPS = 1 SQRT + 2 MULT + 1 ADD - double w_norm = sqrt(p.w_x * p.w_x + p.w_y * p.w_y); - - // TODO: check correctness of this - // 1 FLOP = 1 DIV - double correction_factor = min(1.0, p.v_max / w_norm); - - // 1 FLOP = 1 MULT - p.curr_vel_x = p.w_x * correction_factor; - // 1 FLOP = 1 MULT - p.curr_vel_y = p.w_y * correction_factor; - - // 2 FLOPS = 1 ADD + 1 MULT - p.curr_pos_x = p.curr_pos_x + p.curr_vel_x * dt; - // 2 FLOPS = 1 ADD + 1 MULT - p.curr_pos_y = p.curr_pos_y + p.curr_vel_y * dt; - - if (p.color == 0 && p.curr_pos_x > (BOARD_LENGTH - 1.5)) { - p.curr_pos_x = 1.0; - p.destination_y = p.curr_pos_y; - p.w_x = p.desired_v0; - p.w_y = 0.0; - p.curr_vel_x = p.w_x; - p.curr_vel_y = p.w_y; - } - if (p.color == 1 && p.curr_pos_x < 1.5) { - p.curr_pos_x = BOARD_LENGTH - 1.0; - p.destination_y = p.curr_pos_y; - p.w_x = -p.desired_v0; - p.w_y = 0.0; - p.curr_vel_x = p.w_x; - p.curr_vel_y = p.w_y; - } - - p.curr_pos_y = clamp(p.curr_pos_y, WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - - // 1 FLOP = 1 ADD - double e_x = p.destination_x - p.curr_pos_x; - // 1 FLOP = 1 ADD - double e_y = p.destination_y - p.curr_pos_y; - - // 5 FLOPS = 1 DIV + 1 SQRT + 2 MULT + 1 ADD - double e_norm_inv = 1.0 / sqrt(e_x * e_x + e_y * e_y); - - // 1 FLOP = 1 MULT - p.e_x = e_x * e_norm_inv; - // 1 FLOP = 1 MULT - p.e_y = e_y * e_norm_inv; - - // 3 FLOPS = 2 MULT + 1 ADD - double velocity_norm_sq = p.curr_vel_x * p.curr_vel_x + p.curr_vel_y * p.curr_vel_y; - - // 1 FLOP = 1 SQRT - double velocity_norm = sqrt(velocity_norm_sq); - - // 1 FLOP = 1 MULT - p.s_b_sq = velocity_norm_sq * delta_t_sq; - - // 2 FLOPS = 2 MULT - p.s_b_e_x = p.e_x * (velocity_norm * delta_t); - // 2 FLOP = 2 MULT - p.s_b_e_y = p.e_y * (velocity_norm * delta_t); - -#if !BENCHMARK - if (dump_path && (t % dump_interval == 0)) { - samples.emplace_back(t + 1, i, p.curr_pos_x, p.curr_pos_y, p.e_x, p.e_y, p.color); - } -#endif - } - } - -#if !BENCHMARK - if (dump_path) { - ofstream out(dump_path); - out << "time,id,x,y,p.e.x,p.e.y,color\n"; - - for (auto &[t, id, x, y, e_x, e_y, c] : samples) { - out << t << ',' << id << ',' << x << ',' << y << ',' << e_x << ',' << e_y << ',' << c << '\n'; - } - } -#endif - - return 0; -} diff --git a/variants/variant_inlining_7_symmetry_2_flopcount.cpp b/variants/variant_inlining_7_symmetry_2_flopcount.cpp deleted file mode 100644 index a6740c9..0000000 --- a/variants/variant_inlining_7_symmetry_2_flopcount.cpp +++ /dev/null @@ -1,385 +0,0 @@ -// # Use symmetrical properties to reduce flop count -// # Changes: flopcount -// FLOPCOUNT = n_iter * ( 69 * n_p ** 2 - 32 * n_p + 63 * n_obstacles * n_p ) -// n_iter * [ n_p ** 2 * (12.5 ADD + 23 MULT + 1 DIV + 1 EXP + 2.5 SQRT) + n_p * (- 1.5 ADD + 0.5 SQRT - 2 MULT - 1 EXP + 1 DIV) + n_obstacles * n_p * (12 ADD + 19 MULT + 1 SQRT + 1 DIV + 1 EXP) ] -// # Predecessor: variant_inlining_7_symmetry_2.cpp - -#include "../headers/board.hpp" -#include "../headers/constants.hpp" -#include "../headers/pedestrian_reduced.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - -#define SEED 42 -#define BOARD_WIDTH 10.0 -#define BOARD_LENGTH 50.0 -#define WALL_EPS 1e-3 -#define BOARD_WIDTH_MINUS_WALL_EPS 9.999 - -#ifndef RANDOM_SEED -#define RANDOM_SEED 0 -#endif - -#ifndef BENCHMARK -#define BENCHMARK 0 -#endif - -using namespace std; - -Pedestrian *init_pedestrians(int n_p) { -#if RANDOM_SEED - random_device rd; - mt19937 gen(rd()); -#else - mt19937 gen(SEED); -#endif - - normal_distribution velocity_gen(v0_mean, v0_std_dev); - uniform_real_distribution y_gen(0.3, BOARD_WIDTH - 0.3); - uniform_real_distribution x_gen_left(2.0, BOARD_LENGTH / 2.0); - uniform_real_distribution x_gen_right(BOARD_LENGTH / 2.0, BOARD_LENGTH - 2.0); - - Pedestrian *P = new Pedestrian[n_p]; - - int n_p_half = n_p / 2; - - for (int i = 0; i < n_p_half; i++) { - double x = x_gen_left(gen); - double y = y_gen(gen); - - double start_pos_x = x; - double start_pos_y = y; - - double destination_x = BOARD_LENGTH + 30.0; - double destination_y = y; - - double init_e_x = destination_x - start_pos_x; - double init_e_y = destination_y - start_pos_y; - double init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - double init_e_unit_x = init_e_x / init_e_norm; - double init_e_unit_y = init_e_y / init_e_norm; - - double desired_v0; - do { - desired_v0 = velocity_gen(gen); - } while (desired_v0 <= 0.1); - - double v_max = 1.3 * desired_v0; - - P[i] = Pedestrian(0, 0, 0, start_pos_x, start_pos_y, init_e_unit_x, init_e_unit_y, v_max, desired_v0, destination_x, destination_y); - } - - for (int i = n_p_half; i < n_p; i++) { - double x = x_gen_right(gen); - double y = y_gen(gen); - - double start_pos_x = x; - double start_pos_y = y; - double destination_x = -30; - double destination_y = y; - - double init_e_x = destination_x - start_pos_x; - double init_e_y = destination_y - start_pos_y; - double init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - double init_e_unit_x = init_e_x / init_e_norm; - double init_e_unit_y = init_e_y / init_e_norm; - - double desired_v0; - do { - desired_v0 = velocity_gen(gen); - } while (desired_v0 <= 0.1); - - double v_max = 1.3 * desired_v0; - - P[i] = Pedestrian(1, 0, 0, start_pos_x, start_pos_y, init_e_unit_x, init_e_unit_y, v_max, desired_v0, destination_x, destination_y); - } - - return P; -} - -Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } - -int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { - -#if BENCHMARK - (void)dump_path; -#endif - -#if !BENCHMARK - const int dump_interval = 1; - - vector> samples; - - if (dump_path) { - samples.reserve(static_cast(n_iter / dump_interval + 1) * n_p); - - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - samples.emplace_back(0, i, p.curr_pos_x, p.curr_pos_y, p.e_x, p.e_y, p.color); - } - } -#endif - - // here we have real (simple) symmetry - std::vector r_ab_x_lut(n_p * n_p, 0.0); - std::vector r_ab_y_lut(n_p * n_p, 0.0); - std::vector r_ab_norm_lut(n_p * n_p, 0.0); - // use NAME[i * n_p + j] - - // FLOPCOUNT = n_iter * ( {0.5 * (n_p * n_p - n_p) * 6 FLOPS} + {n_p * [ (8 FLOPS) + ((n_p - 1) * 66 FLOPS) + (n_obstacles * 63 FLOPS) ]} + {n_p * 29 FLOPS} ) - // FLOPCOUNT = n_iter * ( {3 * n_p ** 2 - 3 * n_p} + {66 * n_p ** 2 - 58 * n_p + 63 * n_obstacles * n_p} + {29 * n_p} ) - // FLOPCOUNT = n_iter * ( 3 * n_p ** 2 - 3 * n_p + 66 * n_p ** 2 - 58 * n_p + 63 * n_obstacles * n_p + 29 * n_p) - // FLOPCOUNT = n_iter * ( [3 * n_p ** 2 + 66 * n_p ** 2] + [- 3 * n_p - 58 * n_p + 29 * n_p] + [63 * n_obstacles * n_p] ) - // FLOPCOUNT = n_iter * ( 69 * n_p ** 2 - 32 * n_p + 63 * n_obstacles * n_p ) - for (int t = 0; t < n_iter; t++) { - - // get all distances first - // FLOPCOUNT = 0.5 * (n_p * n_p - n_p) * 6 FLOPS - for (int i = 0; i < n_p; i++) { - for (int j = i + 1; j < n_p; j++) { - // 1 FLOP = 1 ADD - double dx = pedestrians[i].curr_pos_x - pedestrians[j].curr_pos_x; - // 1 FLOP = 1 ADD - double dy = pedestrians[i].curr_pos_y - pedestrians[j].curr_pos_y; - // 4 FLOPS = 1 SQRT + 2 MULT + 1 ADD - double norm = sqrt(dx * dx + dy * dy); - int idx = i * n_p + j; - r_ab_x_lut[idx] = dx; - r_ab_y_lut[idx] = dy; - r_ab_norm_lut[idx] = norm; - } - } - - // FLOPCOUNT = n_p * [ 8 FLOPS + (((n_p - 1) * 66 FLOPS)) + (n_obstacles * 63 FLOPS) ] - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - - // 1 FLOP = 1 MULT - double desired_velocity_x = p.e_x * p.desired_v0; - // 1 FLOP = 1 MULT - double desired_velocity_y = p.e_y * p.desired_v0; - - // 2 FLOPS = 1 ADD + 1 MULT - double f_alpha_dt_x = (desired_velocity_x - p.curr_vel_x) * dt_times_tau_alpha_inv; - // 2 FLOPS = 1 ADD + 1 MULT - double f_alpha_dt_y = (desired_velocity_y - p.curr_vel_y) * dt_times_tau_alpha_inv; - - // force between pedestrians --> no symmetry because of different accellerations - // FLOPCOUNT = (((n_p - 1) * 66 FLOPS)) - for (int j = 0; j < n_p; j++) { - if (i == j) - continue; - - // symmetry - double r_ab_x, r_ab_y, r_ab_norm; - if (i < j) { - r_ab_x = r_ab_x_lut[i * n_p + j]; - r_ab_y = r_ab_y_lut[i * n_p + j]; - r_ab_norm = r_ab_norm_lut[i * n_p + j]; - } else { - // other direction - r_ab_x = -1 * r_ab_x_lut[j * n_p + i]; - r_ab_y = -1 * r_ab_y_lut[j * n_p + i]; - r_ab_norm = r_ab_norm_lut[j * n_p + i]; - } - - // ---- - - // 1 FLOP = 1 ADD - double r_ab2_x = r_ab_x - pedestrians[j].s_b_e_x; - // 1 FLOP = 1 ADD - double r_ab2_y = r_ab_y - pedestrians[j].s_b_e_y; - - // 4 FLOPS = 1 SQRT + 2 MULT + 1 ADD - double r_ab2_norm = sqrt(r_ab2_x * r_ab2_x + r_ab2_y * r_ab2_y); - // 1 FLOP = 1 ADD - double r_ab_norm_sum = r_ab_norm + r_ab2_norm; - // 2 FLOPS = 1 MULT + 1 ADD - double two_b_sq = r_ab_norm_sum * r_ab_norm_sum - pedestrians[j].s_b_sq; - // 1 FLOP = 1 SQRT - double two_b = sqrt(two_b_sq); - // 36 FLOPS = 1 DIV + 5 MULT + 1 EXP - double scalar_mult_common = (r_ab_norm_sum / (two_b * r_ab_norm * r_ab2_norm)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b * NEG_TWO_SIGMA_INV)); - // 1 FLOP = 1 MULT - double scalar_mult_r_ab = scalar_mult_common * r_ab2_norm; - // 1 FLOP = 1 MULT - double scalar_mult_r_ab2 = scalar_mult_common * r_ab_norm; - - // 3 FLOPS = 2 MULT + 1 ADD - double f_alpha_beta_neg_x = r_ab_x * scalar_mult_r_ab + r_ab2_x * scalar_mult_r_ab2; - // 3 FLOPS = 2 MULT + 1 ADD - double f_alpha_beta_neg_y = r_ab_y * scalar_mult_r_ab + r_ab2_y * scalar_mult_r_ab2; - - double w_val; - // 4 FLOPS = 3 MULT + 1 ADD - double a = (p.e_x * f_alpha_beta_neg_x + p.e_y * f_alpha_beta_neg_y) * cos_phi_inv; - // 3 FLOPS = 2 MULT + 1 ADD - double b_sq = f_alpha_beta_neg_x * f_alpha_beta_neg_x + f_alpha_beta_neg_y * f_alpha_beta_neg_y; - - w_val = dt_neg; - // 1 FLOP = 1 MULT - if (a >= 0 && (a * a > b_sq)) { - w_val = c_neg_times_dt; - } - - // 2 FLOPS = 1 ADD + 1 MULT - f_alpha_dt_x = f_alpha_dt_x + f_alpha_beta_neg_x * w_val; - // 2 FLOPS = 1 ADD + 1 MULT - f_alpha_dt_y = f_alpha_dt_y + f_alpha_beta_neg_y * w_val; - } - - // force between pedestrian and obstacles - // FLOPCOUNT = n_obstacles * 63 FLOPS - for (int k = 0; k < board.n_obstacles; k++) { - - // 1 FLOP = 1 ADD - double v1_x = p.curr_pos_x - board.obstacles[k].start.x; - // 1 FLOP = 1 ADD - double v1_y = p.curr_pos_y - board.obstacles[k].start.y; - - // 4 FLOPS = 3 MULT + 1 ADD - double projection = (v1_x * board.obstacles[k].obstacle_v.x + v1_y * board.obstacles[k].obstacle_v.y) * board.obstacles[k].length_sq_inv; - - if (projection < 0.0) - projection = 0.0; - else if (projection > 1.0) - projection = 1.0; - - // 3 FLOPS = 2 ADD + 1 MULT - double r_aB_x = p.curr_pos_x - (board.obstacles[k].start.x + board.obstacles[k].obstacle_v.x * projection); - // 3 FLOPS = 2 ADD + 1 MULT - double r_aB_y = p.curr_pos_y - (board.obstacles[k].start.y + board.obstacles[k].obstacle_v.y * projection); - - // 4 FLOPS = 1 SQRT + 2 MULT + 1 ADD - double r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); - // 33 FLOPS = 1 EXP + 2 MULT + 1 DIV - double scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; - // 1 FLOP = 1 MULT - double f_alpha_B_neg_x = r_aB_x * scalar_mult; - // 1 FLOP = 1 MULT - double f_alpha_B_neg_y = r_aB_y * scalar_mult; - - double w_val; - // 4 FLOPS = 3 MULT + 1 ADD - double a = (p.e_x * f_alpha_B_neg_x + p.e_y * f_alpha_B_neg_y) * cos_phi_inv; - // 3 FLOPS = 2 MULT + 1 ADD - double b_sq = f_alpha_B_neg_x * f_alpha_B_neg_x + f_alpha_B_neg_y * f_alpha_B_neg_y; - - w_val = dt_neg; - // 1 FLOP = 1 MULT - if (a >= 0 && (a * a > b_sq)) { - w_val = c_neg_times_dt; - } - - // 1 FLOP = 1 MULT - double f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; - // 1 FLOP = 1 MULT - double f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; - - // 1 FLOP = 1 ADD - f_alpha_dt_x += f_alpha_B_dt_x; - // 1 FLOP = 1 ADD - f_alpha_dt_y += f_alpha_B_dt_y; - } - - // 1 FLOP = 1 ADD - p.w_x += f_alpha_dt_x; - // 1 FLOP = 1 ADD - p.w_y += f_alpha_dt_y; - } - - // update the positions etc. - // FLOPCOUNT = n_p * 29 FLOPS - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - - // 4 FLOPS = 1 SQRT + 2 MULT + 1 ADD - double w_norm = sqrt(p.w_x * p.w_x + p.w_y * p.w_y); - - // 1 FLOP = 1 DIV - double correction_factor = min(1.0, p.v_max / w_norm); - - // 1 FLOP = 1 MULT - p.curr_vel_x = p.w_x * correction_factor; - // 1 FLOP = 1 MULT - p.curr_vel_y = p.w_y * correction_factor; - - // 2 FLOPS = 1 MULT + 1 ADD - p.curr_pos_x = p.curr_pos_x + p.curr_vel_x * dt; - // 2 FLOPS = 1 MULT + 1 ADD - p.curr_pos_y = p.curr_pos_y + p.curr_vel_y * dt; - - if (p.color == 0 && p.curr_pos_x > (BOARD_LENGTH - 1.5)) { - p.curr_pos_x = 1.0; - p.destination_y = p.curr_pos_y; - p.w_x = p.desired_v0; - p.w_y = 0.0; - p.curr_vel_x = p.w_x; - p.curr_vel_y = p.w_y; - } - if (p.color == 1 && p.curr_pos_x < 1.5) { - p.curr_pos_x = BOARD_LENGTH - 1.0; - p.destination_y = p.curr_pos_y; - p.w_x = -p.desired_v0; - p.w_y = 0.0; - p.curr_vel_x = p.w_x; - p.curr_vel_y = p.w_y; - } - - p.curr_pos_y = clamp(p.curr_pos_y, WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - - // 1 FLOP = 1 ADD - double e_x = p.destination_x - p.curr_pos_x; - // 1 FLOP = 1 ADD - double e_y = p.destination_y - p.curr_pos_y; - - // 5 FLOPS = 1 DIV + 1 SQRT + 2 MULT + 1 ADD - double e_norm_inv = 1.0 / sqrt(e_x * e_x + e_y * e_y); - - // 1 FLOP = 1 MULT - p.e_x = e_x * e_norm_inv; - // 1 FLOP = 1 MULT - p.e_y = e_y * e_norm_inv; - - // 3 FLOPS = 2 MULT + 1 ADD - double velocity_norm_sq = p.curr_vel_x * p.curr_vel_x + p.curr_vel_y * p.curr_vel_y; - - // 1 FLOP = 1 SQRT - double velocity_norm = sqrt(velocity_norm_sq); - - // 1 FLOP = 1 MULT - p.s_b_sq = velocity_norm_sq * delta_t_sq; - - // 2 FLOPS = 2 MULT - p.s_b_e_x = p.e_x * (velocity_norm * delta_t); - // 2 FLOPS = 2 MULT - p.s_b_e_y = p.e_y * (velocity_norm * delta_t); - -#if !BENCHMARK - if (dump_path && (t % dump_interval == 0)) { - samples.emplace_back(t + 1, i, p.curr_pos_x, p.curr_pos_y, p.e_x, p.e_y, p.color); - } -#endif - } - } - -#if !BENCHMARK - if (dump_path) { - ofstream out(dump_path); - out << "time,id,x,y,p.e.x,p.e.y,color\n"; - - for (auto &[t, id, x, y, e_x, e_y, c] : samples) { - out << t << ',' << id << ',' << x << ',' << y << ',' << e_x << ',' << e_y << ',' << c << '\n'; - } - } -#endif - - return 0; -} diff --git a/variants/variant_inlining_7_symmetry_2_ilp_1_flopcount.cpp b/variants/variant_inlining_7_symmetry_2_ilp_1_flopcount.cpp deleted file mode 100644 index 2e85f45..0000000 --- a/variants/variant_inlining_7_symmetry_2_ilp_1_flopcount.cpp +++ /dev/null @@ -1,633 +0,0 @@ -// # ILP -// # Changes: FLOPCOUNT -// n_iter * [ n_p ** 2 * (12.5 A + 2.5 S + 23 M + 1 D + 1 E) + n_p * (6.5 A + 0.5 S - 2 M + 1 D - 1 E) + n_obstacles * n_p * (12 A + 19 M + 1 S + 1 D + 1 E)] -// # Predecessor: variant_inlining_7_symmetry_2_ilp.cpp - -#include "../headers/board.hpp" -#include "../headers/constants.hpp" -#include "../headers/pedestrian_reduced.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - -#define SEED 42 -#define BOARD_WIDTH 10.0 -#define BOARD_LENGTH 50.0 -#define WALL_EPS 1e-3 -#define BOARD_WIDTH_MINUS_WALL_EPS 9.999 - -#ifndef RANDOM_SEED -#define RANDOM_SEED 0 -#endif - -#ifndef BENCHMARK -#define BENCHMARK 0 -#endif - -using namespace std; - -Pedestrian *init_pedestrians(int n_p) { -#if RANDOM_SEED - random_device rd; - mt19937 gen(rd()); -#else - mt19937 gen(SEED); -#endif - - normal_distribution velocity_gen(v0_mean, v0_std_dev); - uniform_real_distribution y_gen(0.3, BOARD_WIDTH - 0.3); - uniform_real_distribution x_gen_left(2.0, BOARD_LENGTH / 2.0); - uniform_real_distribution x_gen_right(BOARD_LENGTH / 2.0, BOARD_LENGTH - 2.0); - - Pedestrian *P = new Pedestrian[n_p]; - - int n_p_half = n_p / 2; - - for (int i = 0; i < n_p_half; i++) { - double x = x_gen_left(gen); - double y = y_gen(gen); - - double start_pos_x = x; - double start_pos_y = y; - - double destination_x = BOARD_LENGTH + 30.0; - double destination_y = y; - - double init_e_x = destination_x - start_pos_x; - double init_e_y = destination_y - start_pos_y; - double init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - double init_e_unit_x = init_e_x / init_e_norm; - double init_e_unit_y = init_e_y / init_e_norm; - - double desired_v0; - do { - desired_v0 = velocity_gen(gen); - } while (desired_v0 <= 0.1); - - double v_max = 1.3 * desired_v0; - - P[i] = Pedestrian(0, 0, 0, start_pos_x, start_pos_y, init_e_unit_x, init_e_unit_y, v_max, desired_v0, destination_x, destination_y); - } - - for (int i = n_p_half; i < n_p; i++) { - double x = x_gen_right(gen); - double y = y_gen(gen); - - double start_pos_x = x; - double start_pos_y = y; - double destination_x = -30; - double destination_y = y; - - double init_e_x = destination_x - start_pos_x; - double init_e_y = destination_y - start_pos_y; - double init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - double init_e_unit_x = init_e_x / init_e_norm; - double init_e_unit_y = init_e_y / init_e_norm; - - double desired_v0; - do { - desired_v0 = velocity_gen(gen); - } while (desired_v0 <= 0.1); - - double v_max = 1.3 * desired_v0; - - P[i] = Pedestrian(1, 0, 0, start_pos_x, start_pos_y, init_e_unit_x, init_e_unit_y, v_max, desired_v0, destination_x, destination_y); - } - - return P; -} - -Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } - -int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { - -#if BENCHMARK - (void)dump_path; -#endif - -#if !BENCHMARK - const int dump_interval = 1; - - vector> samples; - - if (dump_path) { - samples.reserve(static_cast(n_iter / dump_interval + 1) * n_p); - - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - samples.emplace_back(0, i, p.curr_pos_x, p.curr_pos_y, p.e_x, p.e_y, p.color); - } - } -#endif - - // here we have real (simple) symmetry - std::vector r_ab_x_lut(n_p * n_p, 0.0); - std::vector r_ab_y_lut(n_p * n_p, 0.0); - std::vector r_ab_norm_lut(n_p * n_p, 0.0); - // use NAME[i * n_p + j] - - - - // n_iter * [ 0.5 * (n_p * n_p - n_p) * (3 ADD + 1 SQRT + 2 MULT) + n_p * [ (12 ADD + 4 MULT) + ((n_p - 1) * (11 ADD + 22 MULT + 2 SQRT + 1 DIV + 1 EXP)) ] + n_p * (7 ADD + 17 MULT + 3 SQRT + 2 DIV) + n_obstacles * n_p * (12 ADD + 19 MULT + 1 SQRT + 1 DIV + 1 EXP)] - // n_iter * [ 0.5 * n_p ** 2 * (3 A + 1 S + 2 M) - 0.5 * n_p * (3 A + 1 S + 2 M) + n_p ** 2 * (11 A + 22 M + 2 S + 1 D + 1 E) + n_p * (1 A - 18 M - 2 S - 1 D - 1 E) + n_p * (7 A + 17 M + 3 S + 2 D) + n_obstacles * n_p * (12 A + 19 M + 1 S + 1 D + 1 E)] - // n_iter * [ n_p ** 2 * (1.5 A + 0.5 S + 1 M + 11 A + 22 M + 2 S + 1 D + 1 E) + n_p * (- 1.5 A - 0.5 S - 1 M + 1 A - 18 M - 2 S - 1 D - 1 E + 7 A + 17 M + 3 S + 2 D) + n_obstacles * n_p * (12 A + 19 M + 1 S + 1 D + 1 E)] - // n_iter * [ n_p ** 2 * (12.5 A + 2.5 S + 23 M + 1 D + 1 E) + n_p * (6.5 A + 0.5 S - 2 M + 1 D - 1 E) + n_obstacles * n_p * (12 A + 19 M + 1 S + 1 D + 1 E)] - for (int t = 0; t < n_iter; t++) { - - // get all distances first - // No ILP because no accumulators - // FLOPCOUNT = 0.5 * (n_p * n_p - n_p) * 6 FLOPS - // 0.5 * (n_p * n_p - n_p) * (3 ADD + 1 SQRT + 2 MULT) - for (int i = 0; i < n_p; i++) { - // only upper triangle - for (int j = i + 1; j < n_p; j++) { - // 1 FLOP = 1 ADD - double dx = pedestrians[i].curr_pos_x - pedestrians[j].curr_pos_x; - // 1 FLOP = 1 ADD - double dy = pedestrians[i].curr_pos_y - pedestrians[j].curr_pos_y; - // 4 FLOPS = 1 SQRT + 2 MULT + 1 ADD - double norm = sqrt(dx * dx + dy * dy); - r_ab_x_lut[i * n_p + j] = dx; - r_ab_y_lut[i * n_p + j] = dy; - r_ab_norm_lut[i * n_p + j] = norm; - } - } - - - // FLOPCOUNT = n_p * [ 16 FLOPS + ((n_p - 1) * 66 FLOPS) + (n_obstacles * 63 FLOPS)] - // n_p * [ (12 ADD + 4 MULT) + ((n_p - 1) * (11 ADD + 22 MULT + 2 SQRT + 1 DIV + 1 EXP)) + n_obstacles * (12 ADD + 19 MULT + 1 SQRT + 1 DIV + 1 EXP) ] - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - - // 1 FLOP = 1 MULT - double desired_velocity_x = p.e_x * p.desired_v0; - // 1 FLOP = 1 MULT - double desired_velocity_y = p.e_y * p.desired_v0; - - // 2 FLOPS = 1 ADD + 1 MULT - double f_alpha_dt_x = (desired_velocity_x - p.curr_vel_x) * dt_times_tau_alpha_inv; - // 2 FLOPS = 1 ADD + 1 MULT - double f_alpha_dt_y = (desired_velocity_y - p.curr_vel_y) * dt_times_tau_alpha_inv; - - // accumulators for ILP - // f_alpha_dt_x = f_alpha_dt_x + f_alpha_beta_neg_x * w_val; - // f_alpha_dt_y = f_alpha_dt_y + f_alpha_beta_neg_y * w_val; - double acc_0_x = 0.0, acc_1_x = 0.0, acc_2_x = 0.0, acc_3_x = 0.0; - double acc_0_y = 0.0, acc_1_y = 0.0, acc_2_y = 0.0, acc_3_y = 0.0; - - const double p_e_x = p.e_x; - const double p_e_y = p.e_y; - - - // force between pedestrians --> no symmetry because of different accelerations - // ILP - int j = 0; - // FLOPCOUNT = ((n_p - 1) * 66 FLOPS) - // ((n_p - 1) * (11 ADD + 22 MULT + 2 SQRT + 1 DIV + 1 EXP)) - for (; j <= n_p - 4; j+=4) { - // distance symmetry - double r_ab_x_0, r_ab_y_0, r_ab_norm_0; - double r_ab_x_1, r_ab_y_1, r_ab_norm_1; - double r_ab_x_2, r_ab_y_2, r_ab_norm_2; - double r_ab_x_3, r_ab_y_3, r_ab_norm_3; - - int j0 = j, j1 = j+1, j2 = j+2, j3 = j+3; - - // skip i == j - // FLOPCOUNT = 66 FLOPS - // 11 ADD + 22 MULT + 2 SQRT + 1 DIV + 1 EXP - if (i != j0) { - if (i < j0) { - r_ab_x_0 = r_ab_x_lut[i * n_p + j0]; - r_ab_y_0 = r_ab_y_lut[i * n_p + j0]; - r_ab_norm_0 = r_ab_norm_lut[i * n_p + j0]; - } else { - // other direction - // I think here we can optimize for sure, currently not using LUT good - r_ab_x_0 = -1 * r_ab_x_lut[j0 * n_p + i]; - r_ab_y_0 = -1 * r_ab_y_lut[j0 * n_p + i]; - r_ab_norm_0 = r_ab_norm_lut[j0 * n_p + i]; - } - // the math, see paper - // 1 FLOP = 1 ADD - double r_ab2_x_0 = r_ab_x_0 - pedestrians[j0].s_b_e_x; - // 1 FLOP = 1 ADD - double r_ab2_y_0 = r_ab_y_0 - pedestrians[j0].s_b_e_y; - - // 4 FLOPS = 1 SQRT + 2 MULT + 1 ADD - double r_ab2_norm_0 = sqrt(r_ab2_x_0 * r_ab2_x_0 + r_ab2_y_0 * r_ab2_y_0); - - // 1 FLOP = 1 ADD - double r_ab_norm_sum_0 = r_ab_norm_0 + r_ab2_norm_0; - - // 2 FLOPS = 1 MULT + 1 ADD - double two_b_sq_0 = r_ab_norm_sum_0 * r_ab_norm_sum_0 - pedestrians[j0].s_b_sq; - - // 1 FLOP = 1 SQRT - double two_b_0 = sqrt(two_b_sq_0); - - // 36 FLOPS = 1 DIV + 5 MULT + 1 EXP - double scalar_mult_common_0 = (r_ab_norm_sum_0 / (two_b_0 * r_ab_norm_0 * r_ab2_norm_0)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_0 * NEG_TWO_SIGMA_INV)); - - // 1 FLOP = 1 MULT - double scalar_mult_r_ab_0 = scalar_mult_common_0 * r_ab2_norm_0; - - // 1 FLOP = 1 MULT - double scalar_mult_r_ab2_0 = scalar_mult_common_0 * r_ab_norm_0; - - // 3 FLOPS = 2 MULT + 1 ADD - double f_alpha_beta_neg_x_0 = r_ab_x_0 * scalar_mult_r_ab_0 + r_ab2_x_0 * scalar_mult_r_ab2_0; - - // 3 FLOPS = 2 MULT + 1 ADD - double f_alpha_beta_neg_y_0 = r_ab_y_0 * scalar_mult_r_ab_0 + r_ab2_y_0 * scalar_mult_r_ab2_0; - - double w_val_0; - // 4 FLOPS = 3 MULT + 1 ADD - double a_0 = (p_e_x * f_alpha_beta_neg_x_0 + p_e_y * f_alpha_beta_neg_y_0) * cos_phi_inv; - // 3 FLOPS = 2 MULT + 1 ADD - double b_sq_0 = f_alpha_beta_neg_x_0 * f_alpha_beta_neg_x_0 + f_alpha_beta_neg_y_0 * f_alpha_beta_neg_y_0; - - w_val_0 = dt_neg; - // 1 FLOP = 1 MULT - if (a_0 >= 0 && (a_0 * a_0 > b_sq_0)) { - w_val_0 = c_neg_times_dt; - } - - // 2 FLOPS = 1 ADD + 1 MULT - acc_0_x += f_alpha_beta_neg_x_0 * w_val_0; - // 2 FLOPS = 1 ADD + 1 MULT - acc_0_y += f_alpha_beta_neg_y_0 * w_val_0; - } - - // skip i == j - // FLOPCOUNT= 66 FLOPS - if (i != j1) { - if (i < j1) { - r_ab_x_1 = r_ab_x_lut[i * n_p + j1]; - r_ab_y_1 = r_ab_y_lut[i * n_p + j1]; - r_ab_norm_1 = r_ab_norm_lut[i * n_p + j1]; - } else { - // other direction - // I think here we can optimize for sure, currently not using LUT good - r_ab_x_1 = -1 * r_ab_x_lut[j1 * n_p + i]; - r_ab_y_1 = -1 * r_ab_y_lut[j1 * n_p + i]; - r_ab_norm_1 = r_ab_norm_lut[j1 * n_p + i]; - } - // the math, see paper - // 1 FLOP = 1 ADD - double r_ab2_x_1 = r_ab_x_1 - pedestrians[j1].s_b_e_x; - // 1 FLOP = 1 ADD - double r_ab2_y_1 = r_ab_y_1 - pedestrians[j1].s_b_e_y; - - // 4 FLOPS = 1 SQRT + 2 MULT + 1 ADD - double r_ab2_norm_1 = sqrt(r_ab2_x_1 * r_ab2_x_1 + r_ab2_y_1 * r_ab2_y_1); - - // 1 FLOP = 1 ADD - double r_ab_norm_sum_1 = r_ab_norm_1 + r_ab2_norm_1; - - // 2 FLOPS = 1 MULT + 1 ADD - double two_b_sq_1 = r_ab_norm_sum_1 * r_ab_norm_sum_1 - pedestrians[j1].s_b_sq; - - // 1 FLOP = 1 SQRT - double two_b_1 = sqrt(two_b_sq_1); - - // 36 FLOPS = 1 DIV + 5 MULT + 1 EXP - double scalar_mult_common_1 = (r_ab_norm_sum_1 / (two_b_1 * r_ab_norm_1 * r_ab2_norm_1)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_1 * NEG_TWO_SIGMA_INV)); - double scalar_mult_r_ab_1 = scalar_mult_common_1 * r_ab2_norm_1; - double scalar_mult_r_ab2_1 = scalar_mult_common_1 * r_ab_norm_1; - - // 3 FLOPS = 2 MULT + 1 ADD - double f_alpha_beta_neg_x_1 = r_ab_x_1 * scalar_mult_r_ab_1 + r_ab2_x_1 * scalar_mult_r_ab2_1; - // 3 FLOPS = 2 MULT + 1 ADD - double f_alpha_beta_neg_y_1 = r_ab_y_1 * scalar_mult_r_ab_1 + r_ab2_y_1 * scalar_mult_r_ab2_1; - - double w_val_1; - // 4 FLOPS = 3 MULT + 1 ADD - double a_1 = (p_e_x * f_alpha_beta_neg_x_1 + p_e_y * f_alpha_beta_neg_y_1) * cos_phi_inv; - // 3 FLOPS = 2 MULT + 1 ADD - double b_sq_1 = f_alpha_beta_neg_x_1 * f_alpha_beta_neg_x_1 + f_alpha_beta_neg_y_1 * f_alpha_beta_neg_y_1; - - w_val_1 = dt_neg; - // 1 FLOP = 1 MULT - if (a_1 >= 0 && (a_1 * a_1 > b_sq_1)) { - w_val_1 = c_neg_times_dt; - } - - // 2 FLOPS = 1 MULT + 1 ADD - acc_1_x += f_alpha_beta_neg_x_1 * w_val_1; - // 2 FLOPS = 1 MULT + 1 ADD - acc_1_y += f_alpha_beta_neg_y_1 * w_val_1; - } - - // skip i == j - // FLOPCOUNT = 66 FLOPS - if (i != j2) { - if (i < j2) { - r_ab_x_2 = r_ab_x_lut[i * n_p + j2]; - r_ab_y_2 = r_ab_y_lut[i * n_p + j2]; - r_ab_norm_2 = r_ab_norm_lut[i * n_p + j2]; - } else { - // other direction - // I think here we can optimize for sure, currently not using LUT good - r_ab_x_2 = -1 * r_ab_x_lut[j2 * n_p + i]; - r_ab_y_2 = -1 * r_ab_y_lut[j2 * n_p + i]; - r_ab_norm_2 = r_ab_norm_lut[j2 * n_p + i]; - } - // the math, see paper - double r_ab2_x_2 = r_ab_x_2 - pedestrians[j2].s_b_e_x; - double r_ab2_y_2 = r_ab_y_2 - pedestrians[j2].s_b_e_y; - - double r_ab2_norm_2 = sqrt(r_ab2_x_2 * r_ab2_x_2 + r_ab2_y_2 * r_ab2_y_2); - double r_ab_norm_sum_2 = r_ab_norm_2 + r_ab2_norm_2; - double two_b_sq_2 = r_ab_norm_sum_2 * r_ab_norm_sum_2 - pedestrians[j2].s_b_sq; - double two_b_2 = sqrt(two_b_sq_2); - double scalar_mult_common_2 = (r_ab_norm_sum_2 / (two_b_2 * r_ab_norm_2 * r_ab2_norm_2)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_2 * NEG_TWO_SIGMA_INV)); - double scalar_mult_r_ab_2 = scalar_mult_common_2 * r_ab2_norm_2; - double scalar_mult_r_ab2_2 = scalar_mult_common_2 * r_ab_norm_2; - - double f_alpha_beta_neg_x_2 = r_ab_x_2 * scalar_mult_r_ab_2 + r_ab2_x_2 * scalar_mult_r_ab2_2; - double f_alpha_beta_neg_y_2 = r_ab_y_2 * scalar_mult_r_ab_2 + r_ab2_y_2 * scalar_mult_r_ab2_2; - - double w_val_2; - double a_2 = (p_e_x * f_alpha_beta_neg_x_2 + p_e_y * f_alpha_beta_neg_y_2) * cos_phi_inv; - double b_sq_2 = f_alpha_beta_neg_x_2 * f_alpha_beta_neg_x_2 + f_alpha_beta_neg_y_2 * f_alpha_beta_neg_y_2; - - w_val_2 = dt_neg; - if (a_2 >= 0 && (a_2 * a_2 > b_sq_2)) { - w_val_2 = c_neg_times_dt; - } - - acc_2_x += f_alpha_beta_neg_x_2 * w_val_2; - acc_2_y += f_alpha_beta_neg_y_2 * w_val_2; - } - - // skip i == j - // FLOPCOUNT = 66 FLOPS - if (i != j3) { - if (i < j3) { - r_ab_x_3 = r_ab_x_lut[i * n_p + j3]; - r_ab_y_3 = r_ab_y_lut[i * n_p + j3]; - r_ab_norm_3 = r_ab_norm_lut[i * n_p + j3]; - } else { - // other direction - // I think here we can optimize for sure, currently not using LUT good - r_ab_x_3 = -1 * r_ab_x_lut[j3 * n_p + i]; - r_ab_y_3 = -1 * r_ab_y_lut[j3 * n_p + i]; - r_ab_norm_3 = r_ab_norm_lut[j3 * n_p + i]; - } - // the math, see paper - double r_ab2_x_3 = r_ab_x_3 - pedestrians[j3].s_b_e_x; - double r_ab2_y_3 = r_ab_y_3 - pedestrians[j3].s_b_e_y; - - double r_ab2_norm_3 = sqrt(r_ab2_x_3 * r_ab2_x_3 + r_ab2_y_3 * r_ab2_y_3); - double r_ab_norm_sum_3 = r_ab_norm_3 + r_ab2_norm_3; - double two_b_sq_3 = r_ab_norm_sum_3 * r_ab_norm_sum_3 - pedestrians[j3].s_b_sq; - double two_b_3 = sqrt(two_b_sq_3); - double scalar_mult_common_3 = (r_ab_norm_sum_3 / (two_b_3 * r_ab_norm_3 * r_ab2_norm_3)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_3 * NEG_TWO_SIGMA_INV)); - double scalar_mult_r_ab_3 = scalar_mult_common_3 * r_ab2_norm_3; - double scalar_mult_r_ab2_3 = scalar_mult_common_3 * r_ab_norm_3; - - double f_alpha_beta_neg_x_3 = r_ab_x_3 * scalar_mult_r_ab_3 + r_ab2_x_3 * scalar_mult_r_ab2_3; - double f_alpha_beta_neg_y_3 = r_ab_y_3 * scalar_mult_r_ab_3 + r_ab2_y_3 * scalar_mult_r_ab2_3; - - double w_val_3; - double a_3 = (p_e_x * f_alpha_beta_neg_x_3 + p_e_y * f_alpha_beta_neg_y_3) * cos_phi_inv; - double b_sq_3 = f_alpha_beta_neg_x_3 * f_alpha_beta_neg_x_3 + f_alpha_beta_neg_y_3 * f_alpha_beta_neg_y_3; - - w_val_3 = dt_neg; - if (a_3 >= 0 && (a_3 * a_3 > b_sq_3)) { - w_val_3 = c_neg_times_dt; - } - - acc_3_x += f_alpha_beta_neg_x_3 * w_val_3; - acc_3_y += f_alpha_beta_neg_y_3 * w_val_3; - } - } - - // add the result - // 4 FLOPS = 4 ADD - f_alpha_dt_x += acc_0_x + acc_1_x + acc_2_x + acc_3_x; - // 4 FLOPS = 4 ADD - f_alpha_dt_y += acc_0_y + acc_1_y + acc_2_y + acc_3_y; - - // remaining - // 66 FLOPS --> see ILP loop - // 11 ADD + 22 MULT + 2 SQRT + 1 DIV + 1 EXP - for (; j < n_p; j++) { - if (i == j) continue; - - double r_ab_x, r_ab_y, r_ab_norm; - if (i < j) { - r_ab_x = r_ab_x_lut[i * n_p + j]; - r_ab_y = r_ab_y_lut[i * n_p + j]; - r_ab_norm = r_ab_norm_lut[i * n_p + j]; - } else { - r_ab_x = -1 * r_ab_x_lut[j * n_p + i]; - r_ab_y = -1 * r_ab_y_lut[j * n_p + i]; - r_ab_norm = r_ab_norm_lut[j * n_p + i]; - } - - // 1 FLOP = 1 ADD - double r_ab2_x = r_ab_x - pedestrians[j].s_b_e_x; - // 1 FLOP = 1 ADD - double r_ab2_y = r_ab_y - pedestrians[j].s_b_e_y; - - // 4 FLOPS = 1 SQRT + 2 MULT + 1 ADD - double r_ab2_norm = sqrt(r_ab2_x * r_ab2_x + r_ab2_y * r_ab2_y); - // 1 FLOP = 1 ADD - double r_ab_norm_sum = r_ab_norm + r_ab2_norm; - // 2 FLOPS = 1 MULT + 1 ADD - double two_b_sq = r_ab_norm_sum * r_ab_norm_sum - pedestrians[j].s_b_sq; - // 1 FLOP = 1 SQRT - double two_b = sqrt(two_b_sq); - // 36 FLOPS = 1 DIV + 5 MULT + 1 EXP - double scalar_mult_common = (r_ab_norm_sum / (two_b * r_ab_norm * r_ab2_norm)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b * NEG_TWO_SIGMA_INV)); - // 1 FLOP = 1 MULT - double scalar_mult_r_ab = scalar_mult_common * r_ab2_norm; - // 1 FLOP = 1 MULT - double scalar_mult_r_ab2 = scalar_mult_common * r_ab_norm; - - // 3 FLOPS = 2 MULT + 1 ADD - double f_alpha_beta_neg_x = r_ab_x * scalar_mult_r_ab + r_ab2_x * scalar_mult_r_ab2; - // 3 FLOPS = 2 MULT + 1 ADD - double f_alpha_beta_neg_y = r_ab_y * scalar_mult_r_ab + r_ab2_y * scalar_mult_r_ab2; - - double w_val; - // 4 FLOPS = 3 MULT + 1 ADD - double a = (p_e_x * f_alpha_beta_neg_x + p_e_y * f_alpha_beta_neg_y) * cos_phi_inv; - // 3 FLOPS = 2 MULT + 1 ADD - double b_sq = f_alpha_beta_neg_x * f_alpha_beta_neg_x + f_alpha_beta_neg_y * f_alpha_beta_neg_y; - - w_val = dt_neg; - // 1 FLOP = 1 MULT - if (a >= 0 && (a * a > b_sq)) { - w_val = c_neg_times_dt; - } - - // 2 FLOPS = 1 MULT + 1 ADD - f_alpha_dt_x = f_alpha_dt_x + f_alpha_beta_neg_x * w_val; - // 2 FLOPS = 1 MULT + 1 ADD - f_alpha_dt_y = f_alpha_dt_y + f_alpha_beta_neg_y * w_val; - } - - - // force between pedestrian and obstacles - // initialized with 0 obstacles, might consider deleting this? - // to sparse to use ILP - // FLOPCOUNT = n_obstacles * 63 FLOPS - // n_obstacles * (12 ADD + 19 MULT + 1 SQRT + 1 DIV + 1 EXP) - for (int k = 0; k < board.n_obstacles; k++) { - - // 1 FLOP = 1 ADD - double v1_x = p.curr_pos_x - board.obstacles[k].start.x; - // 1 FLOP = 1 ADD - double v1_y = p.curr_pos_y - board.obstacles[k].start.y; - - // 4 FLOPS = 3 MULT + 1 ADD - double projection = (v1_x * board.obstacles[k].obstacle_v.x + v1_y * board.obstacles[k].obstacle_v.y) * board.obstacles[k].length_sq_inv; - - if (projection < 0.0) - projection = 0.0; - else if (projection > 1.0) - projection = 1.0; - - // 3 FLOPS = 1 MULT + 2 ADD - double r_aB_x = p.curr_pos_x - (board.obstacles[k].start.x + board.obstacles[k].obstacle_v.x * projection); - // 3 FLOPS = 1 MULT + 2 ADD - double r_aB_y = p.curr_pos_y - (board.obstacles[k].start.y + board.obstacles[k].obstacle_v.y * projection); - - // 4 FLOPS = 1 SQRT + 2 MULT + 1 ADD - double r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); - // 33 FLOPS = 1 DIV + 2 MULT + 1 EXPT - double scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; - // 1 FLOP = 1 MULT - double f_alpha_B_neg_x = r_aB_x * scalar_mult; - // 1 FLOP = 1 MULT - double f_alpha_B_neg_y = r_aB_y * scalar_mult; - - double w_val; - // 4 FLOPS = 3 MULT + 1 ADD - double a = (p.e_x * f_alpha_B_neg_x + p.e_y * f_alpha_B_neg_y) * cos_phi_inv; - // 3 FLOPS = 2 MULT + 1 ADD - double b_sq = f_alpha_B_neg_x * f_alpha_B_neg_x + f_alpha_B_neg_y * f_alpha_B_neg_y; - - w_val = dt_neg; - // 1 FLOP = 1 MULT - if (a >= 0 && (a * a > b_sq)) { - w_val = c_neg_times_dt; - } - - // 1 FLOP = 1 MULT - double f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; - // 1 FLOP = 1 MULT - double f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; - - // 1 FLOP = 1 ADD - f_alpha_dt_x += f_alpha_B_dt_x; - // 1 FLOP = 1 ADD - f_alpha_dt_y += f_alpha_B_dt_y; - } - - // 1 FLOP = 1 ADD - p.w_x += f_alpha_dt_x; - // 1 FLOP = 1 ADD - p.w_y += f_alpha_dt_y; - } - - // update the positions etc. - // ILP is not possible I think - // FLOPCOUNT = n_p * 29 FLOPS - // n_p * (7 ADD + 17 MULT + 3 SQRT + 2 DIV) - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - - // 4 FLOPS = 1 SQRT + 2 MULT + 1 ADD - double w_norm = sqrt(p.w_x * p.w_x + p.w_y * p.w_y); - - // 1 FLOP = 1 DIV - double correction_factor = min(1.0, p.v_max / w_norm); - - // 1 FLOP = 1 MULT - p.curr_vel_x = p.w_x * correction_factor; - // 1 FLOP = 1 MULT - p.curr_vel_y = p.w_y * correction_factor; - - // maybe move this calculation to a separate loop to enable ILP - // 2 FLOPS = 1 MULT + 1 ADD - p.curr_pos_x = p.curr_pos_x + p.curr_vel_x * dt; - // 2 FLOPS = 1 MULT + 1 ADD - p.curr_pos_y = p.curr_pos_y + p.curr_vel_y * dt; - - if (p.color == 0 && p.curr_pos_x > (BOARD_LENGTH - 1.5)) { - p.curr_pos_x = 1.0; - p.destination_y = p.curr_pos_y; - p.w_x = p.desired_v0; - p.w_y = 0.0; - p.curr_vel_x = p.w_x; - p.curr_vel_y = p.w_y; - } - if (p.color == 1 && p.curr_pos_x < 1.5) { - p.curr_pos_x = BOARD_LENGTH - 1.0; - p.destination_y = p.curr_pos_y; - p.w_x = -p.desired_v0; - p.w_y = 0.0; - p.curr_vel_x = p.w_x; - p.curr_vel_y = p.w_y; - } - - p.curr_pos_y = clamp(p.curr_pos_y, WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - - // 1 FLOP = 1 ADD - double e_x = p.destination_x - p.curr_pos_x; - // 1 FLOP = 1 ADD - double e_y = p.destination_y - p.curr_pos_y; - - // 5 FLOPS = 1 DIV + 1 SQRT + 2 MULT + 1 ADD - double e_norm_inv = 1.0 / sqrt(e_x * e_x + e_y * e_y); - - // 1 FLOP = 1 MULT - p.e_x = e_x * e_norm_inv; - // 1 FLOP = 1 MULT - p.e_y = e_y * e_norm_inv; - - // 3 FLOPS = 2 MULT + 1 ADD - double velocity_norm_sq = p.curr_vel_x * p.curr_vel_x + p.curr_vel_y * p.curr_vel_y; - - // 1 FLOP = 1 SQRT - double velocity_norm = sqrt(velocity_norm_sq); - - // 1 FLOP = 1 MULT - p.s_b_sq = velocity_norm_sq * delta_t_sq; - - // 2 FLOPS = 2 MULT - p.s_b_e_x = p.e_x * (velocity_norm * delta_t); - // 2 FLOPS = 2 MULT - p.s_b_e_y = p.e_y * (velocity_norm * delta_t); - -#if !BENCHMARK - if (dump_path && (t % dump_interval == 0)) { - samples.emplace_back(t + 1, i, p.curr_pos_x, p.curr_pos_y, p.e_x, p.e_y, p.color); - } -#endif - } - } - -#if !BENCHMARK - if (dump_path) { - ofstream out(dump_path); - out << "time,id,x,y,p.e.x,p.e.y,color\n"; - - for (auto &[t, id, x, y, e_x, e_y, c] : samples) { - out << t << ',' << id << ',' << x << ',' << y << ',' << e_x << ',' << e_y << ',' << c << '\n'; - } - } -#endif - - return 0; -} diff --git a/variants/variant_inlining_7_symmetry_2_ilp_2_flopcount.cpp b/variants/variant_inlining_7_symmetry_2_ilp_2_flopcount.cpp deleted file mode 100644 index 372c69c..0000000 --- a/variants/variant_inlining_7_symmetry_2_ilp_2_flopcount.cpp +++ /dev/null @@ -1,753 +0,0 @@ -// # ILP -// # Changes: flopcoun -// FLOPCOUNT = n_iter * [ 69 * n_p ** 2 - 16 * n_p + 63 * n_obstacles * n_p ] -// n_iter * [ n_p ** 2 * (12.5 A + 23 M + 2.5 S + 1 D + 1 E) + n_p * (14.5 A - 2 M + 0.5 S + 1 D - 1 E) + n_obstacles * n_p * (12 A + 19 M + 1 S + 1 D + 1 E) ] -// # Predecessor: variant_inlining_7_symmetry_2_ilp_2.cpp - -#include "../headers/board.hpp" -#include "../headers/constants.hpp" -#include "../headers/pedestrian_reduced.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - -#define SEED 42 -#define BOARD_WIDTH 10.0 -#define BOARD_LENGTH 50.0 -#define WALL_EPS 1e-3 -#define BOARD_WIDTH_MINUS_WALL_EPS 9.999 - -#ifndef RANDOM_SEED -#define RANDOM_SEED 0 -#endif - -#ifndef BENCHMARK -#define BENCHMARK 0 -#endif - -using namespace std; - -Pedestrian *init_pedestrians(int n_p) { -#if RANDOM_SEED - random_device rd; - mt19937 gen(rd()); -#else - mt19937 gen(SEED); -#endif - - normal_distribution velocity_gen(v0_mean, v0_std_dev); - uniform_real_distribution y_gen(0.3, BOARD_WIDTH - 0.3); - uniform_real_distribution x_gen_left(2.0, BOARD_LENGTH / 2.0); - uniform_real_distribution x_gen_right(BOARD_LENGTH / 2.0, BOARD_LENGTH - 2.0); - - Pedestrian *P = new Pedestrian[n_p]; - - int n_p_half = n_p / 2; - - for (int i = 0; i < n_p_half; i++) { - double x = x_gen_left(gen); - double y = y_gen(gen); - - double start_pos_x = x; - double start_pos_y = y; - - double destination_x = BOARD_LENGTH + 30.0; - double destination_y = y; - - double init_e_x = destination_x - start_pos_x; - double init_e_y = destination_y - start_pos_y; - double init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - double init_e_unit_x = init_e_x / init_e_norm; - double init_e_unit_y = init_e_y / init_e_norm; - - double desired_v0; - do { - desired_v0 = velocity_gen(gen); - } while (desired_v0 <= 0.1); - - double v_max = 1.3 * desired_v0; - - P[i] = Pedestrian(0, 0, 0, start_pos_x, start_pos_y, init_e_unit_x, init_e_unit_y, v_max, desired_v0, destination_x, destination_y); - } - - for (int i = n_p_half; i < n_p; i++) { - double x = x_gen_right(gen); - double y = y_gen(gen); - - double start_pos_x = x; - double start_pos_y = y; - double destination_x = -30; - double destination_y = y; - - double init_e_x = destination_x - start_pos_x; - double init_e_y = destination_y - start_pos_y; - double init_e_norm = sqrt(init_e_x * init_e_x + init_e_y * init_e_y); - double init_e_unit_x = init_e_x / init_e_norm; - double init_e_unit_y = init_e_y / init_e_norm; - - double desired_v0; - do { - desired_v0 = velocity_gen(gen); - } while (desired_v0 <= 0.1); - - double v_max = 1.3 * desired_v0; - - P[i] = Pedestrian(1, 0, 0, start_pos_x, start_pos_y, init_e_unit_x, init_e_unit_y, v_max, desired_v0, destination_x, destination_y); - } - - return P; -} - -Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } - -int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { - -#if BENCHMARK - (void)dump_path; -#endif - -#if !BENCHMARK - const int dump_interval = 1; - - vector> samples; - - if (dump_path) { - samples.reserve(static_cast(n_iter / dump_interval + 1) * n_p); - - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - samples.emplace_back(0, i, p.curr_pos_x, p.curr_pos_y, p.e_x, p.e_y, p.color); - } - } -#endif - - // here we have real (simple) symmetry - std::vector r_ab_x_lut(n_p * n_p, 0.0); - std::vector r_ab_y_lut(n_p * n_p, 0.0); - std::vector r_ab_norm_lut(n_p * n_p, 0.0); - // use NAME[i * n_p + j] - - // FLOPCOUNT = n_iter * [ {0.5 * (n_p * n_p - n_p) * 6 FLOPS} + {n_p * [(24 FLOPS) + ((n_p - 1) * 66 FLOPS) + (n_obstacles * 63 FLOPS) ]} + {n_p * 29 FLOPS} ] - // FLOPCOUNT = n_iter * [ {3 * (n_p * n_p - n_p)} + {n_p * [(24) + ((n_p - 1) * 66) + (n_obstacles * 63) ]} + {n_p * 29} ] - // FLOPCOUNT = n_iter * [ {3 * n_p ** 2 - 3 * n_p} + {66 * n_p ** 2 - 42 * n_p + 63 * n_obstacles * n_p} + {29 * n_p} ] - // FLOPCOUNT = n_iter * [ {3 * n_p ** 2 + 66 * n_p ** 2} + { - 3 * n_p - 42 * n_p + 29 * n_p} + {63 * n_obstacles * n_p} ] - // FLOPCOUNT = n_iter * [ 69 * n_p ** 2 - 16 * n_p + 63 * n_obstacles * n_p ] - - - // n_iter * [ {0.5 * (n_p * n_p - n_p) * (3 ADD + 2 MULT + 1 SQRT)} + {n_p * [ (20 ADD + 4 MULT) + ((n_p - 1) * (11 ADD + 22 MULT + 2 SQRT + 1 DIV + 1 EXP)) + n_obstacles * (12 ADD + 19 MULT + 1 SQRT + 1 DIV + 1 EXP) ]} + {n_p * (7 ADD + 17 MULT + 3 SQRT + 2 DIV)} ] - // n_iter * [ {0.5 * n_p ** 2 * (3 A + 2 M + 1 S) - 0.5 * n_p * (3 A + 2 M + 1 S)} + {n_p * [ (20 A + 4 M) + ((n_p - 1) * (11 A + 22 M + 2 S + 1 D + 1 E)) + n_obstacles * (12 A + 19 M + 1 S + 1 D + 1 E) ]} + {n_p * (7 A + 17 M + 3 S + 2 D)} ] - // n_iter * [ 0.5 * n_p ** 2 * (3 A + 2 M + 1 S) - 0.5 * n_p * (3 A + 2 M + 1 S) + {n_p * [ (20 A + 4 M) + n_p * (11 A + 22 M + 2 S + 1 D + 1 E) - 1 * (11 A + 22 M + 2 S + 1 D + 1 E) + n_obstacles * (12 A + 19 M + 1 S + 1 D + 1 E) ]} + {n_p * (7 A + 17 M + 3 S + 2 D)} ] - // n_iter * [ 0.5 * n_p ** 2 * (3 A + 2 M + 1 S) - 0.5 * n_p * (3 A + 2 M + 1 S) + n_p ** 2 * (11 A + 22 M + 2 S + 1 D + 1 E) + n_p * (9 A - 18 M - 2 S - 1 D - 1 E) + n_obstacles * n_p * (12 A + 19 M + 1 S + 1 D + 1 E) + n_p * (7 A + 17 M + 3 S + 2 D) ] - // n_iter * [ n_p ** 2 * (1.5 A + 1 M + 0.5 S + 11 A + 22 M + 2 S + 1 D + 1 E) + n_p * (- 1.5 A - 1 M - 0.5 S + 9 A - 18 M - 2 S - 1 D - 1 E + 7 A + 17 M + 3 S + 2 D) + n_obstacles * n_p * (12 A + 19 M + 1 S + 1 D + 1 E) ] - // n_iter * [ n_p ** 2 * (12.5 A + 23 M + 2.5 S + 1 D + 1 E) + n_p * (14.5 A - 2 M + 0.5 S + 1 D - 1 E) + n_obstacles * n_p * (12 A + 19 M + 1 S + 1 D + 1 E) ] - for (int t = 0; t < n_iter; t++) { - - // get all distances first - // No ILP because no accumulators - // FLOPCOUNT = 0.5 * (n_p * n_p - n_p) * 6 FLOPS - // 0.5 * (n_p * n_p - n_p) * (3 ADD + 2 MULT + 1 SQRT) - for (int i = 0; i < n_p; i++) { - // only upper triangle - for (int j = i + 1; j < n_p; j++) { - // 1 FLOP = 1 ADD - double dx = pedestrians[i].curr_pos_x - pedestrians[j].curr_pos_x; - // 1 FLOP = 1 ADD - double dy = pedestrians[i].curr_pos_y - pedestrians[j].curr_pos_y; - // 4 FLOPS = 1 SQRT + 2 MULT + 1 ADD - double norm = sqrt(dx * dx + dy * dy); - r_ab_x_lut[i * n_p + j] = dx; - r_ab_y_lut[i * n_p + j] = dy; - r_ab_norm_lut[i * n_p + j] = norm; - } - } - - - // FLOPCOUNT = n_p * [(24 FLOPS) + ((n_p - 1) * 66 FLOPS) + (n_obstacles * 63 FLOPS) ] - // n_p * [ (20 ADD + 4 MULT) + ((n_p - 1) * (11 ADD + 22 MULT + 2 SQRT + 1 DIV + 1 EXP)) + n_obstacles * (12 ADD + 19 MULT + 1 SQRT + 1 DIV + 1 EXP) ] - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - - // 1 FLOP = 1 MULT - double desired_velocity_x = p.e_x * p.desired_v0; - // 1 FLOP = 1 MULT - double desired_velocity_y = p.e_y * p.desired_v0; - - // 2 FLOPS = 1ADD + 1 MULT - double f_alpha_dt_x = (desired_velocity_x - p.curr_vel_x) * dt_times_tau_alpha_inv; - // 2 FLOPS = 1ADD + 1 MULT - double f_alpha_dt_y = (desired_velocity_y - p.curr_vel_y) * dt_times_tau_alpha_inv; - - // accumulators for ILP - // f_alpha_dt_x = f_alpha_dt_x + f_alpha_beta_neg_x * w_val; - // f_alpha_dt_y = f_alpha_dt_y + f_alpha_beta_neg_y * w_val; - double acc_0_x = 0.0, acc_1_x = 0.0, acc_2_x = 0.0, acc_3_x = 0.0, acc_4_x = 0.0, acc_5_x = 0.0, acc_6_x = 0.0, acc_7_x = 0.0; - double acc_0_y = 0.0, acc_1_y = 0.0, acc_2_y = 0.0, acc_3_y = 0.0, acc_4_y = 0.0, acc_5_y = 0.0, acc_6_y = 0.0, acc_7_y = 0.0; - - const double p_e_x = p.e_x; - const double p_e_y = p.e_y; - - - // force between pedestrians --> no symmetry because of different accelerations - // ILP - int j = 0; - // FLOPCOUNT = (n_p - 1) * 66 FLOPS - for (; j <= n_p - 8; j+=8) { - // distance symmetry - double r_ab_x_0, r_ab_y_0, r_ab_norm_0; - double r_ab_x_1, r_ab_y_1, r_ab_norm_1; - double r_ab_x_2, r_ab_y_2, r_ab_norm_2; - double r_ab_x_3, r_ab_y_3, r_ab_norm_3; - double r_ab_x_4, r_ab_y_4, r_ab_norm_4; - double r_ab_x_5, r_ab_y_5, r_ab_norm_5; - double r_ab_x_6, r_ab_y_6, r_ab_norm_6; - double r_ab_x_7, r_ab_y_7, r_ab_norm_7; - - int j0 = j, j1 = j+1, j2 = j+2, j3 = j+3, j4 = j+4, j5 = j+5, j6 = j+6, j7 = j+7; - - // skip i == j - // FLOPCOUNT = 66 FLOPS - if (i != j0) { - if (i < j0) { - r_ab_x_0 = r_ab_x_lut[i * n_p + j0]; - r_ab_y_0 = r_ab_y_lut[i * n_p + j0]; - r_ab_norm_0 = r_ab_norm_lut[i * n_p + j0]; - } else { - // other direction - // I think here we can optimize for sure, currently not using LUT good - r_ab_x_0 = -1 * r_ab_x_lut[j0 * n_p + i]; - r_ab_y_0 = -1 * r_ab_y_lut[j0 * n_p + i]; - r_ab_norm_0 = r_ab_norm_lut[j0 * n_p + i]; - } - // the math, see paper - // 1 FLOP = 1 ADD - double r_ab2_x_0 = r_ab_x_0 - pedestrians[j0].s_b_e_x; - // 1 FLOP = 1 ADD - double r_ab2_y_0 = r_ab_y_0 - pedestrians[j0].s_b_e_y; - - // 4 FLOPS = 1 SQRT + 2 MULT + 1 ADD - double r_ab2_norm_0 = sqrt(r_ab2_x_0 * r_ab2_x_0 + r_ab2_y_0 * r_ab2_y_0); - // 1 FLOP = 1 ADD - double r_ab_norm_sum_0 = r_ab_norm_0 + r_ab2_norm_0; - // 2 FLOPS = 1 MULT + 1 ADD - double two_b_sq_0 = r_ab_norm_sum_0 * r_ab_norm_sum_0 - pedestrians[j0].s_b_sq; - // 1 FLOP = 1 SQRT - double two_b_0 = sqrt(two_b_sq_0); - // 36 FLOPS = 1 DIV + 5 MULT + 1 EXP - double scalar_mult_common_0 = (r_ab_norm_sum_0 / (two_b_0 * r_ab_norm_0 * r_ab2_norm_0)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_0 * NEG_TWO_SIGMA_INV)); - // 1 FLOP = 1 MULT - double scalar_mult_r_ab_0 = scalar_mult_common_0 * r_ab2_norm_0; - // 1 FLOP = 1 MULT - double scalar_mult_r_ab2_0 = scalar_mult_common_0 * r_ab_norm_0; - - // 3 FLOPS = 1 ADD + 2 MULT - double f_alpha_beta_neg_x_0 = r_ab_x_0 * scalar_mult_r_ab_0 + r_ab2_x_0 * scalar_mult_r_ab2_0; - // 3 FLOPS = 1 ADD + 2 MULT - double f_alpha_beta_neg_y_0 = r_ab_y_0 * scalar_mult_r_ab_0 + r_ab2_y_0 * scalar_mult_r_ab2_0; - - double w_val_0; - // 4 FLOPS = 1 ADD + 3 MULT - double a_0 = (p_e_x * f_alpha_beta_neg_x_0 + p_e_y * f_alpha_beta_neg_y_0) * cos_phi_inv; - // 3 FLOPS = 1 ADD + 2 MULT - double b_sq_0 = f_alpha_beta_neg_x_0 * f_alpha_beta_neg_x_0 + f_alpha_beta_neg_y_0 * f_alpha_beta_neg_y_0; - - w_val_0 = dt_neg; - // 1 FLOP - if (a_0 >= 0 && (a_0 * a_0 > b_sq_0)) { - w_val_0 = c_neg_times_dt; - } - - // 2 FLOPS = 1 ADD + 1 MULT - acc_0_x += f_alpha_beta_neg_x_0 * w_val_0; - // 2 FLOPS = 1 ADD + 1 MULT - acc_0_y += f_alpha_beta_neg_y_0 * w_val_0; - } - - // skip i == j - // FLOPCOUNT = 66 FLOPS - if (i != j1) { - if (i < j1) { - r_ab_x_1 = r_ab_x_lut[i * n_p + j1]; - r_ab_y_1 = r_ab_y_lut[i * n_p + j1]; - r_ab_norm_1 = r_ab_norm_lut[i * n_p + j1]; - } else { - // other direction - // I think here we can optimize for sure, currently not using LUT good - r_ab_x_1 = -1 * r_ab_x_lut[j1 * n_p + i]; - r_ab_y_1 = -1 * r_ab_y_lut[j1 * n_p + i]; - r_ab_norm_1 = r_ab_norm_lut[j1 * n_p + i]; - } - // the math, see paper - double r_ab2_x_1 = r_ab_x_1 - pedestrians[j1].s_b_e_x; - double r_ab2_y_1 = r_ab_y_1 - pedestrians[j1].s_b_e_y; - - double r_ab2_norm_1 = sqrt(r_ab2_x_1 * r_ab2_x_1 + r_ab2_y_1 * r_ab2_y_1); - double r_ab_norm_sum_1 = r_ab_norm_1 + r_ab2_norm_1; - double two_b_sq_1 = r_ab_norm_sum_1 * r_ab_norm_sum_1 - pedestrians[j1].s_b_sq; - double two_b_1 = sqrt(two_b_sq_1); - double scalar_mult_common_1 = (r_ab_norm_sum_1 / (two_b_1 * r_ab_norm_1 * r_ab2_norm_1)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_1 * NEG_TWO_SIGMA_INV)); - double scalar_mult_r_ab_1 = scalar_mult_common_1 * r_ab2_norm_1; - double scalar_mult_r_ab2_1 = scalar_mult_common_1 * r_ab_norm_1; - - double f_alpha_beta_neg_x_1 = r_ab_x_1 * scalar_mult_r_ab_1 + r_ab2_x_1 * scalar_mult_r_ab2_1; - double f_alpha_beta_neg_y_1 = r_ab_y_1 * scalar_mult_r_ab_1 + r_ab2_y_1 * scalar_mult_r_ab2_1; - - double w_val_1; - double a_1 = (p_e_x * f_alpha_beta_neg_x_1 + p_e_y * f_alpha_beta_neg_y_1) * cos_phi_inv; - double b_sq_1 = f_alpha_beta_neg_x_1 * f_alpha_beta_neg_x_1 + f_alpha_beta_neg_y_1 * f_alpha_beta_neg_y_1; - - w_val_1 = dt_neg; - if (a_1 >= 0 && (a_1 * a_1 > b_sq_1)) { - w_val_1 = c_neg_times_dt; - } - - acc_1_x += f_alpha_beta_neg_x_1 * w_val_1; - acc_1_y += f_alpha_beta_neg_y_1 * w_val_1; - } - - // skip i == j - // FLOPCOUNT = 66 FLOPS - if (i != j2) { - if (i < j2) { - r_ab_x_2 = r_ab_x_lut[i * n_p + j2]; - r_ab_y_2 = r_ab_y_lut[i * n_p + j2]; - r_ab_norm_2 = r_ab_norm_lut[i * n_p + j2]; - } else { - // other direction - // I think here we can optimize for sure, currently not using LUT good - r_ab_x_2 = -1 * r_ab_x_lut[j2 * n_p + i]; - r_ab_y_2 = -1 * r_ab_y_lut[j2 * n_p + i]; - r_ab_norm_2 = r_ab_norm_lut[j2 * n_p + i]; - } - // the math, see paper - double r_ab2_x_2 = r_ab_x_2 - pedestrians[j2].s_b_e_x; - double r_ab2_y_2 = r_ab_y_2 - pedestrians[j2].s_b_e_y; - - double r_ab2_norm_2 = sqrt(r_ab2_x_2 * r_ab2_x_2 + r_ab2_y_2 * r_ab2_y_2); - double r_ab_norm_sum_2 = r_ab_norm_2 + r_ab2_norm_2; - double two_b_sq_2 = r_ab_norm_sum_2 * r_ab_norm_sum_2 - pedestrians[j2].s_b_sq; - double two_b_2 = sqrt(two_b_sq_2); - double scalar_mult_common_2 = (r_ab_norm_sum_2 / (two_b_2 * r_ab_norm_2 * r_ab2_norm_2)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_2 * NEG_TWO_SIGMA_INV)); - double scalar_mult_r_ab_2 = scalar_mult_common_2 * r_ab2_norm_2; - double scalar_mult_r_ab2_2 = scalar_mult_common_2 * r_ab_norm_2; - - double f_alpha_beta_neg_x_2 = r_ab_x_2 * scalar_mult_r_ab_2 + r_ab2_x_2 * scalar_mult_r_ab2_2; - double f_alpha_beta_neg_y_2 = r_ab_y_2 * scalar_mult_r_ab_2 + r_ab2_y_2 * scalar_mult_r_ab2_2; - - double w_val_2; - double a_2 = (p_e_x * f_alpha_beta_neg_x_2 + p_e_y * f_alpha_beta_neg_y_2) * cos_phi_inv; - double b_sq_2 = f_alpha_beta_neg_x_2 * f_alpha_beta_neg_x_2 + f_alpha_beta_neg_y_2 * f_alpha_beta_neg_y_2; - - w_val_2 = dt_neg; - if (a_2 >= 0 && (a_2 * a_2 > b_sq_2)) { - w_val_2 = c_neg_times_dt; - } - - acc_2_x += f_alpha_beta_neg_x_2 * w_val_2; - acc_2_y += f_alpha_beta_neg_y_2 * w_val_2; - } - - // skip i == j - // FLOPCOUNT = 66 FLOPS - if (i != j3) { - if (i < j3) { - r_ab_x_3 = r_ab_x_lut[i * n_p + j3]; - r_ab_y_3 = r_ab_y_lut[i * n_p + j3]; - r_ab_norm_3 = r_ab_norm_lut[i * n_p + j3]; - } else { - // other direction - // I think here we can optimize for sure, currently not using LUT good - r_ab_x_3 = -1 * r_ab_x_lut[j3 * n_p + i]; - r_ab_y_3 = -1 * r_ab_y_lut[j3 * n_p + i]; - r_ab_norm_3 = r_ab_norm_lut[j3 * n_p + i]; - } - // the math, see paper - double r_ab2_x_3 = r_ab_x_3 - pedestrians[j3].s_b_e_x; - double r_ab2_y_3 = r_ab_y_3 - pedestrians[j3].s_b_e_y; - - double r_ab2_norm_3 = sqrt(r_ab2_x_3 * r_ab2_x_3 + r_ab2_y_3 * r_ab2_y_3); - double r_ab_norm_sum_3 = r_ab_norm_3 + r_ab2_norm_3; - double two_b_sq_3 = r_ab_norm_sum_3 * r_ab_norm_sum_3 - pedestrians[j3].s_b_sq; - double two_b_3 = sqrt(two_b_sq_3); - double scalar_mult_common_3 = (r_ab_norm_sum_3 / (two_b_3 * r_ab_norm_3 * r_ab2_norm_3)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_3 * NEG_TWO_SIGMA_INV)); - double scalar_mult_r_ab_3 = scalar_mult_common_3 * r_ab2_norm_3; - double scalar_mult_r_ab2_3 = scalar_mult_common_3 * r_ab_norm_3; - - double f_alpha_beta_neg_x_3 = r_ab_x_3 * scalar_mult_r_ab_3 + r_ab2_x_3 * scalar_mult_r_ab2_3; - double f_alpha_beta_neg_y_3 = r_ab_y_3 * scalar_mult_r_ab_3 + r_ab2_y_3 * scalar_mult_r_ab2_3; - - double w_val_3; - double a_3 = (p_e_x * f_alpha_beta_neg_x_3 + p_e_y * f_alpha_beta_neg_y_3) * cos_phi_inv; - double b_sq_3 = f_alpha_beta_neg_x_3 * f_alpha_beta_neg_x_3 + f_alpha_beta_neg_y_3 * f_alpha_beta_neg_y_3; - - w_val_3 = dt_neg; - if (a_3 >= 0 && (a_3 * a_3 > b_sq_3)) { - w_val_3 = c_neg_times_dt; - } - - acc_3_x += f_alpha_beta_neg_x_3 * w_val_3; - acc_3_y += f_alpha_beta_neg_y_3 * w_val_3; - } - - // skip i == j - // FLOPCOUNT = 66 FLOPS - if (i != j4) { - if (i < j4) { - r_ab_x_4 = r_ab_x_lut[i * n_p + j4]; - r_ab_y_4 = r_ab_y_lut[i * n_p + j4]; - r_ab_norm_4 = r_ab_norm_lut[i * n_p + j4]; - } else { - // other direction - // I think here we can optimize for sure, currently not using LUT good - r_ab_x_4 = -1 * r_ab_x_lut[j4 * n_p + i]; - r_ab_y_4 = -1 * r_ab_y_lut[j4 * n_p + i]; - r_ab_norm_4 = r_ab_norm_lut[j4 * n_p + i]; - } - // the math, see paper - double r_ab2_x_4 = r_ab_x_4 - pedestrians[j4].s_b_e_x; - double r_ab2_y_4 = r_ab_y_4 - pedestrians[j4].s_b_e_y; - - double r_ab2_norm_4 = sqrt(r_ab2_x_4 * r_ab2_x_4 + r_ab2_y_4 * r_ab2_y_4); - double r_ab_norm_sum_4 = r_ab_norm_4 + r_ab2_norm_4; - double two_b_sq_4 = r_ab_norm_sum_4 * r_ab_norm_sum_4 - pedestrians[j4].s_b_sq; - double two_b_4 = sqrt(two_b_sq_4); - double scalar_mult_common_4 = (r_ab_norm_sum_4 / (two_b_4 * r_ab_norm_4 * r_ab2_norm_4)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_4 * NEG_TWO_SIGMA_INV)); - double scalar_mult_r_ab_4 = scalar_mult_common_4 * r_ab2_norm_4; - double scalar_mult_r_ab2_4 = scalar_mult_common_4 * r_ab_norm_4; - - double f_alpha_beta_neg_x_4 = r_ab_x_4 * scalar_mult_r_ab_4 + r_ab2_x_4 * scalar_mult_r_ab2_4; - double f_alpha_beta_neg_y_4 = r_ab_y_4 * scalar_mult_r_ab_4 + r_ab2_y_4 * scalar_mult_r_ab2_4; - - double w_val_4; - double a_4 = (p_e_x * f_alpha_beta_neg_x_4 + p_e_y * f_alpha_beta_neg_y_4) * cos_phi_inv; - double b_sq_4 = f_alpha_beta_neg_x_4 * f_alpha_beta_neg_x_4 + f_alpha_beta_neg_y_4 * f_alpha_beta_neg_y_4; - - w_val_4 = dt_neg; - if (a_4 >= 0 && (a_4 * a_4 > b_sq_4)) { - w_val_4 = c_neg_times_dt; - } - - acc_4_x += f_alpha_beta_neg_x_4 * w_val_4; - acc_4_y += f_alpha_beta_neg_y_4 * w_val_4; - } - - // skip i == j - // FLOPCOUNT = 66 FLOPS - if (i != j5) { - if (i < j5) { - r_ab_x_5 = r_ab_x_lut[i * n_p + j5]; - r_ab_y_5 = r_ab_y_lut[i * n_p + j5]; - r_ab_norm_5 = r_ab_norm_lut[i * n_p + j5]; - } else { - // other direction - // I think here we can optimize for sure, currently not using LUT good - r_ab_x_5 = -1 * r_ab_x_lut[j5 * n_p + i]; - r_ab_y_5 = -1 * r_ab_y_lut[j5 * n_p + i]; - r_ab_norm_5 = r_ab_norm_lut[j5 * n_p + i]; - } - // the math, see paper - double r_ab2_x_5 = r_ab_x_5 - pedestrians[j5].s_b_e_x; - double r_ab2_y_5 = r_ab_y_5 - pedestrians[j5].s_b_e_y; - - double r_ab2_norm_5 = sqrt(r_ab2_x_5 * r_ab2_x_5 + r_ab2_y_5 * r_ab2_y_5); - double r_ab_norm_sum_5 = r_ab_norm_5 + r_ab2_norm_5; - double two_b_sq_5 = r_ab_norm_sum_5 * r_ab_norm_sum_5 - pedestrians[j5].s_b_sq; - double two_b_5 = sqrt(two_b_sq_5); - double scalar_mult_common_5 = (r_ab_norm_sum_5 / (two_b_5 * r_ab_norm_5 * r_ab2_norm_5)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_5 * NEG_TWO_SIGMA_INV)); - double scalar_mult_r_ab_5 = scalar_mult_common_5 * r_ab2_norm_5; - double scalar_mult_r_ab2_5 = scalar_mult_common_5 * r_ab_norm_5; - - double f_alpha_beta_neg_x_5 = r_ab_x_5 * scalar_mult_r_ab_5 + r_ab2_x_5 * scalar_mult_r_ab2_5; - double f_alpha_beta_neg_y_5 = r_ab_y_5 * scalar_mult_r_ab_5 + r_ab2_y_5 * scalar_mult_r_ab2_5; - - double w_val_5; - double a_5 = (p_e_x * f_alpha_beta_neg_x_5 + p_e_y * f_alpha_beta_neg_y_5) * cos_phi_inv; - double b_sq_5 = f_alpha_beta_neg_x_5 * f_alpha_beta_neg_x_5 + f_alpha_beta_neg_y_5 * f_alpha_beta_neg_y_5; - - w_val_5 = dt_neg; - if (a_5 >= 0 && (a_5 * a_5 > b_sq_5)) { - w_val_5 = c_neg_times_dt; - } - - acc_5_x += f_alpha_beta_neg_x_5 * w_val_5; - acc_5_y += f_alpha_beta_neg_y_5 * w_val_5; - } - - // skip i == j - // FLOPCOUNT = 66 FLOPS - if (i != j6) { - if (i < j6) { - r_ab_x_6 = r_ab_x_lut[i * n_p + j6]; - r_ab_y_6 = r_ab_y_lut[i * n_p + j6]; - r_ab_norm_6 = r_ab_norm_lut[i * n_p + j6]; - } else { - // other direction - // I think here we can optimize for sure, currently not using LUT good - r_ab_x_6 = -1 * r_ab_x_lut[j6 * n_p + i]; - r_ab_y_6 = -1 * r_ab_y_lut[j6 * n_p + i]; - r_ab_norm_6 = r_ab_norm_lut[j6 * n_p + i]; - } - // the math, see paper - double r_ab2_x_6 = r_ab_x_6 - pedestrians[j6].s_b_e_x; - double r_ab2_y_6 = r_ab_y_6 - pedestrians[j6].s_b_e_y; - - double r_ab2_norm_6 = sqrt(r_ab2_x_6 * r_ab2_x_6 + r_ab2_y_6 * r_ab2_y_6); - double r_ab_norm_sum_6 = r_ab_norm_6 + r_ab2_norm_6; - double two_b_sq_6 = r_ab_norm_sum_6 * r_ab_norm_sum_6 - pedestrians[j6].s_b_sq; - double two_b_6 = sqrt(two_b_sq_6); - double scalar_mult_common_6 = (r_ab_norm_sum_6 / (two_b_6 * r_ab_norm_6 * r_ab2_norm_6)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_6 * NEG_TWO_SIGMA_INV)); - double scalar_mult_r_ab_6 = scalar_mult_common_6 * r_ab2_norm_6; - double scalar_mult_r_ab2_6 = scalar_mult_common_6 * r_ab_norm_6; - - double f_alpha_beta_neg_x_6 = r_ab_x_6 * scalar_mult_r_ab_6 + r_ab2_x_6 * scalar_mult_r_ab2_6; - double f_alpha_beta_neg_y_6 = r_ab_y_6 * scalar_mult_r_ab_6 + r_ab2_y_6 * scalar_mult_r_ab2_6; - - double w_val_6; - double a_6 = (p_e_x * f_alpha_beta_neg_x_6 + p_e_y * f_alpha_beta_neg_y_6) * cos_phi_inv; - double b_sq_6 = f_alpha_beta_neg_x_6 * f_alpha_beta_neg_x_6 + f_alpha_beta_neg_y_6 * f_alpha_beta_neg_y_6; - - w_val_6 = dt_neg; - if (a_6 >= 0 && (a_6 * a_6 > b_sq_6)) { - w_val_6 = c_neg_times_dt; - } - - acc_6_x += f_alpha_beta_neg_x_6 * w_val_6; - acc_6_y += f_alpha_beta_neg_y_6 * w_val_6; - } - - // skip i == j - // FLOPCOUNT = 66 FLOPS - if (i != j7) { - if (i < j7) { - r_ab_x_7 = r_ab_x_lut[i * n_p + j7]; - r_ab_y_7 = r_ab_y_lut[i * n_p + j7]; - r_ab_norm_7 = r_ab_norm_lut[i * n_p + j7]; - } else { - // other direction - // I think here we can optimize for sure, currently not using LUT good - r_ab_x_7 = -1 * r_ab_x_lut[j7 * n_p + i]; - r_ab_y_7 = -1 * r_ab_y_lut[j7 * n_p + i]; - r_ab_norm_7 = r_ab_norm_lut[j7 * n_p + i]; - } - // the math, see paper - double r_ab2_x_7 = r_ab_x_7 - pedestrians[j7].s_b_e_x; - double r_ab2_y_7 = r_ab_y_7 - pedestrians[j7].s_b_e_y; - - double r_ab2_norm_7 = sqrt(r_ab2_x_7 * r_ab2_x_7 + r_ab2_y_7 * r_ab2_y_7); - double r_ab_norm_sum_7 = r_ab_norm_7 + r_ab2_norm_7; - double two_b_sq_7 = r_ab_norm_sum_7 * r_ab_norm_sum_7 - pedestrians[j7].s_b_sq; - double two_b_7 = sqrt(two_b_sq_7); - double scalar_mult_common_7 = (r_ab_norm_sum_7 / (two_b_7 * r_ab_norm_7 * r_ab2_norm_7)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b_7 * NEG_TWO_SIGMA_INV)); - double scalar_mult_r_ab_7 = scalar_mult_common_7 * r_ab2_norm_7; - double scalar_mult_r_ab2_7 = scalar_mult_common_7 * r_ab_norm_7; - - double f_alpha_beta_neg_x_7 = r_ab_x_7 * scalar_mult_r_ab_7 + r_ab2_x_7 * scalar_mult_r_ab2_7; - double f_alpha_beta_neg_y_7 = r_ab_y_7 * scalar_mult_r_ab_7 + r_ab2_y_7 * scalar_mult_r_ab2_7; - - double w_val_7; - double a_7 = (p_e_x * f_alpha_beta_neg_x_7 + p_e_y * f_alpha_beta_neg_y_7) * cos_phi_inv; - double b_sq_7 = f_alpha_beta_neg_x_7 * f_alpha_beta_neg_x_7 + f_alpha_beta_neg_y_7 * f_alpha_beta_neg_y_7; - - w_val_7 = dt_neg; - if (a_7 >= 0 && (a_7 * a_7 > b_sq_7)) { - w_val_7 = c_neg_times_dt; - } - - acc_7_x += f_alpha_beta_neg_x_7 * w_val_7; - acc_7_y += f_alpha_beta_neg_y_7 * w_val_7; - } - - } - - // add the result - // 8 FLOPS = 8 ADD - f_alpha_dt_x += acc_0_x + acc_1_x + acc_2_x + acc_3_x + acc_4_x + acc_5_x + acc_6_x + acc_7_x; - // 8 FLOPS = 8 ADD - f_alpha_dt_y += acc_0_y + acc_1_y + acc_2_y + acc_3_y + acc_4_y + acc_5_y + acc_6_y + acc_7_y; - - // remaining - // 66 FLOPS --> ignore for flop count already handled correctly with ILP loop - for (; j < n_p; j++) { - if (i == j) continue; - - double r_ab_x, r_ab_y, r_ab_norm; - if (i < j) { - r_ab_x = r_ab_x_lut[i * n_p + j]; - r_ab_y = r_ab_y_lut[i * n_p + j]; - r_ab_norm = r_ab_norm_lut[i * n_p + j]; - } else { - r_ab_x = -1 * r_ab_x_lut[j * n_p + i]; - r_ab_y = -1 * r_ab_y_lut[j * n_p + i]; - r_ab_norm = r_ab_norm_lut[j * n_p + i]; - } - - // 1 FLOP = 1 ADD - double r_ab2_x = r_ab_x - pedestrians[j].s_b_e_x; - // 1 FLOP = 1 ADD - double r_ab2_y = r_ab_y - pedestrians[j].s_b_e_y; - - // 4 FLOPS = 1 SQRT + 2 MULT + 1 ADD - double r_ab2_norm = sqrt(r_ab2_x * r_ab2_x + r_ab2_y * r_ab2_y); - // 1 FLOP = 1 ADD - double r_ab_norm_sum = r_ab_norm + r_ab2_norm; - // 2 FLOPS = 1 MULT + 1 ADD - double two_b_sq = r_ab_norm_sum * r_ab_norm_sum - pedestrians[j].s_b_sq; - // 1 FLOP = 1 SQRT - double two_b = sqrt(two_b_sq); - // 36 FLOPS = 1 DIV + 5 MULT + 1 EXP - double scalar_mult_common = (r_ab_norm_sum / (two_b * r_ab_norm * r_ab2_norm)) * (NEG_V0_AB_div_TWO_SIGMA * exp(two_b * NEG_TWO_SIGMA_INV)); - // 1 FLOP = 1 MULT - double scalar_mult_r_ab = scalar_mult_common * r_ab2_norm; - // 1 FLOP = 1 MULT - double scalar_mult_r_ab2 = scalar_mult_common * r_ab_norm; - - // 3 FLOPS = 2 MULT + 1 ADD - double f_alpha_beta_neg_x = r_ab_x * scalar_mult_r_ab + r_ab2_x * scalar_mult_r_ab2; - // 3 FLOPS = 2 MULT + 1 ADD - double f_alpha_beta_neg_y = r_ab_y * scalar_mult_r_ab + r_ab2_y * scalar_mult_r_ab2; - - double w_val; - // 4 FLOPS = 3 MULT + 1 ADD - double a = (p_e_x * f_alpha_beta_neg_x + p_e_y * f_alpha_beta_neg_y) * cos_phi_inv; - // 3 FLOPS = 2 MULT + 1 ADD - double b_sq = f_alpha_beta_neg_x * f_alpha_beta_neg_x + f_alpha_beta_neg_y * f_alpha_beta_neg_y; - - w_val = dt_neg; - // 1 FLOP = 1 MULT - if (a >= 0 && (a * a > b_sq)) { - w_val = c_neg_times_dt; - } - - // 2 FLOPS = 1 ADD + 1 MULT - f_alpha_dt_x = f_alpha_dt_x + f_alpha_beta_neg_x * w_val; - // 2 FLOPS = 1 ADD + 1 MULT - f_alpha_dt_y = f_alpha_dt_y + f_alpha_beta_neg_y * w_val; - } - - - // force between pedestrian and obstacles - // initialized with 0 obstacles, might consider deleting this? - // to sparse to use ILP - // FLOPS = n_obstacles * 63 FLOPS - for (int k = 0; k < board.n_obstacles; k++) { - - double v1_x = p.curr_pos_x - board.obstacles[k].start.x; - double v1_y = p.curr_pos_y - board.obstacles[k].start.y; - - double projection = (v1_x * board.obstacles[k].obstacle_v.x + v1_y * board.obstacles[k].obstacle_v.y) * board.obstacles[k].length_sq_inv; - - if (projection < 0.0) - projection = 0.0; - else if (projection > 1.0) - projection = 1.0; - - double r_aB_x = p.curr_pos_x - (board.obstacles[k].start.x + board.obstacles[k].obstacle_v.x * projection); - double r_aB_y = p.curr_pos_y - (board.obstacles[k].start.y + board.obstacles[k].obstacle_v.y * projection); - - double r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); - double scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; - double f_alpha_B_neg_x = r_aB_x * scalar_mult; - double f_alpha_B_neg_y = r_aB_y * scalar_mult; - - double w_val; - double a = (p.e_x * f_alpha_B_neg_x + p.e_y * f_alpha_B_neg_y) * cos_phi_inv; - double b_sq = f_alpha_B_neg_x * f_alpha_B_neg_x + f_alpha_B_neg_y * f_alpha_B_neg_y; - - w_val = dt_neg; - if (a >= 0 && (a * a > b_sq)) { - w_val = c_neg_times_dt; - } - - double f_alpha_B_dt_x = f_alpha_B_neg_x * w_val; - double f_alpha_B_dt_y = f_alpha_B_neg_y * w_val; - - f_alpha_dt_x += f_alpha_B_dt_x; - f_alpha_dt_y += f_alpha_B_dt_y; - } - - // 1 FLOP = 1 ADD - p.w_x += f_alpha_dt_x; - // 1 FLOP = 1 ADD - p.w_y += f_alpha_dt_y; - } - - // update the positions etc. - // ILP is not possible I think - // FLOPCOUNT = n_p * 29 FLOPS - // n_p * (7 ADD + 17 MULT + 3 SQRT + 2 DIV) - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - - double w_norm = sqrt(p.w_x * p.w_x + p.w_y * p.w_y); - - double correction_factor = min(1.0, p.v_max / w_norm); - - p.curr_vel_x = p.w_x * correction_factor; - p.curr_vel_y = p.w_y * correction_factor; - - // maybe move this calculation to a separate loop to enable ILP - p.curr_pos_x = p.curr_pos_x + p.curr_vel_x * dt; - p.curr_pos_y = p.curr_pos_y + p.curr_vel_y * dt; - - if (p.color == 0 && p.curr_pos_x > (BOARD_LENGTH - 1.5)) { - p.curr_pos_x = 1.0; - p.destination_y = p.curr_pos_y; - p.w_x = p.desired_v0; - p.w_y = 0.0; - p.curr_vel_x = p.w_x; - p.curr_vel_y = p.w_y; - } - if (p.color == 1 && p.curr_pos_x < 1.5) { - p.curr_pos_x = BOARD_LENGTH - 1.0; - p.destination_y = p.curr_pos_y; - p.w_x = -p.desired_v0; - p.w_y = 0.0; - p.curr_vel_x = p.w_x; - p.curr_vel_y = p.w_y; - } - - p.curr_pos_y = clamp(p.curr_pos_y, WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - - double e_x = p.destination_x - p.curr_pos_x; - double e_y = p.destination_y - p.curr_pos_y; - - double e_norm_inv = 1.0 / sqrt(e_x * e_x + e_y * e_y); - - p.e_x = e_x * e_norm_inv; - p.e_y = e_y * e_norm_inv; - - double velocity_norm_sq = p.curr_vel_x * p.curr_vel_x + p.curr_vel_y * p.curr_vel_y; - - double velocity_norm = sqrt(velocity_norm_sq); - - p.s_b_sq = velocity_norm_sq * delta_t_sq; - - p.s_b_e_x = p.e_x * (velocity_norm * delta_t); - p.s_b_e_y = p.e_y * (velocity_norm * delta_t); - -#if !BENCHMARK - if (dump_path && (t % dump_interval == 0)) { - samples.emplace_back(t + 1, i, p.curr_pos_x, p.curr_pos_y, p.e_x, p.e_y, p.color); - } -#endif - } - } - -#if !BENCHMARK - if (dump_path) { - ofstream out(dump_path); - out << "time,id,x,y,p.e.x,p.e.y,color\n"; - - for (auto &[t, id, x, y, e_x, e_y, c] : samples) { - out << t << ',' << id << ',' << x << ',' << y << ',' << e_x << ',' << e_y << ',' << c << '\n'; - } - } -#endif - - return 0; -} diff --git a/variants/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt.cpp b/variants/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt.cpp index 2164224..cb3d8e3 100644 --- a/variants/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt.cpp +++ b/variants/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt.cpp @@ -166,23 +166,42 @@ Pedestrian *init_pedestrians(int n_p) { Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } +// # 128 MULTs, 112 ADDs static inline __m512d _avx512_exp_pd(__m512d x) { - + const __m512d log2e = _mm512_set1_pd(1.4426950408889634); + + // # 8 MULTs __m512d nf = _mm512_roundscale_pd(_mm512_mul_pd(x, log2e), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); const __m512d ln2 = _mm512_set1_pd(0.6931471805599453); + + // # 8 MULTs, 8 ADDs __m512d r = _mm512_fnmadd_pd(nf, ln2, x); - const __m512d c7 = _mm512_set1_pd(1.0 / 5040.0); - const __m512d c6 = _mm512_set1_pd(1.0 / 720.0); - const __m512d c5 = _mm512_set1_pd(1.0 / 120.0); - const __m512d c4 = _mm512_set1_pd(1.0 / 24.0); - const __m512d c3 = _mm512_set1_pd(1.0 / 6.0); - const __m512d c2 = _mm512_set1_pd(0.5); - const __m512d c1 = _mm512_set1_pd(1.0); - const __m512d c0 = _mm512_set1_pd(1.0); + const __m512d c13 = _mm512_set1_pd(c13_scalar); + const __m512d c12 = _mm512_set1_pd(c12_scalar); + const __m512d c11 = _mm512_set1_pd(c11_scalar); + const __m512d c10 = _mm512_set1_pd(c10_scalar); + const __m512d c9 = _mm512_set1_pd(c9_scalar); + const __m512d c8 = _mm512_set1_pd(c8_scalar); + const __m512d c7 = _mm512_set1_pd(c7_scalar); + const __m512d c6 = _mm512_set1_pd(c6_scalar); + const __m512d c5 = _mm512_set1_pd(c5_scalar); + const __m512d c4 = _mm512_set1_pd(c4_scalar); + const __m512d c3 = _mm512_set1_pd(c3_scalar); + const __m512d c2 = _mm512_set1_pd(c2_scalar); + const __m512d c1 = _mm512_set1_pd(c1_scalar); + const __m512d c0 = _mm512_set1_pd(c0_scalar); - __m512d p = c7; + __m512d p = c13; + + // # 104 MULTs, 104 ADDs + p = _mm512_fmadd_pd(p, r, c12); + p = _mm512_fmadd_pd(p, r, c11); + p = _mm512_fmadd_pd(p, r, c10); + p = _mm512_fmadd_pd(p, r, c9); + p = _mm512_fmadd_pd(p, r, c8); + p = _mm512_fmadd_pd(p, r, c7); p = _mm512_fmadd_pd(p, r, c6); p = _mm512_fmadd_pd(p, r, c5); p = _mm512_fmadd_pd(p, r, c4); @@ -208,6 +227,7 @@ static inline __m512d _avx512_exp_pd(__m512d x) { __m512d pow2n = _mm512_castsi512_pd(scaled); + // # 8 MULTs return _mm512_mul_pd(p, pow2n); } @@ -261,6 +281,23 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c const __m512d v_np = _mm512_set1_pd(n_p); + // # ADDs: n_iter * n_p * 33 + + // # n_iter * n_p * (n_p_pad / 8) * 232 + + // # n_iter * n_p * board.n_obstacles * 10 + + // # MULTs: n_iter * n_p * 40 + + // # n_iter * n_p * (n_p_pad / 8) * 320 + + // # n_iter * n_p * board.n_obstacles * 13 + + // # DIVs: n_iter * n_p * (n_p_pad / 8) * 8 + + // # n_iter * n_p * board.n_obstacles + + // # SQRTs: n_iter * n_p + + // # n_iter * n_p * (n_p_pad / 8) * 24 + + // # n_iter * n_p * board.n_obstacles + + // # EXPs: n_iter * n_p * board.n_obstacles + for (int t = 0; t < n_iter; t++) { for (int i = 0; i < n_p; i++) { diff --git a/variants/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr.cpp b/variants/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr.cpp index 6f5b8df..c621275 100644 --- a/variants/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr.cpp +++ b/variants/variant_inlining_8_SoA_AVX512_polyexp_fastinvsqrt_sr.cpp @@ -14,6 +14,8 @@ #define SEED 42 #define BOARD_WIDTH 10.0 #define BOARD_LENGTH 50.0 +#define BOARD_LENGTH_MINUS_ONE BOARD_LENGTH - 1.0 +#define BOARD_LENGTH_MINUS_ONE_POINT_FIVE BOARD_LENGTH - 1.5 #define WALL_EPS 1e-3 #define BOARD_WIDTH_MINUS_WALL_EPS 9.999 @@ -163,23 +165,42 @@ Pedestrian *init_pedestrians(int n_p) { Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } +// # 128 MULTs, 112 ADDs static inline __m512d _avx512_exp_pd(__m512d x) { const __m512d log2e = _mm512_set1_pd(1.4426950408889634); + + // # 8 MULTs __m512d nf = _mm512_roundscale_pd(_mm512_mul_pd(x, log2e), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); const __m512d ln2 = _mm512_set1_pd(0.6931471805599453); + + // # 8 MULTs, 8 ADDs __m512d r = _mm512_fnmadd_pd(nf, ln2, x); - const __m512d c7 = _mm512_set1_pd(1.0 / 5040.0); - const __m512d c6 = _mm512_set1_pd(1.0 / 720.0); - const __m512d c5 = _mm512_set1_pd(1.0 / 120.0); - const __m512d c4 = _mm512_set1_pd(1.0 / 24.0); - const __m512d c3 = _mm512_set1_pd(1.0 / 6.0); - const __m512d c2 = _mm512_set1_pd(0.5); - const __m512d c1 = _mm512_set1_pd(1.0); - const __m512d c0 = _mm512_set1_pd(1.0); + const __m512d c13 = _mm512_set1_pd(c13_scalar); + const __m512d c12 = _mm512_set1_pd(c12_scalar); + const __m512d c11 = _mm512_set1_pd(c11_scalar); + const __m512d c10 = _mm512_set1_pd(c10_scalar); + const __m512d c9 = _mm512_set1_pd(c9_scalar); + const __m512d c8 = _mm512_set1_pd(c8_scalar); + const __m512d c7 = _mm512_set1_pd(c7_scalar); + const __m512d c6 = _mm512_set1_pd(c6_scalar); + const __m512d c5 = _mm512_set1_pd(c5_scalar); + const __m512d c4 = _mm512_set1_pd(c4_scalar); + const __m512d c3 = _mm512_set1_pd(c3_scalar); + const __m512d c2 = _mm512_set1_pd(c2_scalar); + const __m512d c1 = _mm512_set1_pd(c1_scalar); + const __m512d c0 = _mm512_set1_pd(c0_scalar); - __m512d p = c7; + __m512d p = c13; + + // # 104 MULTs, 104 ADDs + p = _mm512_fmadd_pd(p, r, c12); + p = _mm512_fmadd_pd(p, r, c11); + p = _mm512_fmadd_pd(p, r, c10); + p = _mm512_fmadd_pd(p, r, c9); + p = _mm512_fmadd_pd(p, r, c8); + p = _mm512_fmadd_pd(p, r, c7); p = _mm512_fmadd_pd(p, r, c6); p = _mm512_fmadd_pd(p, r, c5); p = _mm512_fmadd_pd(p, r, c4); @@ -205,9 +226,11 @@ static inline __m512d _avx512_exp_pd(__m512d x) { __m512d pow2n = _mm512_castsi512_pd(scaled); + // # 8 MULTs return _mm512_mul_pd(p, pow2n); } +// # 10 MULTs, 3 ADDs static inline double fast_inv_sqrt(double number) { double y = number; @@ -258,9 +281,26 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c const __m512d v_np = _mm512_set1_pd(n_p); - for (int t = 0; t < n_iter; t++) { + // # ADDs: n_iter * n_p * 33 + + // # n_iter * n_p * (n_p_pad / 8) * 232 + + // # n_iter * n_p * board.n_obstacles * 10 + // # MULTs: n_iter * n_p * 40 + + // # n_iter * n_p * (n_p_pad / 8) * 320 + + // # n_iter * n_p * board.n_obstacles * 13 + + // # DIVs: n_iter * n_p * (n_p_pad / 8) * 8 + + // # n_iter * n_p * board.n_obstacles + + // # SQRTs: n_iter * n_p + + // # n_iter * n_p * (n_p_pad / 8) * 24 + + // # n_iter * n_p * board.n_obstacles + + // # EXPs: n_iter * n_p * board.n_obstacles + + for (int t = 0; t < n_iter; t++) { for (int i = 0; i < n_p; i++) { + double pos_x_i = pos_x[i]; double pos_y_i = pos_y[i]; double e_x_i = e_x[i]; @@ -269,6 +309,7 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c double curr_vel_x_i = curr_vel_x[i]; double curr_vel_y_i = curr_vel_y[i]; + // # 4 MULTs, 2 ADDs double f_alpha_dt_x = (e_x_i * desired_v0_i - curr_vel_x_i) * dt_times_tau_alpha_inv; double f_alpha_dt_y = (e_y_i * desired_v0_i - curr_vel_y_i) * dt_times_tau_alpha_inv; @@ -282,6 +323,8 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512d acc_y = _mm512_setzero_pd(); for (int j = 0; j < n_p_pad; j += 8) { + + // # 8 ADDs __m512d j_idx = _mm512_add_pd(_mm512_set1_pd((double)j), lane_off); __mmask8 m_neq_i = _mm512_cmp_pd_mask(j_idx, v_i, _CMP_NEQ_OQ); @@ -294,36 +337,65 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512d sbe_jy = _mm512_loadu_pd(&sb_e_y[j]); __m512d sb_jsq = _mm512_loadu_pd(&sb_sq[j]); + // # 16 ADDs __m512d r_ab_x = _mm512_sub_pd(pix, pjx); __m512d r_ab_y = _mm512_sub_pd(piy, pjy); + + // # 16 MULTs, 8 ADDs __m512d r_ab_n2 = _mm512_fmadd_pd(r_ab_x, r_ab_x, _mm512_mul_pd(r_ab_y, r_ab_y)); + + // # 8 SQRTs __m512d r_ab_n = _mm512_sqrt_pd(r_ab_n2); + // # 16 ADDs __m512d r_ab2_x = _mm512_sub_pd(r_ab_x, sbe_jx); __m512d r_ab2_y = _mm512_sub_pd(r_ab_y, sbe_jy); + + // # 16 MULTs, 8 ADDs __m512d r_ab2_n2 = _mm512_fmadd_pd(r_ab2_x, r_ab2_x, _mm512_mul_pd(r_ab2_y, r_ab2_y)); + + // # 8 SQRTs __m512d r_ab2_n = _mm512_sqrt_pd(r_ab2_n2); + // # 8 ADDs __m512d r_sum = _mm512_add_pd(r_ab_n, r_ab2_n); + + // # 8 MULTs, 8 ADDs __m512d two_b_sq = _mm512_fmsub_pd(r_sum, r_sum, sb_jsq); + + // # 8 SQRTs __m512d two_b = _mm512_sqrt_pd(two_b_sq); + // # 8 MULTs __m512d e_arg = _mm512_mul_pd(two_b, v_neg_2s_inv); + + // # 128 MULTs, 112 ADDs __m512d e_val = _avx512_exp_pd(e_arg); + // # 32 MULTs __m512d numer = _mm512_mul_pd(_mm512_mul_pd(r_sum, v_neg_v0_div_2s), e_val); __m512d denom = _mm512_mul_pd(_mm512_mul_pd(two_b, r_ab_n), r_ab2_n); + __m512d denom_safe = _mm512_mask_blend_pd(active, _mm512_set1_pd(1.0), denom); + + // # 8 DIVs __m512d smc = _mm512_div_pd(numer, denom_safe); + // # 16 MULTs __m512d sm_r_ab = _mm512_mul_pd(smc, r_ab2_n); __m512d sm_r_ab2 = _mm512_mul_pd(smc, r_ab_n); + // # 32 MULTs, 16 ADDs __m512d f_x = _mm512_fmadd_pd(r_ab2_x, sm_r_ab2, _mm512_mul_pd(r_ab_x, sm_r_ab)); __m512d f_y = _mm512_fmadd_pd(r_ab2_y, sm_r_ab2, _mm512_mul_pd(r_ab_y, sm_r_ab)); + // # 24 MULTs, 8 ADDs __m512d a = _mm512_mul_pd(_mm512_fmadd_pd(eix, f_x, _mm512_mul_pd(eiy, f_y)), v_cos_phi_inv); + + // # 8 MULTs __m512d a_sq = _mm512_mul_pd(a, a); + + // # 16 MULTs, 8 ADDs __m512d b_sq = _mm512_fmadd_pd(f_x, f_x, _mm512_mul_pd(f_y, f_y)); __mmask8 k_ge = _mm512_cmp_pd_mask(a, v_zero, _CMP_GE_OQ); @@ -333,10 +405,13 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512d f_x_safe = _mm512_maskz_mov_pd(active, f_x); __m512d f_y_safe = _mm512_maskz_mov_pd(active, f_y); + + // # 16 MULTs, 16 ADDs acc_x = _mm512_fmadd_pd(f_x_safe, w_val, acc_x); acc_y = _mm512_fmadd_pd(f_y_safe, w_val, acc_y); } + // # 16 ADDs f_alpha_dt_x += _mm512_reduce_add_pd(acc_x); f_alpha_dt_y += _mm512_reduce_add_pd(acc_y); @@ -348,9 +423,11 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c double obs_v_y = board.obstacles[k].obstacle_v_y; double obs_length_sq_inv = board.obstacles[k].length_sq_inv; + // # 2 ADDs double v1_x = pos_x_i - obs_start_x; double v1_y = pos_y_i - obs_start_y; + // # 3 MULTs, 1 ADD double projection = (v1_x * obs_v_x + v1_y * obs_v_y) * obs_length_sq_inv; if (projection < 0.0) @@ -358,11 +435,17 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c else if (projection > 1.0) projection = 1.0; + // # 2 MULTs, 4 ADDs double r_aB_x = pos_x_i - (obs_start_x + obs_v_x * projection); double r_aB_y = pos_y_i - (obs_start_y + obs_v_y * projection); + // # 1 SQRT, 2 MULTs, 1 ADD double r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); + + // # 2 MULTs, 1 EXP, 1 DIV double scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; + + // # 2 MULTs double f_alpha_B_neg_x = r_aB_x * scalar_mult; double f_alpha_B_neg_y = r_aB_y * scalar_mult; @@ -371,15 +454,18 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c if (e_dot_f < cos_phi) w_val = c_neg_times_dt; + // # 2 MULTs, 2 ADDs f_alpha_dt_x += f_alpha_B_neg_x * w_val; f_alpha_dt_y += f_alpha_B_neg_y * w_val; } + // # 2 ADDs w_x[i] += f_alpha_dt_x; w_y[i] += f_alpha_dt_y; } for (int i = 0; i < n_p; i++) { + double color_i = color[i]; double curr_vel_x_i = curr_vel_x[i]; double curr_vel_y_i = curr_vel_y[i]; @@ -394,17 +480,21 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c double destination_x_i = destination_x[i]; double destination_y_i = destination_y[i]; + // # 12 MULTs, 4 ADDs double w_norm_inv = fast_inv_sqrt(w_x_i * w_x_i + w_y_i * w_y_i); + // # 1 MULT double correction_factor = min(1.0, v_max_i * w_norm_inv); + // # 2 MULTs curr_vel_x_i = w_x_i * correction_factor; curr_vel_y_i = w_y_i * correction_factor; + // # 2 MULTs, 2 ADDs pos_x_i = pos_x_i + curr_vel_x_i * dt; pos_y_i = pos_y_i + curr_vel_y_i * dt; - if (!color_i && pos_x_i > (BOARD_LENGTH - 1.5)) { + if (!color_i && pos_x_i > (BOARD_LENGTH_MINUS_ONE_POINT_FIVE)) { pos_x_i = 1.0; destination_y_i = pos_y_i; w_x_i = desired_v0_i; @@ -413,7 +503,7 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c curr_vel_y_i = w_y_i; } if (color_i && pos_x_i < 1.5) { - pos_x_i = BOARD_LENGTH - 1.0; + pos_x_i = BOARD_LENGTH_MINUS_ONE; destination_y_i = pos_y_i; w_x_i = -desired_v0_i; w_y_i = 0.0; @@ -423,16 +513,24 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c pos_y_i = clamp(pos_y_i, WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); + // # 2 ADDs double ex = destination_x_i - pos_x_i; double ey = destination_y_i - pos_y_i; + // # 12 MULTs, 4 ADDs double e_norm_inv = fast_inv_sqrt(ex * ex + ey * ey); + // # 2 MULTs e_x_i = ex * e_norm_inv; e_y_i = ey * e_norm_inv; + // # 2 MULTs, 1 ADD double velocity_norm_sq = curr_vel_x_i * curr_vel_x_i + curr_vel_y_i * curr_vel_y_i; + + // # 1 MULT double sb_sq_i = velocity_norm_sq * delta_t_sq; + + // # 1 SQRT double velocity_norm_mul_delta_t = sqrt(sb_sq_i); curr_vel_x[i] = curr_vel_x_i; @@ -450,6 +548,8 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c destination_y[i] = destination_y_i; sb_sq[i] = sb_sq_i; + + // # 2 MULTs sb_e_x[i] = e_x_i * velocity_norm_mul_delta_t; sb_e_y[i] = e_y_i * velocity_norm_mul_delta_t; diff --git a/variants/variant_inlining_8_SoA_AVX512_polyexp_moreavx.cpp b/variants/variant_inlining_8_SoA_AVX512_polyexp_moreavx.cpp index ceab1cb..7b51d9a 100644 --- a/variants/variant_inlining_8_SoA_AVX512_polyexp_moreavx.cpp +++ b/variants/variant_inlining_8_SoA_AVX512_polyexp_moreavx.cpp @@ -13,6 +13,8 @@ #define SEED 42 #define BOARD_WIDTH 10.0 #define BOARD_LENGTH 50.0 +#define BOARD_LENGTH_MINUS_ONE BOARD_LENGTH - 1.0 +#define BOARD_LENGTH_MINUS_ONE_POINT_FIVE BOARD_LENGTH - 1.5 #define WALL_EPS 1e-3 #define BOARD_WIDTH_MINUS_WALL_EPS 9.999 @@ -162,23 +164,42 @@ Pedestrian *init_pedestrians(int n_p) { Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } +// # 128 MULTs, 112 ADDs static inline __m512d _avx512_exp_pd(__m512d x) { const __m512d log2e = _mm512_set1_pd(1.4426950408889634); + + // # 8 MULTs __m512d nf = _mm512_roundscale_pd(_mm512_mul_pd(x, log2e), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); const __m512d ln2 = _mm512_set1_pd(0.6931471805599453); + + // # 8 MULTs, 8 ADDs __m512d r = _mm512_fnmadd_pd(nf, ln2, x); - const __m512d c7 = _mm512_set1_pd(1.0 / 5040.0); - const __m512d c6 = _mm512_set1_pd(1.0 / 720.0); - const __m512d c5 = _mm512_set1_pd(1.0 / 120.0); - const __m512d c4 = _mm512_set1_pd(1.0 / 24.0); - const __m512d c3 = _mm512_set1_pd(1.0 / 6.0); - const __m512d c2 = _mm512_set1_pd(0.5); - const __m512d c1 = _mm512_set1_pd(1.0); - const __m512d c0 = _mm512_set1_pd(1.0); + const __m512d c13 = _mm512_set1_pd(c13_scalar); + const __m512d c12 = _mm512_set1_pd(c12_scalar); + const __m512d c11 = _mm512_set1_pd(c11_scalar); + const __m512d c10 = _mm512_set1_pd(c10_scalar); + const __m512d c9 = _mm512_set1_pd(c9_scalar); + const __m512d c8 = _mm512_set1_pd(c8_scalar); + const __m512d c7 = _mm512_set1_pd(c7_scalar); + const __m512d c6 = _mm512_set1_pd(c6_scalar); + const __m512d c5 = _mm512_set1_pd(c5_scalar); + const __m512d c4 = _mm512_set1_pd(c4_scalar); + const __m512d c3 = _mm512_set1_pd(c3_scalar); + const __m512d c2 = _mm512_set1_pd(c2_scalar); + const __m512d c1 = _mm512_set1_pd(c1_scalar); + const __m512d c0 = _mm512_set1_pd(c0_scalar); - __m512d p = c7; + __m512d p = c13; + + // # 104 MULTs, 104 ADDs + p = _mm512_fmadd_pd(p, r, c12); + p = _mm512_fmadd_pd(p, r, c11); + p = _mm512_fmadd_pd(p, r, c10); + p = _mm512_fmadd_pd(p, r, c9); + p = _mm512_fmadd_pd(p, r, c8); + p = _mm512_fmadd_pd(p, r, c7); p = _mm512_fmadd_pd(p, r, c6); p = _mm512_fmadd_pd(p, r, c5); p = _mm512_fmadd_pd(p, r, c4); @@ -204,6 +225,7 @@ static inline __m512d _avx512_exp_pd(__m512d x) { __m512d pow2n = _mm512_castsi512_pd(scaled); + // # 8 MULTs return _mm512_mul_pd(p, pow2n); } @@ -240,6 +262,26 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c const __m512d v_np = _mm512_set1_pd(n_p); + // # ADDs: n_iter * n_p * 20 + + // # n_iter * n_p * (n_p_pad / 8) * 232 + + // # n_iter * n_p * board.n_obstacles * 10 + + // # n_iter * (n_p_pad / 8) * 56 + + // # MULTs: n_iter * n_p * 4 + + // # n_iter * n_p * (n_p_pad / 8) * 320 + + // # n_iter * n_p * board.n_obstacles * 13 + + // # n_iter * (n_p_pad / 8) * 120 + + // # DIVs: n_iter * n_p * (n_p_pad / 8) * 8 + + // # n_iter * n_p * board.n_obstacles + + // # n_iter * (n_p_pad / 8) * 16 + + // # SQRTs: n_iter * n_p * (n_p_pad / 8) * 24 + + // # n_iter * n_p * board.n_obstacles + + // # n_iter * (n_p_pad / 8) * 24 + + // # EXPs: n_iter * n_p * board.n_obstacles + for (int t = 0; t < n_iter; t++) { for (int i = 0; i < n_p; i++) { @@ -251,6 +293,7 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c double curr_vel_x_i = curr_vel_x[i]; double curr_vel_y_i = curr_vel_y[i]; + // # 4 MULTs, 2 ADDs double f_alpha_dt_x = (e_x_i * desired_v0_i - curr_vel_x_i) * dt_times_tau_alpha_inv; double f_alpha_dt_y = (e_y_i * desired_v0_i - curr_vel_y_i) * dt_times_tau_alpha_inv; @@ -264,6 +307,8 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512d acc_y = _mm512_setzero_pd(); for (int j = 0; j < n_p_pad; j += 8) { + + // # 8 ADDs __m512d j_idx = _mm512_add_pd(_mm512_set1_pd((double)j), lane_off); __mmask8 m_neq_i = _mm512_cmp_pd_mask(j_idx, v_i, _CMP_NEQ_OQ); @@ -276,35 +321,63 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512d sbe_jy = _mm512_loadu_pd(&sb_e_y[j]); __m512d sb_jsq = _mm512_loadu_pd(&sb_sq[j]); + // # 16 ADDs __m512d r_ab_x = _mm512_sub_pd(pix, pjx); __m512d r_ab_y = _mm512_sub_pd(piy, pjy); + + // # 16 MULTs, 8 ADDs __m512d r_ab_n2 = _mm512_fmadd_pd(r_ab_x, r_ab_x, _mm512_mul_pd(r_ab_y, r_ab_y)); + + // # 8 SQRTs __m512d r_ab_n = _mm512_sqrt_pd(r_ab_n2); + // # 16 ADDs __m512d r_ab2_x = _mm512_sub_pd(r_ab_x, sbe_jx); __m512d r_ab2_y = _mm512_sub_pd(r_ab_y, sbe_jy); + + // # 16 MULTs, 8 ADDs __m512d r_ab2_n2 = _mm512_fmadd_pd(r_ab2_x, r_ab2_x, _mm512_mul_pd(r_ab2_y, r_ab2_y)); + + // # 8 SQRTs __m512d r_ab2_n = _mm512_sqrt_pd(r_ab2_n2); + // # 8 ADDs __m512d r_sum = _mm512_add_pd(r_ab_n, r_ab2_n); + + // # 8 MULTs, 8 ADDs __m512d two_b_sq = _mm512_fmsub_pd(r_sum, r_sum, sb_jsq); + + // # 8 SQRTs __m512d two_b = _mm512_sqrt_pd(two_b_sq); + // # 8 MULTs __m512d e_arg = _mm512_mul_pd(two_b, v_neg_2s_inv); + + // # 128 MULTs, 112 ADDs __m512d e_val = _avx512_exp_pd(e_arg); + // # 32 MULTs __m512d numer = _mm512_mul_pd(_mm512_mul_pd(r_sum, v_neg_v0_div_2s), e_val); __m512d denom = _mm512_mul_pd(_mm512_mul_pd(two_b, r_ab_n), r_ab2_n); + + // # 8 DIVs __m512d smc = _mm512_div_pd(numer, denom); + // # 16 MULTs __m512d sm_r_ab = _mm512_mul_pd(smc, r_ab2_n); __m512d sm_r_ab2 = _mm512_mul_pd(smc, r_ab_n); + // # 32 MULTs, 16 ADDs __m512d f_x = _mm512_fmadd_pd(r_ab2_x, sm_r_ab2, _mm512_mul_pd(r_ab_x, sm_r_ab)); __m512d f_y = _mm512_fmadd_pd(r_ab2_y, sm_r_ab2, _mm512_mul_pd(r_ab_y, sm_r_ab)); + // # 24 MULTs, 8 ADDs __m512d a = _mm512_mul_pd(_mm512_fmadd_pd(eix, f_x, _mm512_mul_pd(eiy, f_y)), v_cos_phi_inv); + + // # 8 MULTs __m512d a_sq = _mm512_mul_pd(a, a); + + // # 16 MULTs, 8 ADDs __m512d b_sq = _mm512_fmadd_pd(f_x, f_x, _mm512_mul_pd(f_y, f_y)); __mmask8 k_ge = _mm512_cmp_pd_mask(a, v_zero, _CMP_GE_OQ); @@ -314,18 +387,23 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512d f_x_safe = _mm512_maskz_mov_pd(active, f_x); __m512d f_y_safe = _mm512_maskz_mov_pd(active, f_y); + + // # 16 MULTs, 16 ADDs acc_x = _mm512_fmadd_pd(f_x_safe, w_val, acc_x); acc_y = _mm512_fmadd_pd(f_y_safe, w_val, acc_y); } + // # 16 ADDS f_alpha_dt_x += _mm512_reduce_add_pd(acc_x); f_alpha_dt_y += _mm512_reduce_add_pd(acc_y); for (int k = 0; k < board.n_obstacles; k++) { + // # 2 ADDs double v1_x = pos_x_i - board.obstacles[k].start_x; double v1_y = pos_y_i - board.obstacles[k].start_y; + // # 3 MULTs, 1 ADD double projection = (v1_x * board.obstacles[k].obstacle_v_x + v1_y * board.obstacles[k].obstacle_v_y) * board.obstacles[k].length_sq_inv; if (projection < 0.0) @@ -333,11 +411,17 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c else if (projection > 1.0) projection = 1.0; + // # 4 ADDs, 2 MULTs double r_aB_x = pos_x_i - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); double r_aB_y = pos_y_i - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); + // # 1 SQRT, 2 MULTs, 1 ADD double r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); + + // # 2 MULTs, 1 EXP, 1 DIV double scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; + + // # 2 MULTs double f_alpha_B_neg_x = r_aB_x * scalar_mult; double f_alpha_B_neg_y = r_aB_y * scalar_mult; @@ -346,10 +430,12 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c if (e_dot_f < cos_phi) w_val = c_neg_times_dt; + // # 2 MULTs, 2 ADDs f_alpha_dt_x += f_alpha_B_neg_x * w_val; f_alpha_dt_y += f_alpha_B_neg_y * w_val; } + // # 2 ADDs w_x[i] += f_alpha_dt_x; w_y[i] += f_alpha_dt_y; } @@ -367,19 +453,27 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m256i color_i_vec = _mm256_loadu_si256((__m256i *)&color[i]); + // # 16 MULTs, 8 ADDs __m512d w_norm_sq = _mm512_fmadd_pd(w_x_i_vec, w_x_i_vec, _mm512_mul_pd(w_y_i_vec, w_y_i_vec)); + + // # 8 SQRTs __m512d w_norm = _mm512_sqrt_pd(w_norm_sq); + + // # 8 DIVs __m512d correction_factor = _mm512_min_pd(_mm512_set1_pd(1.0), _mm512_div_pd(v_max_i_vec, w_norm)); + // # 16 MULTs __m512d curr_vel_x_i_vec = _mm512_mul_pd(w_x_i_vec, correction_factor); __m512d curr_vel_y_i_vec = _mm512_mul_pd(w_y_i_vec, correction_factor); __m512d dt_vec = _mm512_set1_pd(dt); + + // # 16 MULTs, 16 ADDs pos_x_i_vec = _mm512_fmadd_pd(curr_vel_x_i_vec, dt_vec, pos_x_i_vec); pos_y_i_vec = _mm512_fmadd_pd(curr_vel_y_i_vec, dt_vec, pos_y_i_vec); __mmask8 cond_1_left = _mm256_cmpeq_epi32_mask(color_i_vec, _mm256_setzero_si256()); - __mmask8 cond_1_right = _mm512_cmp_pd_mask(pos_x_i_vec, _mm512_set1_pd(BOARD_LENGTH - 1.5), _CMP_GT_OQ); + __mmask8 cond_1_right = _mm512_cmp_pd_mask(pos_x_i_vec, _mm512_set1_pd(BOARD_LENGTH_MINUS_ONE_POINT_FIVE), _CMP_GT_OQ); __mmask8 cond_1 = cond_1_left & cond_1_right; pos_x_i_vec = _mm512_mask_blend_pd(cond_1, pos_x_i_vec, _mm512_set1_pd(1.0)); @@ -404,16 +498,30 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c pos_y_i_vec = _mm512_max_pd(pos_y_i_vec, _mm512_set1_pd(WALL_EPS)); pos_y_i_vec = _mm512_min_pd(pos_y_i_vec, _mm512_set1_pd(BOARD_WIDTH_MINUS_WALL_EPS)); + // # 16 ADDs __m512d ex_vec = _mm512_sub_pd(destination_x_i_vec, pos_x_i_vec); __m512d ey_vec = _mm512_sub_pd(destination_y_i_vec, pos_y_i_vec); + + // # 16 MULTs, 8 ADDs __m512d e_norm_sq = _mm512_fmadd_pd(ex_vec, ex_vec, _mm512_mul_pd(ey_vec, ey_vec)); + + // # 8 SQRTs __m512d e_norm = _mm512_sqrt_pd(e_norm_sq); + + // # 8 DIVs __m512d e_norm_inv = _mm512_div_pd(_mm512_set1_pd(1.0), e_norm); + + // # 16 MULT __m512d e_x_i_vec = _mm512_mul_pd(ex_vec, e_norm_inv); __m512d e_y_i_vec = _mm512_mul_pd(ey_vec, e_norm_inv); + // # 16 MULTs, 8 ADDs __m512d vel_norm_sq = _mm512_fmadd_pd(curr_vel_x_i_vec, curr_vel_x_i_vec, _mm512_mul_pd(curr_vel_y_i_vec, curr_vel_y_i_vec)); + + // # 8 MULTs __m512d sb_sq_i_vec = _mm512_mul_pd(vel_norm_sq, _mm512_set1_pd(delta_t_sq)); + + // # 8 SQRTs __m512d vel_norm_dt = _mm512_sqrt_pd(sb_sq_i_vec); _mm512_storeu_pd(&curr_vel_x[i], curr_vel_x_i_vec); @@ -426,6 +534,8 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c _mm512_storeu_pd(&e_y[i], e_y_i_vec); _mm512_storeu_pd(&destination_y[i], destination_y_i_vec); _mm512_storeu_pd(&sb_sq[i], sb_sq_i_vec); + + // # 16 MULTs _mm512_storeu_pd(&sb_e_x[i], _mm512_mul_pd(e_x_i_vec, vel_norm_dt)); _mm512_storeu_pd(&sb_e_y[i], _mm512_mul_pd(e_y_i_vec, vel_norm_dt)); } diff --git a/variants/variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2.cpp b/variants/variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2.cpp index b6b8d2d..486512c 100644 --- a/variants/variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2.cpp +++ b/variants/variant_inlining_8_SoA_AVX512_polyexp_moreavx_ilp_2.cpp @@ -13,6 +13,8 @@ #define SEED 42 #define BOARD_WIDTH 10.0 #define BOARD_LENGTH 50.0 +#define BOARD_LENGTH_MINUS_ONE BOARD_LENGTH - 1.0 +#define BOARD_LENGTH_MINUS_ONE_POINT_FIVE BOARD_LENGTH - 1.5 #define WALL_EPS 1e-3 #define BOARD_WIDTH_MINUS_WALL_EPS 9.999 @@ -162,23 +164,42 @@ Pedestrian *init_pedestrians(int n_p) { Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } +// # 128 MULTs, 112 ADDs static inline __m512d _avx512_exp_pd(__m512d x) { const __m512d log2e = _mm512_set1_pd(1.4426950408889634); + + // # 8 MULTs __m512d nf = _mm512_roundscale_pd(_mm512_mul_pd(x, log2e), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC); const __m512d ln2 = _mm512_set1_pd(0.6931471805599453); + + // # 8 MULTs, 8 ADDs __m512d r = _mm512_fnmadd_pd(nf, ln2, x); - const __m512d c7 = _mm512_set1_pd(1.0 / 5040.0); - const __m512d c6 = _mm512_set1_pd(1.0 / 720.0); - const __m512d c5 = _mm512_set1_pd(1.0 / 120.0); - const __m512d c4 = _mm512_set1_pd(1.0 / 24.0); - const __m512d c3 = _mm512_set1_pd(1.0 / 6.0); - const __m512d c2 = _mm512_set1_pd(0.5); - const __m512d c1 = _mm512_set1_pd(1.0); - const __m512d c0 = _mm512_set1_pd(1.0); + const __m512d c13 = _mm512_set1_pd(c13_scalar); + const __m512d c12 = _mm512_set1_pd(c12_scalar); + const __m512d c11 = _mm512_set1_pd(c11_scalar); + const __m512d c10 = _mm512_set1_pd(c10_scalar); + const __m512d c9 = _mm512_set1_pd(c9_scalar); + const __m512d c8 = _mm512_set1_pd(c8_scalar); + const __m512d c7 = _mm512_set1_pd(c7_scalar); + const __m512d c6 = _mm512_set1_pd(c6_scalar); + const __m512d c5 = _mm512_set1_pd(c5_scalar); + const __m512d c4 = _mm512_set1_pd(c4_scalar); + const __m512d c3 = _mm512_set1_pd(c3_scalar); + const __m512d c2 = _mm512_set1_pd(c2_scalar); + const __m512d c1 = _mm512_set1_pd(c1_scalar); + const __m512d c0 = _mm512_set1_pd(c0_scalar); - __m512d p = c7; + __m512d p = c13; + + // # 104 MULTs, 104 ADDs + p = _mm512_fmadd_pd(p, r, c12); + p = _mm512_fmadd_pd(p, r, c11); + p = _mm512_fmadd_pd(p, r, c10); + p = _mm512_fmadd_pd(p, r, c9); + p = _mm512_fmadd_pd(p, r, c8); + p = _mm512_fmadd_pd(p, r, c7); p = _mm512_fmadd_pd(p, r, c6); p = _mm512_fmadd_pd(p, r, c5); p = _mm512_fmadd_pd(p, r, c4); @@ -204,6 +225,7 @@ static inline __m512d _avx512_exp_pd(__m512d x) { __m512d pow2n = _mm512_castsi512_pd(scaled); + // # 8 MULTs return _mm512_mul_pd(p, pow2n); } @@ -242,9 +264,30 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c const __m512d v_np = _mm512_set1_pd((float)n_p); const __m512d v_exp_min = _mm512_set1_pd(-87.0f); + // # ADDs: n_iter * n_p * 36 + + // # n_iter * n_p * (n_p_pad / 16) * 464 + + // # n_iter * n_p * board.n_obstacles * 10 + + // # n_iter * (n_p_pad / 8) * 56 + + // # MULTs: n_iter * n_p * 4 + + // # n_iter * n_p * (n_p_pad / 16) * 640 + + // # n_iter * n_p * board.n_obstacles * 13 + + // # n_iter * (n_p_pad / 8) * 120 + + // # DIVs: n_iter * n_p * (n_p_pad / 16) * 16 + + // # n_iter * n_p * board.n_obstacles + + // # n_iter * (n_p_pad / 8) * 16 + + // # SQRTs: n_iter * n_p * (n_p_pad / 16) * 48 + + // # n_iter * n_p * board.n_obstacles + + // # n_iter * (n_p_pad / 8) * 24 + + // # EXPs: n_iter * n_p * board.n_obstacles + for (int t = 0; t < n_iter; t++) { for (int i = 0; i < n_p; i++) { + double pos_x_i = pos_x[i]; double pos_y_i = pos_y[i]; double e_x_i = e_x[i]; @@ -253,6 +296,7 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c double curr_vel_x_i = curr_vel_x[i]; double curr_vel_y_i = curr_vel_y[i]; + // # 4 MULTs, 2 ADDs double f_alpha_dt_x = (e_x_i * desired_v0_i - curr_vel_x_i) * dt_times_tau_alpha_inv; double f_alpha_dt_y = (e_y_i * desired_v0_i - curr_vel_y_i) * dt_times_tau_alpha_inv; @@ -268,6 +312,8 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512d acc_y_1 = _mm512_setzero_pd(); for (int j = 0; j < n_p_pad; j += 16) { + + // # 16 ADDs __m512d j_idx_0 = _mm512_add_pd(_mm512_set1_pd((double)j), lane_off); __m512d j_idx_1 = _mm512_add_pd(_mm512_set1_pd((double)j + 8), lane_off); @@ -295,81 +341,105 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512d sb_jsq_0 = _mm512_loadu_pd(&sb_sq[j]); __m512d sb_jsq_1 = _mm512_loadu_pd(&sb_sq[j + 8]); + // # 16 ADDs __m512d r_ab_x_0 = _mm512_sub_pd(pix, pjx_0); __m512d r_ab_x_1 = _mm512_sub_pd(pix, pjx_1); + // # 16 ADDs __m512d r_ab_y_0 = _mm512_sub_pd(piy, pjy_0); __m512d r_ab_y_1 = _mm512_sub_pd(piy, pjy_1); + // # 32 MULTs, 16 ADDs __m512d r_ab_n2_0 = _mm512_fmadd_pd(r_ab_x_0, r_ab_x_0, _mm512_mul_pd(r_ab_y_0, r_ab_y_0)); __m512d r_ab_n2_1 = _mm512_fmadd_pd(r_ab_x_1, r_ab_x_1, _mm512_mul_pd(r_ab_y_1, r_ab_y_1)); + // # 16 SQRTs __m512d r_ab_n_0 = _mm512_sqrt_pd(r_ab_n2_0); __m512d r_ab_n_1 = _mm512_sqrt_pd(r_ab_n2_1); + // # 16 ADDs __m512d r_ab2_x_0 = _mm512_sub_pd(r_ab_x_0, sbe_jx_0); __m512d r_ab2_x_1 = _mm512_sub_pd(r_ab_x_1, sbe_jx_1); + // # 16 ADDs __m512d r_ab2_y_0 = _mm512_sub_pd(r_ab_y_0, sbe_jy_0); __m512d r_ab2_y_1 = _mm512_sub_pd(r_ab_y_1, sbe_jy_1); + // # 32 MULTs, 16 ADDs __m512d r_ab2_n2_0 = _mm512_fmadd_pd(r_ab2_x_0, r_ab2_x_0, _mm512_mul_pd(r_ab2_y_0, r_ab2_y_0)); __m512d r_ab2_n2_1 = _mm512_fmadd_pd(r_ab2_x_1, r_ab2_x_1, _mm512_mul_pd(r_ab2_y_1, r_ab2_y_1)); + // # 16 SQRTs __m512d r_ab2_n_0 = _mm512_sqrt_pd(r_ab2_n2_0); __m512d r_ab2_n_1 = _mm512_sqrt_pd(r_ab2_n2_1); + // # 16 ADDs __m512d r_sum_0 = _mm512_add_pd(r_ab_n_0, r_ab2_n_0); __m512d r_sum_1 = _mm512_add_pd(r_ab_n_1, r_ab2_n_1); + // # 16 MULTs, 16 ADDs __m512d two_b_sq_0 = _mm512_fmsub_pd(r_sum_0, r_sum_0, sb_jsq_0); __m512d two_b_sq_1 = _mm512_fmsub_pd(r_sum_1, r_sum_1, sb_jsq_1); + // # 16 SQRTs __m512d two_b_0 = _mm512_sqrt_pd(two_b_sq_0); __m512d two_b_1 = _mm512_sqrt_pd(two_b_sq_1); + // # 16 MULTs __m512d e_arg_0 = _mm512_mul_pd(two_b_0, v_neg_2s_inv); __m512d e_arg_1 = _mm512_mul_pd(two_b_1, v_neg_2s_inv); e_arg_0 = _mm512_max_pd(e_arg_0, v_exp_min); e_arg_1 = _mm512_max_pd(e_arg_1, v_exp_min); + // # 256 MULTs, 224 ADDs __m512d e_val_0 = _avx512_exp_pd(e_arg_0); __m512d e_val_1 = _avx512_exp_pd(e_arg_1); + // # 32 MULTs __m512d numer_0 = _mm512_mul_pd(_mm512_mul_pd(r_sum_0, v_neg_v0_div_2s), e_val_0); __m512d numer_1 = _mm512_mul_pd(_mm512_mul_pd(r_sum_1, v_neg_v0_div_2s), e_val_1); + // # 32 MULTs __m512d denom_0 = _mm512_mul_pd(_mm512_mul_pd(two_b_0, r_ab_n_0), r_ab2_n_0); __m512d denom_1 = _mm512_mul_pd(_mm512_mul_pd(two_b_1, r_ab_n_1), r_ab2_n_1); __m512d denom_safe_0 = _mm512_mask_blend_pd(active_0, v_one, denom_0); __m512d denom_safe_1 = _mm512_mask_blend_pd(active_1, v_one, denom_1); + // # 16 DIVs __m512d smc_0 = _mm512_div_pd(numer_0, denom_safe_0); __m512d smc_1 = _mm512_div_pd(numer_1, denom_safe_1); + // # 16 MULTs __m512d sm_r_ab_0 = _mm512_mul_pd(smc_0, r_ab2_n_0); __m512d sm_r_ab_1 = _mm512_mul_pd(smc_1, r_ab2_n_1); + // # 16 MULTs __m512d sm_r_ab2_0 = _mm512_mul_pd(smc_0, r_ab_n_0); __m512d sm_r_ab2_1 = _mm512_mul_pd(smc_1, r_ab_n_1); + // # 32 MULTs, 16 ADDs __m512d f_x_0 = _mm512_fmadd_pd(r_ab2_x_0, sm_r_ab2_0, _mm512_mul_pd(r_ab_x_0, sm_r_ab_0)); __m512d f_x_1 = _mm512_fmadd_pd(r_ab2_x_1, sm_r_ab2_1, _mm512_mul_pd(r_ab_x_1, sm_r_ab_1)); + // # 32 MULTs, 16 ADDs __m512d f_y_0 = _mm512_fmadd_pd(r_ab2_y_0, sm_r_ab2_0, _mm512_mul_pd(r_ab_y_0, sm_r_ab_0)); __m512d f_y_1 = _mm512_fmadd_pd(r_ab2_y_1, sm_r_ab2_1, _mm512_mul_pd(r_ab_y_1, sm_r_ab_1)); + // # 32 MULTs, 16 ADDs __m512d f_norm_sq_0 = _mm512_fmadd_pd(f_x_0, f_x_0, _mm512_mul_pd(f_y_0, f_y_0)); __m512d f_norm_sq_1 = _mm512_fmadd_pd(f_x_1, f_x_1, _mm512_mul_pd(f_y_1, f_y_1)); + // # 16 MULTs __m512d rhs_0 = _mm512_mul_pd(f_norm_sq_0, v_cos_phi_sq); __m512d rhs_1 = _mm512_mul_pd(f_norm_sq_1, v_cos_phi_sq); + // # 32 MULTs, 16 ADDs __m512d e_dot_f_0 = _mm512_fmadd_pd(eix, f_x_0, _mm512_mul_pd(eiy, f_y_0)); __m512d e_dot_f_1 = _mm512_fmadd_pd(eix, f_x_1, _mm512_mul_pd(eiy, f_y_1)); + // # 16 MULTs __m512d e_dot_f_sq_0 = _mm512_mul_pd(e_dot_f_0, e_dot_f_0); __m512d e_dot_f_sq_1 = _mm512_mul_pd(e_dot_f_1, e_dot_f_1); @@ -391,21 +461,26 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m512d f_y_safe_0 = _mm512_maskz_mov_pd(active_0, f_y_0); __m512d f_y_safe_1 = _mm512_maskz_mov_pd(active_1, f_y_1); + // # 16 MULTs, 16 ADDs acc_x_0 = _mm512_fmadd_pd(f_x_safe_0, w_val_0, acc_x_0); acc_x_1 = _mm512_fmadd_pd(f_x_safe_1, w_val_1, acc_x_1); + // # 16 MULTs, 16 ADDs acc_y_0 = _mm512_fmadd_pd(f_y_safe_0, w_val_0, acc_y_0); acc_y_1 = _mm512_fmadd_pd(f_y_safe_1, w_val_1, acc_y_1); } + // # 32 ADDs f_alpha_dt_x += _mm512_reduce_add_pd(_mm512_add_pd(acc_x_0, acc_x_1)); f_alpha_dt_y += _mm512_reduce_add_pd(_mm512_add_pd(acc_y_0, acc_y_1)); for (int k = 0; k < board.n_obstacles; k++) { + // # 2 ADDs double v1_x = pos_x_i - board.obstacles[k].start_x; double v1_y = pos_y_i - board.obstacles[k].start_y; + // # 3 MULTs, 1 ADD double projection = (v1_x * board.obstacles[k].obstacle_v_x + v1_y * board.obstacles[k].obstacle_v_y) * board.obstacles[k].length_sq_inv; if (projection < 0.0) @@ -413,11 +488,17 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c else if (projection > 1.0) projection = 1.0; + // # 4 ADDs, 2 MULTs double r_aB_x = pos_x_i - (board.obstacles[k].start_x + board.obstacles[k].obstacle_v_x * projection); double r_aB_y = pos_y_i - (board.obstacles[k].start_y + board.obstacles[k].obstacle_v_y * projection); + // # 1 SQRT, 2 MULTs, 1 ADD double r_aB_norm = sqrt(r_aB_x * r_aB_x + r_aB_y * r_aB_y); + + // # 2 MULTs, 1 EXP, 1 DIV double scalar_mult = (NEG_U0_AB_div_R * exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; + + // # 2 MULTs double f_alpha_B_neg_x = r_aB_x * scalar_mult; double f_alpha_B_neg_y = r_aB_y * scalar_mult; @@ -426,10 +507,12 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c if (e_dot_f < cos_phi) w_val = c_neg_times_dt; + // # 2 MULTs, 2 ADDs f_alpha_dt_x += f_alpha_B_neg_x * w_val; f_alpha_dt_y += f_alpha_B_neg_y * w_val; } + // # 2 ADDs w_x[i] += f_alpha_dt_x; w_y[i] += f_alpha_dt_y; } @@ -447,19 +530,27 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c __m256i color_i_vec = _mm256_loadu_si256((__m256i *)&color[i]); + // # 16 MULTs, 8 ADDs __m512d w_norm_sq = _mm512_fmadd_pd(w_x_i_vec, w_x_i_vec, _mm512_mul_pd(w_y_i_vec, w_y_i_vec)); + + // # 8 SQRTs __m512d w_norm = _mm512_sqrt_pd(w_norm_sq); + + // # 8 DIVs __m512d correction_factor = _mm512_min_pd(_mm512_set1_pd(1.0), _mm512_div_pd(v_max_i_vec, w_norm)); + // # 16 MULTs __m512d curr_vel_x_i_vec = _mm512_mul_pd(w_x_i_vec, correction_factor); __m512d curr_vel_y_i_vec = _mm512_mul_pd(w_y_i_vec, correction_factor); __m512d dt_vec = _mm512_set1_pd(dt); + + // # 16 MULTs, 16 ADDs pos_x_i_vec = _mm512_fmadd_pd(curr_vel_x_i_vec, dt_vec, pos_x_i_vec); pos_y_i_vec = _mm512_fmadd_pd(curr_vel_y_i_vec, dt_vec, pos_y_i_vec); __mmask8 cond_1_left = _mm256_cmpeq_epi32_mask(color_i_vec, _mm256_setzero_si256()); - __mmask8 cond_1_right = _mm512_cmp_pd_mask(pos_x_i_vec, _mm512_set1_pd(BOARD_LENGTH - 1.5), _CMP_GT_OQ); + __mmask8 cond_1_right = _mm512_cmp_pd_mask(pos_x_i_vec, _mm512_set1_pd(BOARD_LENGTH_MINUS_ONE_POINT_FIVE), _CMP_GT_OQ); __mmask8 cond_1 = cond_1_left & cond_1_right; pos_x_i_vec = _mm512_mask_blend_pd(cond_1, pos_x_i_vec, _mm512_set1_pd(1.0)); @@ -484,16 +575,30 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c pos_y_i_vec = _mm512_max_pd(pos_y_i_vec, _mm512_set1_pd(WALL_EPS)); pos_y_i_vec = _mm512_min_pd(pos_y_i_vec, _mm512_set1_pd(BOARD_WIDTH_MINUS_WALL_EPS)); + // # 16 ADDs __m512d ex_vec = _mm512_sub_pd(destination_x_i_vec, pos_x_i_vec); __m512d ey_vec = _mm512_sub_pd(destination_y_i_vec, pos_y_i_vec); + + // # 16 MULTs, 8 ADDs __m512d e_norm_sq = _mm512_fmadd_pd(ex_vec, ex_vec, _mm512_mul_pd(ey_vec, ey_vec)); + + // # 8 SQRTs __m512d e_norm = _mm512_sqrt_pd(e_norm_sq); + + // # 8 DIVs __m512d e_norm_inv = _mm512_div_pd(_mm512_set1_pd(1.0), e_norm); + + // # 16 MULT __m512d e_x_i_vec = _mm512_mul_pd(ex_vec, e_norm_inv); __m512d e_y_i_vec = _mm512_mul_pd(ey_vec, e_norm_inv); + // # 16 MULTs, 8 ADDs __m512d vel_norm_sq = _mm512_fmadd_pd(curr_vel_x_i_vec, curr_vel_x_i_vec, _mm512_mul_pd(curr_vel_y_i_vec, curr_vel_y_i_vec)); + + // # 8 MULTs __m512d sb_sq_i_vec = _mm512_mul_pd(vel_norm_sq, _mm512_set1_pd(delta_t_sq)); + + // # 8 SQRTs __m512d vel_norm_dt = _mm512_sqrt_pd(sb_sq_i_vec); _mm512_storeu_pd(&curr_vel_x[i], curr_vel_x_i_vec); @@ -506,6 +611,8 @@ int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, c _mm512_storeu_pd(&e_y[i], e_y_i_vec); _mm512_storeu_pd(&destination_y[i], destination_y_i_vec); _mm512_storeu_pd(&sb_sq[i], sb_sq_i_vec); + + // # 16 MULTs _mm512_storeu_pd(&sb_e_x[i], _mm512_mul_pd(e_x_i_vec, vel_norm_dt)); _mm512_storeu_pd(&sb_e_y[i], _mm512_mul_pd(e_y_i_vec, vel_norm_dt)); } diff --git a/variants/variant_lut_exp_flopcount.cpp b/variants/variant_lut_exp_flopcount.cpp deleted file mode 100644 index 86036ef..0000000 --- a/variants/variant_lut_exp_flopcount.cpp +++ /dev/null @@ -1,492 +0,0 @@ -// This file is copied from the variant_baseline and then modified -// The goal is that we use a look up table to precompute expensive calculations -// especially to precompute the exp calls -// we call exp(two_b * NEG_TWO_SIGMA_INV) -// which is always negativ -// if a value is smaller then -40 its so small that we can ignore it -// for the other values we will create a lookup table - -#include "../headers/board.hpp" -#include "../headers/constants.hpp" -#include "../headers/pedestrian.hpp" -#include "../headers/vector2d.hpp" - -#include -#include -#include -#include -#include // keep — forces code uses unqualified sqrt/exp -#include -#include -#include - -#define SEED 42 -#define BOARD_WIDTH 10.0 -#define BOARD_LENGTH 50.0 -#define WALL_EPS 1e-3 -#define BOARD_WIDTH_MINUS_WALL_EPS 9.999 - -#ifndef RANDOM_SEED -#define RANDOM_SEED 0 -#endif - -#ifndef BENCHMARK -#define BENCHMARK 0 -#endif - -using namespace std; - -// exp lookup table -constexpr int EXP_LUT_SIZE = 69000; -constexpr double EXP_LUT_MIN = -40.0; -constexpr double EXP_LUT_MAX = 0.0; -constexpr double EXP_LUT_INV_STEP = (EXP_LUT_SIZE - 1) / (EXP_LUT_MAX - EXP_LUT_MIN); - -static double exp_lut[EXP_LUT_SIZE]; - -struct ExpLutInit { - ExpLutInit() { - const double step = (EXP_LUT_MAX - EXP_LUT_MIN) / (EXP_LUT_SIZE - 1); - for (int i = 0; i < EXP_LUT_SIZE; i++) { - exp_lut[i] = std::exp(EXP_LUT_MIN + i * step); - } - } -}; -static ExpLutInit exp_lut_init_helper; -// i used the following things to get a better understanding of how i can solve that problem -// Tang, P. T. P. (1989). "Table-driven implementation of the exponential function in IEEE floating-point arithmetic." ACM TOMS 15(2), 144-157. -// https://dl.acm.org/doi/10.1145/63522.214389 -// Cubic Hermite spline. Wikipedia. -// https://en.wikipedia.org/wiki/Cubic_Hermite_spline -inline double fast_exp(double x) { - if (x <= EXP_LUT_MIN) - return 0.0; - if (x >= EXP_LUT_MAX) - return 1.0; - - double pos = (x - EXP_LUT_MIN) * EXP_LUT_INV_STEP; - int idx = static_cast(pos); - if (idx >= EXP_LUT_SIZE - 1) - return 1.0; - - double t = pos - idx; - double y0 = exp_lut[idx]; - double y1 = exp_lut[idx + 1]; - - // For exp(x), derivative equals function value. - // In normalized parameter space (t in [0,1] across width h), - // dy/dt = h * y. No centered differences needed - we know the exact slope. - constexpr double h_step = (EXP_LUT_MAX - EXP_LUT_MIN) / (EXP_LUT_SIZE - 1); - - double t2 = t * t; - double t3 = t2 * t; - - double h00 = 2.0 * t3 - 3.0 * t2 + 1.0; - double h10 = t3 - 2.0 * t2 + t; - double h01 = -2.0 * t3 + 3.0 * t2; - double h11 = t3 - t2; - - return y0 * (h00 + h_step * h10) + y1 * (h01 + h_step * h11); -} -// forces.cpp - -// Flop count: 2 ADDs, 5 MULTs, 1 SQRT -double w(Vector2d e, Vector2d f) { - if (e.dot(f) >= f.norm() * cos_phi) - return dt_neg; - else - return c_neg_times_dt; -} - -// Flop count: 2 ADDs, 4 MULTs -Vector2d acceleration_term_dt(const Pedestrian &alpha) { - - // # 2 MULTs - Vector2d desired_velocity = alpha.e * alpha.desired_v0; - - Vector2d actual_velocity = alpha.curr_vel; - - // # 2 ADDs, 2 MULTs - Vector2d f_alpha_0_dt = (desired_velocity - actual_velocity) * dt_times_tau_alpha_inv; - - return f_alpha_0_dt; -} - -// Flop count: 12 ADDs, 23 MULTs, 1 DIV, 4 SQRTs, 1 EXP -Vector2d pedestrian_repulsion_dt(const Pedestrian &alpha, const Pedestrian &beta) { - - // # 2 ADDs - // $\vec{r}_{\alpha\beta}$ - Vector2d r_ab = alpha.curr_pos - beta.curr_pos; - - // # 1 ADD, 2 MULTs, 1 SQRT - // $\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert$ - double r_ab_norm = r_ab.norm(); - r_ab_norm = r_ab_norm > EPS ? r_ab_norm : EPS; // Avoid division by zero - - // $v_\beta \Delta t \vec{e}_\beta$ - Vector2d s_b_e = beta.s_b_e; - - // # 2 ADDs - // $\vec{r}_{\alpha\beta} - \vec{v}_{\beta}\varDelta_{t}\vec{e}_{\beta}$ - Vector2d r_ab2 = r_ab - s_b_e; - - // # 1 ADD, 2 MULTs, 1 SQRT - // $\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert$ - double r_ab2_norm = r_ab2.norm(); - r_ab2_norm = r_ab2_norm > EPS ? r_ab2_norm : EPS; // Avoid division by zero - - // # 1 ADD - // $\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert$ - double r_ab_norm_sum = r_ab_norm + r_ab2_norm; - - // # 1 ADD, 1 MULTs, 1 SQRT - // - // $2b = \sqrt{(\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert)^2 - (v_\beta \Delta t)^2}$ - // - double two_b_sq = r_ab_norm_sum * r_ab_norm_sum - beta.s_b_sq; - two_b_sq = two_b_sq > EPS_SQ ? two_b_sq : EPS_SQ; // Avoid sqrt of negative and avoid division by zero - double two_b = sqrt(two_b_sq); - - // # 5 MULTs, 1 DIV, 1 EXP - // - // $\frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert\,\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}$ - // - double scalar_mult_common = (r_ab_norm_sum / (two_b * r_ab_norm * r_ab2_norm)) * (NEG_V0_AB_div_TWO_SIGMA * fast_exp(two_b * NEG_TWO_SIGMA_INV)); - - // # 1 MULT - // - // $\frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert}$ - // - double scalar_mult_r_ab = scalar_mult_common * r_ab2_norm; - - // # 1 MULT - // - // $\frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}$ - // - double scalar_mult_r_ab2 = scalar_mult_common * r_ab_norm; - - // # 2 ADDs, 4 MULTs - // - // $\vec{-f}_{\alpha \beta}(\vec{r}_{\alpha \beta}) = \frac{-V^0_{\alpha \beta}}{2\sigma}e^{-b / \sigma} 2\grad_{\vec{r}_{\alpha \beta}}b $ - // - // - // $= \frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert}\,\vec{r}_{\alpha \beta} + \frac{-V^0_{\alpha\beta}}{2\sigma}\,e^{-b/\sigma}\,\frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} - - // v_\beta \Delta t \vec{e}_\beta \Arrowvert}\,(\vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta)$ - // - // - // - // $2\grad_{\vec{r}_{\alpha \beta}}b = \frac{(\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert)(\frac{\vec{r}_{\alpha \beta}}{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert} + \frac{\vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta}{\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert})}{2b}$ - // - // - // $= \frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert}\,\vec{r}_{\alpha \beta} + \frac{\Arrowvert \vec{r}_{\alpha \beta} \Arrowvert + \Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}{2b\,\Arrowvert \vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta \Arrowvert}\,(\vec{r}_{\alpha \beta} - v_\beta \Delta t \vec{e}_\beta)$ - // - // - Vector2d f_alpha_beta_neg = r_ab * scalar_mult_r_ab + r_ab2 * scalar_mult_r_ab2; - - // # 2 ADDs, 7 MULTs, 1 SQRT - // - // $\vec{F}_{\alpha\beta}(\vec{e}_{\alpha}, \vec{r}_{\alpha \beta}).dt = w(\vec{e}_{\alpha}, -\vec{f}_{\alpha\beta}(\vec{r}_{\alpha \beta})).\vec{f}_{\alpha\beta}(\vec{r}_{\alpha \beta}).dt$ - // - Vector2d f_alpha_beta_dt = f_alpha_beta_neg * w(alpha.e, f_alpha_beta_neg); - - return f_alpha_beta_dt; -} - -// Flop count: 10 ADDs, 18 MULTs, 1 DIVs, 2 SQRTs, 1 EXP -Vector2d obstacle_repulsion_dt(const Pedestrian &alpha, const Obstacle &B) { - - // # 7 ADDs, 5 MULTs - // $\vec{r}_{\alpha B}$ - Vector2d r_aB = alpha.curr_pos - B.find_nearest_obstacle_point(alpha.curr_pos); - - // # 1 ADD, 2 MULTs, 1 SQRT - // $\Arrowvert \vec{r}_{\alpha B} \Arrowvert$ - double r_aB_norm = r_aB.norm(); - r_aB_norm = r_aB_norm > EPS ? r_aB_norm : EPS; // Avoid division by zero - - // # 2 MULTs, 1 DIV, 1 EXP - // - // $\frac{-U^0_{\alpha B}}{R} e^{- \Arrowvert \vec{r}_{\alpha B} \Arrowvert / R}$ - // - double scalar_mult = (NEG_U0_AB_div_R * fast_exp(r_aB_norm * NEG_R_INV)) / r_aB_norm; - - // # 2 MULTs - // - // $-\vec{F}_{\alpha B}(\vec{r}_{\alpha B}) = \frac{-U^0_{\alpha B}}{R} e^{- \Arrowvert \vec{r}_{\alpha B} \Arrowvert / R} \frac{\vec{r}_{\alpha B}}{\Arrowvert \vec{r}_{\alpha B} \Arrowvert}$ - // - Vector2d f_alpha_B_neg = r_aB * scalar_mult; - - // # 2 ADDs, 7 MULTs, 1 SQRT - // - // $\vec{F}_{\alpha B}(\vec{e}_{\alpha}, \vec{r}_{\alpha B}).dt = w(\vec{e}_{\alpha}, -\vec{F}_{\alpha B}(\vec{r}_{\alpha B})).\vec{F}_{\alpha B}(\vec{r}_{\alpha B}).dt$ - // - Vector2d f_alpha_B_dt = f_alpha_B_neg * w(alpha.e, f_alpha_B_neg); - - return f_alpha_B_dt; -} - -// social_force_baseline.cpp - -Pedestrian *init_pedestrians(int n_p) { -#if RANDOM_SEED - random_device rd; // Platform-provided random seed source. - mt19937 gen(rd()); // Non-reproducible initialization. -#else - mt19937 gen(SEED); // Reproducible initialization. -#endif - - normal_distribution velocity_gen(v0_mean, v0_std_dev); - uniform_real_distribution y_gen(0.3, BOARD_WIDTH - 0.3); - uniform_real_distribution x_gen_left(2.0, BOARD_LENGTH / 2.0); - uniform_real_distribution x_gen_right(BOARD_LENGTH / 2.0, BOARD_LENGTH - 2.0); - - Pedestrian *P = new Pedestrian[n_p]; - - int n_p_half = n_p / 2; - - // Group of pedestrians walking from left to right. - for (int i = 0; i < n_p_half; i++) { - double x = x_gen_left(gen); - double y = y_gen(gen); - - Vector2d start_pos = Vector2d(x, y); - Vector2d destination = Vector2d(BOARD_LENGTH + 30.0, y); - - Vector2d init_e = destination - start_pos; - double init_e_norm = init_e.norm(); - Vector2d init_e_unit = init_e / init_e_norm; - - // Reject near-zero desired speeds to avoid pedestrians that barely move, - // and reject negative speeds because they would reverse the intended - // walking direction. - double desired_v0; - do { - desired_v0 = velocity_gen(gen); - } while (desired_v0 <= 0.1); - - double v_max = 1.3 * desired_v0; - - P[i] = Pedestrian(WHITE, Vector2d(), start_pos, init_e_unit, v_max, desired_v0, destination); - } - - // Group of pedestrians walking from right to left. - for (int i = n_p_half; i < n_p; i++) { - double x = x_gen_right(gen); - double y = y_gen(gen); - - Vector2d start_pos = Vector2d(x, y); - Vector2d destination = Vector2d(-30.0, y); - - Vector2d init_e = destination - start_pos; - double init_e_norm = init_e.norm(); - Vector2d init_e_unit = init_e / init_e_norm; - - // Reject near-zero desired speeds to avoid pedestrians that barely move, - // and reject negative speeds because they would reverse the intended - // walking direction. - double desired_v0; - do { - desired_v0 = velocity_gen(gen); - } while (desired_v0 <= 0.1); - - double v_max = 1.3 * desired_v0; - - P[i] = Pedestrian(BLACK, Vector2d(), start_pos, init_e_unit, v_max, desired_v0, destination); - } - - return P; -} - -Board init_board_without_obstacles() { return Board(BOARD_LENGTH, BOARD_WIDTH, 0, nullptr); } - -int run_simulation(Pedestrian *pedestrians, Board &board, int n_p, int n_iter, const char *dump_path) { - -#if BENCHMARK - // Avoid compiler unused parameter warning - (void)dump_path; -#endif - -#if !BENCHMARK - const int dump_interval = 1; - - // Each sample stores: time step, pedestrian id, x, y, e.x, e.y, color. - vector> samples; - - if (dump_path) { - samples.reserve(static_cast(n_iter / dump_interval + 1) * n_p); - - // Store the initial state before the first simulation step. - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - samples.emplace_back(0, i, p.curr_pos.x, p.curr_pos.y, p.e.x, p.e.y, p.color); - } - } -#endif - - // FLOPCOUNT (everything inside the t-loop). EXP = one fast_exp() call (LUT + cubic Hermite), - // NOT a real libm exp. AoS baseline, no distance precompute, r_ab recomputed inside the j-loop. - // section costs: overhead 4 ADD 4 MULT (accel 2 ADD 4 MULT + p.w += 2 ADD) | - // ped-ped j 14 ADD 23 MULT 1 DIV 4 SQRT 1 EXP (12/23/1/4/1 + f_alpha += 2 ADD) | - // obstacle 12 ADD 18 MULT 1 DIV 2 SQRT 1 EXP (10/18/1/2/1 + f_alpha += 2 ADD) | - // update 7 ADD 16 MULT 2 DIV 3 SQRT - - // # ADDs: n_iter * ( - // # n_p * 4 + - // # n_p * (n_p - 1) * 14 + - // # n_p * board.n_obstacles * 12 + - // # n_p * 7 - // # ) - - // # MULTs: n_iter * ( - // # n_p * 4 + - // # n_p * (n_p - 1) * 23 + - // # n_p * board.n_obstacles * 18 + - // # n_p * 16 - // # ) - - // # DIVs: n_iter * ( - // # n_p * (n_p - 1) + - // # n_p * board.n_obstacles + - // # n_p * 2 - // # ) - - // # SQRTs: n_iter * ( - // # n_p * (n_p - 1) * 4 + - // # n_p * board.n_obstacles * 2 + - // # n_p * 3 - // # ) - - // # EXPs (fast_exp, LUT): n_iter * ( - // # n_p * (n_p - 1) + - // # n_p * board.n_obstacles - // # ) - - for (int t = 0; t < n_iter; t++) { - // Pass 1: Compute all forces from the current state. - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - - // # 2 ADDs, 4 MULTs - // - // $\vec{F}_\alpha(\vec{v}_\alpha, v^0_\alpha \vec{e}_\alpha) = \frac{1}{\tau_\alpha}(v^0_\alpha \vec{e}_\alpha - \vec{v}_\alpha)$ - // - Vector2d f_alpha_dt = acceleration_term_dt(p); - - // # (N-1) * (12 ADDs, 23 MULTs, 1 DIV, 4 SQRTs, 1 EXP) - // + (N-1) * 2 ADDs - // - // $\sum_{\beta} \vec{F}_{\alpha\beta}(\vec{e}_{\alpha},\vec{r}_{\alpha} - \vec{r}_{\beta})$ - // - for (int j = 0; j < n_p; j++) { - if (i == j) - continue; - - f_alpha_dt += pedestrian_repulsion_dt(p, pedestrians[j]); - } - - // # board.n_obstacles * (10 ADDs, 18 MULTs, 1 DIV, 2 SQRTs, 1 EXP) - // + board.n_obstacles * 2 ADDs - // - // $\sum_{B} \vec{F}_{\alpha B}(\vec{e}_{\alpha}, \vec{r}_{\alpha} - \vec{r}_{B})$ - // - for (int k = 0; k < board.n_obstacles; k++) { - f_alpha_dt += obstacle_repulsion_dt(p, board.obstacles[k]); - } - - // # 2 ADDs - // - // - // $\frac{d\vec{w}_\alpha}{dt} = \vec{F}_{\alpha}(t)$ - // - p.w += f_alpha_dt; - } - - // Pass 2: Update pedestrian states after all forces have been computed. - // # (7 ADDs, 16 MULTs, 2 DIVs, 3 SQRTs) * n_p - for (int i = 0; i < n_p; i++) { - Pedestrian &p = pedestrians[i]; - - // # 1 ADD, 2 MULTs, 1 SQRT - double w_norm = p.w.norm(); - - double w_norm2 = w_norm > EPS ? w_norm : EPS; // Avoid division by zero. - - // # 1 DIV - double correction_factor = std::min(1.0, p.v_max / w_norm2); - - // # 2 MULTs - p.curr_vel = p.w * correction_factor; - - // # 2 ADDs, 2 MULTs - // - // $\vec{r}_i^{t+1} = \vec{r}_i^t + \vec{v}_i^t dt$ - // - p.curr_pos = p.curr_pos + p.curr_vel * dt; - - // When a pedestrian reaches the end of the corridor, teleport them back - // to the opposite entrance while keeping the same y-coordinate. This - // maintains a constant pedestrian flow and makes lane formation easier to - // observe. - if (p.color == WHITE && p.curr_pos.x > (BOARD_LENGTH - 1.5)) { - p.curr_pos.x = 1.0; - p.destination.y = p.curr_pos.y; - p.w = Vector2d(p.desired_v0, 0.0); - p.curr_vel = p.w; - } - if (p.color == BLACK && p.curr_pos.x < 1.5) { - p.curr_pos.x = BOARD_LENGTH - 1.0; - p.destination.y = p.curr_pos.y; - p.w = Vector2d(-p.desired_v0, 0.0); - p.curr_vel = p.w; - } - - // Keep pedestrians inside the board boundaries. - p.curr_pos.y = clamp(p.curr_pos.y, WALL_EPS, BOARD_WIDTH_MINUS_WALL_EPS); - - // # 2 ADDs - Vector2d e = p.destination - p.curr_pos; - - // # 1 ADD, 2 MULTs, 1 DIV, 1 SQRT - double e_norm = e.norm(); - double e_norm2 = e_norm > EPS ? e_norm : EPS; // Avoid division by zero. - double e_norm_inv = 1.0 / e_norm2; - - // # 2 MULTs - p.e = e * e_norm_inv; - - // # 1 ADD, 2 MULTs - double velocity_norm_sq = p.curr_vel.dot(p.curr_vel); - - // # 1 SQRT - double velocity_norm = std::sqrt(velocity_norm_sq); - - // # 1 MULT - p.s_b_sq = velocity_norm_sq * delta_t_sq; - - // # 3 MULTs - p.s_b_e = p.e * (velocity_norm * delta_t); - -#if !BENCHMARK - // Store the current pedestrian state for visualization. - if (dump_path && (t % dump_interval == 0)) { - samples.emplace_back(t + 1, i, p.curr_pos.x, p.curr_pos.y, p.e.x, p.e.y, p.color); - } -#endif - } - } - -#if !BENCHMARK - // Export recorded simulation states to CSV. - if (dump_path) { - ofstream out(dump_path); - out << "time,id,x,y,p.e.x,p.e.y,color\n"; - - for (auto &[t, id, x, y, e_x, e_y, c] : samples) { - out << t << ',' << id << ',' << x << ',' << y << ',' << e_x << ',' << e_y << ',' << c << '\n'; - } - } -#endif - - return 0; -} \ No newline at end of file