Skip to content

Commit 0aa11d6

Browse files
committed
Merge branch 'feature/spainhour/threaded_gwn' of https://github.com/LLNL/axom into feature/spainhour/threaded_gwn
2 parents ebd7cb6 + 6437782 commit 0aa11d6

102 files changed

Lines changed: 3986 additions & 2162 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci-tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ jobs:
4343
- job_name: gcc@13.3.1, shared, 32bit
4444
host_config: gcc@13.3.1.cmake
4545
compiler_image: ${{ needs.set_image_vars.outputs.gcc_docker_image }}
46-
cmake_opts: '-DBUILD_SHARED_LIBS=ON -DAXOM_USE_64BIT_INDEXTYPE:BOOL=OFF'
46+
cmake_opts: '-DBUILD_SHARED_LIBS=ON -DAXOM_USE_64BIT_INDEXTYPE:BOOL=OFF -DAXOM_NO_INT64_T=1'
4747
do_build: 'yes'
4848
do_benchmarks: 'no'
4949
- job_name: llvm@19.0.0, shared, benchmarks, quest regression

RELEASE-NOTES.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,19 @@ The Axom project release numbers follow [Semantic Versioning](http://semver.org/
2626

2727
### Changed
2828
- Primal: Axom's polygon clipping was modified to handle some corner cases.
29+
- Bump: Several Bump algorithms were improved so they perform better with OpenMP.
30+
- Mir: The `EquiZAlgorithm was improved so it performs better with OpenMP.
31+
- Many algorithms in Bump and Mir have been enhanced with `setAllocatorID()` methods to permit use of custom allocators.
2932
- Uberenv's spack updated to v1.1.1
3033
- `radiuss-spack-configs` submodule removed.
3134

3235
### Fixed
3336
- Primal: Fixed `NURBSPatch::evaluateDerivatives` returning a matrix with empty values. The old behavior
3437
can be recovered with an optional flag, which is more efficient if the previously missing values are unneeded
38+
- Core: the `ArrayView` class was modified so it defers initializing an internal
39+
allocator id via Umpire, if present. This prevents excessive calls to Umpire,
40+
which are not needed in all use cases.
41+
- Quest: A compilation problem with `-DAXOM_NO_INT64_T=1` was fixed.
3542

3643
### Removed
3744

scripts/benchmarks/mir_concentric_circles.py

Lines changed: 209 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,23 @@ def lrun(np):
1313

1414
# Parallel options use 4 ranks per node since that is how many GPUs there are.
1515
runs = {
16-
"build-rzansel-blueos_3_ppc64le_ib_p9-clang@10.0.1.2_cuda-release" : {"policies":["seq", "omp", "cuda"], "launch":lrun},
17-
"build-rzwhippet-toss_4_x86_64_ib-clang@14.0.6-release" : {"policies":["seq", "omp"], "launch":srun},
18-
"build-rzwhippet-toss_4_x86_64_ib-gcc@10.3.1-release" : {"policies":["seq", "omp"], "launch":srun},
19-
"build-rzwhippet-toss_4_x86_64_ib-intel@2022.1.0-release" : {"policies":["seq", "omp"], "launch":srun},
20-
"build-rzvernal-toss_4_x86_64_ib_cray-rocmcc@6.2.1_hip-release" : {"policies":["seq", "hip"], "launch":srun},
21-
"build-rzvernal-toss_4_x86_64_ib_cray-clang@17.0.0_hip-release" : {"policies":["seq", "hip"], "launch":srun},
22-
"build-rzadams-toss_4_x86_64_ib_cray-cce@18.0.0_hip-release" :{"policies":["seq", "hip"], "launch":flux_run},
23-
"build-rzadams-toss_4_x86_64_ib_cray-rocmcc@6.2.1_hip-release" :{"policies":["seq", "hip"], "launch":flux_run}
16+
"build-dane-toss_4_x86_64_ib-gcc@13.3.1-release" : {"policies":["seq", "omp"], "launch":srun},
17+
"build-dane-toss_4_x86_64_ib-intel-oneapi-compilers@2025.2.0-release" : {"policies":["seq", "omp"], "launch":srun},
18+
"build-dane-toss_4_x86_64_ib-llvm@19.1.3-release" : {"policies":["seq", "omp"], "launch":srun},
19+
"build-matrix-toss_4_x86_64_ib-gcc@13.3.1_cuda-release" : {"policies":["seq", "omp", "cuda"], "launch":srun},
20+
"build-matrix-toss_4_x86_64_ib-llvm@19.1.3_cuda-release" : {"policies":["seq", "omp", "cuda"], "launch":srun},
21+
"build-rzwhippet-toss_4_x86_64_ib-llvm@19.1.3-release" : {"policies":["seq", "omp"], "launch":srun},
22+
"build-rzwhippet-toss_4_x86_64_ib-gcc@13.3.1-release" : {"policies":["seq", "omp"], "launch":srun},
23+
"build-rzwhippet-toss_4_x86_64_ib-intel-oneapi-compilers@2025.2.0-release" : {"policies":["seq", "omp"], "launch":srun},
24+
"build-rzvernal-toss_4_x86_64_ib_cray-cce@20.0.0_hip-release" : {"policies":["seq", "hip"], "launch":srun},
25+
"build-rzvernal-toss_4_x86_64_ib_cray-llvm-amdgpu@6.3.1_hip-release" : {"policies":["seq", "hip"], "launch":srun},
26+
"build-rzvernal-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.2_hip-release" : {"policies":["seq", "hip"], "launch":srun},
27+
"build-rzadams-toss_4_x86_64_ib_cray-cce@20.0.0_hip-release" :{"policies":["seq", "hip"], "launch":flux_run},
28+
"build-rzadams-toss_4_x86_64_ib_cray-llvm-amdgpu@6.3.1_hip-release" :{"policies":["seq", "hip"], "launch":flux_run},
29+
"build-rzadams-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.2_hip-release" :{"policies":["seq", "hip"], "launch":flux_run},
30+
"build-tioga-toss_4_x86_64_ib_cray-cce@20.0.0_hip-release" :{"policies":["seq", "hip"], "launch":flux_run},
31+
"build-tioga-toss_4_x86_64_ib_cray-llvm-amdgpu@6.3.1_hip-release" :{"policies":["seq", "hip"], "launch":flux_run},
32+
"build-tioga-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.2_hip-release" :{"policies":["seq", "hip"], "launch":flux_run}
2433
}
2534

2635
def generate(params):
@@ -40,6 +49,10 @@ def generate(params):
4049
f.write("CONCENTRIC_CIRCLES=./examples/mir_concentric_circles\n")
4150
f.write("CONCENTRIC_CIRCLES_MPI=./examples/mir_concentric_circles_mpi\n\n")
4251

52+
f.write("export OMP_PLACES=cores\n")
53+
f.write("export OMP_PROC_BIND=spread\n")
54+
f.write("export OMP_DYNAMIC=FALSE\n")
55+
4356
dimension = params["dimension"]
4457
trials = params["trials"]
4558
for s in params["sizes"]:
@@ -68,7 +81,10 @@ def read_timings(filename, searchKey):
6881
retval = "" # no data
6982
try:
7083
lines = open(filename, "rt").readlines()
71-
print(f"Reading {filename}")
84+
msg = ""
85+
if searchKey.find("Algorithm") == -1:
86+
msg = f" Getting '{searchKey}' value."
87+
print(f"Reading {filename}.{msg}")
7288
for line in lines:
7389
pos = line.find(searchKey)
7490
if pos != -1:
@@ -113,10 +129,7 @@ def average(value, trials):
113129
avg = value
114130
return avg
115131

116-
# Measure just the MIR algorithm
117-
searchKey = "EquizAlgorithm"
118-
if params["method"] == "elvira":
119-
searchKey = "ElviraAlgorithm"
132+
searchKey = params["searchKey"]
120133

121134
columns = []
122135
# Add NumZones column (either square or cube of s, depending on dimension)
@@ -184,9 +197,17 @@ def make_csv(params, outputfile):
184197
f.write(f"{line}\n")
185198
f.close()
186199

187-
def seriesName(name):
200+
def seriesName(name, includeCompiler = False):
188201
policies = {"SEQ" : "Serial", "OMP": "OpenMP", "CUDA" : "CUDA", "HIP" : "HIP"}
189-
newName = name[:name.find("-")]
202+
if includeCompiler:
203+
d0 = name.find("-")
204+
d1 = name.rfind("-")
205+
s0 = name.rfind(" ")
206+
hostName = name[:d0]
207+
compName = name[d1 + 1:s0]
208+
newName = f"{hostName} {compName}"
209+
else:
210+
newName = name[:name.find("-")]
190211
for p in policies.keys():
191212
if name[-len(p) - 1:] == " " + p:
192213
newName = newName + " " + policies[p]
@@ -197,8 +218,15 @@ def lineProps(name):
197218
"""
198219
Make line properties when given a series name.
199220
"""
200-
hostColor = {"rzansel" : "g", "rzwhippet" : "r", "rzvernal" : "o", "rzadams" : "b"}
201-
policyStyle = {"seq" : "--", "omp": ":", "cuda" : "-", "hip" : "-"}
221+
red = "#ff0000"
222+
green = "#00aa00"
223+
blue = "#0000ff"
224+
orange = "#ff6622"
225+
#magenta = "#ff00ff"
226+
#purple = "#8811aa"
227+
hostColor = {"rzwhippet" : red, "rzvernal" : green, "rzadams" : blue,
228+
"dane" : red, "matrix" : green, "tioga": orange, "tuolumne" : blue}
229+
policyStyle = {"seq" : "-", "omp": ":", "cuda" : "--", "hip" : "--"}
202230
policyMark = {"seq" : "o", "omp": "s", "cuda" : "^", "hip" : "^"}
203231
color = "b"
204232
style = "-"
@@ -214,6 +242,25 @@ def lineProps(name):
214242
break
215243
return color, style, mark
216244

245+
def hex_to_rgb(hex_color: str):
246+
"""
247+
Convert a color in "#rrggbb" (or "rrggbb") format to an (r, g, b) tuple.
248+
"""
249+
s = hex_color.strip()
250+
if s.startswith("#"):
251+
s = s[1:]
252+
if len(s) != 6:
253+
raise ValueError(f"Expected 6 hex digits, got {len(s)}: {hex_color!r}")
254+
255+
try:
256+
r = int(s[0:2], 16)
257+
g = int(s[2:4], 16)
258+
b = int(s[4:6], 16)
259+
except ValueError as e:
260+
raise ValueError(f"Invalid hex color: {hex_color!r}") from e
261+
262+
return (r, g, b)
263+
217264
def plot(params):
218265
"""
219266
Read the available timing files and plot them.
@@ -233,22 +280,78 @@ def make_series(col1, col2):
233280
break
234281
return x,y
235282

283+
def rgbToColor(r,g,b):
284+
return "#%02x%02x%02x" % (r,g,b)
285+
286+
def lightenColor(r,g,b):
287+
def clamp255(value):
288+
if value > 255:
289+
return 255
290+
return int(value)
291+
scale = 1.3
292+
return rgbToColor(clamp255(r * scale), clamp255(g * scale), clamp255(b * scale))
293+
294+
def darkenColor(r,g,b):
295+
scale = 0.7
296+
return rgbToColor(int(r * scale), int(g * scale), int(b * scale))
297+
298+
def modifyColor(color, index):
299+
if index == 0:
300+
return color
301+
r,g,b = hex_to_rgb(color)
302+
if index == 1:
303+
return darkenColor(r,g,b)
304+
return lightenColor(r,g,b)
305+
306+
def valid_column(column):
307+
valid = False
308+
for i in range(1, len(column)):
309+
if column[i] != "":
310+
valid = True
311+
return valid
312+
313+
# Make columns from the data
236314
columns = make_columns(params)
237315

316+
# Count how many plots would use the normal legend name
317+
counts = {}
318+
for c in range(1, len(columns)):
319+
if not valid_column(columns[c]):
320+
continue
321+
sn = seriesName(columns[c][0])
322+
if sn in counts:
323+
count, _ = counts[sn]
324+
counts[sn] = (count + 1, 0)
325+
else:
326+
counts[sn] = (1, 0)
327+
238328
import matplotlib.pyplot as plt
329+
seriesLegendNames = {}
239330
for c in range(1, len(columns)):
240331
x, y = make_series(columns[0][1:], columns[c][1:])
241332
if len(x) > 0:
242333
color, style, mark = lineProps(columns[c][0])
243-
plt.plot(x, y, marker=mark, linestyle=style, color=color, linewidth=2., label=seriesName(columns[c][0]))
334+
sn = seriesName(columns[c][0])
335+
if counts[sn][0] > 1:
336+
oldsn = sn
337+
sn = seriesName(columns[c][0], True)
338+
color = modifyColor(color, counts[oldsn][1])
339+
counts[oldsn] = (counts[oldsn][0], counts[oldsn][1] + 1)
340+
seriesLegendNames[c] = sn
341+
plt.plot(x, y, marker=mark, linestyle=style, color=color, linewidth=2., label=sn)
244342

245343
dimension = params["dimension"]
246344
method = params["method"]
345+
searchKey = params["searchKey"]
346+
if searchKey.find("Algorithm") != -1:
347+
# more concise
348+
searchKey = method
349+
doLabels = params["labels"]
247350

248351
# Add labels and title
249352
plt.xlabel('Number of Zones', fontsize=24)
250353
plt.ylabel('Time (s)', fontsize=24)
251-
plt.title(f'{dimension}D MIR Timings ({method})', fontsize=28)
354+
plt.title(f'{dimension}D MIR Timings ({searchKey})', fontsize=28)
252355
xlabels = make_series(columns[0][1:], columns[0][1:])[0]
253356
plt.xticks(ticks=xlabels, labels=xlabels, fontsize=18)
254357
plt.yticks(fontsize=18)
@@ -268,6 +371,65 @@ def make_series(col1, col2):
268371
print(f"There was an error, probably because the benchmark is still running. {columns}")
269372
raise
270373

374+
# Add labels
375+
if doLabels and len(columns) >= 2:
376+
def findIndex(seq, value):
377+
eps = 1.e-8
378+
for i in range(len(seq)):
379+
if math.fabs(value - seq[i]) < eps:
380+
return i
381+
return -1
382+
383+
# Group the related series.
384+
seriesGroups = {}
385+
seriesSer = {}
386+
for c in seriesLegendNames.keys():
387+
sn = seriesLegendNames[c]
388+
host = sn[:sn.rfind(" ")]
389+
if host in seriesGroups:
390+
seriesGroups[host].append(c)
391+
else:
392+
seriesGroups[host] = [c]
393+
if sn.find("Serial") != -1:
394+
seriesSer[host] = c
395+
396+
# Go through groups
397+
for host in seriesGroups:
398+
if not host in seriesSer:
399+
continue
400+
401+
# The serial column
402+
cser = seriesSer[host]
403+
404+
# Compare other columns against the serial column
405+
for c in seriesGroups[host]:
406+
if cser == c:
407+
continue
408+
409+
x1, y1 = make_series(columns[0][1:], columns[cser][1:])
410+
x2, y2 = make_series(columns[0][1:], columns[c][1:])
411+
xa = []
412+
ya = []
413+
labels = []
414+
idx = 0
415+
for i in range(len(x1)):
416+
# Where series 1 (SEQ) > series 2 (OMP)
417+
j = findIndex(x2, x1[i])
418+
if j != -1 and y1[i] > y2[j]:
419+
xa.append(x2[j])
420+
ya.append(y2[j])
421+
labels.append(f"{math.trunc(100. * y1[i] / y2[i]) / 100.:.2f}x")
422+
plt.annotate(
423+
labels[idx],
424+
(xa[idx], ya[idx]),
425+
xytext=(6, -6), textcoords="offset points", # pixel offset
426+
ha="left", va="bottom",
427+
fontsize=10,
428+
bbox=dict(boxstyle="round,pad=0.2", fc="white", ec="none", alpha=0.8),
429+
arrowprops=dict(arrowstyle="-", color="0.3", lw=0.8)
430+
)
431+
idx = idx + 1
432+
271433
# Show the plot
272434
plt.grid(True)
273435
plt.show()
@@ -319,13 +481,27 @@ def get_params():
319481
required=False
320482
)
321483

484+
parser.add_argument(
485+
"--key",
486+
type=str,
487+
help="Name of the caliper timings to extract from the logs",
488+
required=False
489+
)
490+
322491
parser.add_argument(
323492
"--trials",
324493
type=int,
325494
help="Number of times to run MIR",
326495
required=False
327496
)
328497

498+
parser.add_argument(
499+
"--labels",
500+
action="store_true",
501+
help="Boolean flag to indicate whether to draw speedup labels",
502+
required=False
503+
)
504+
329505
args = parser.parse_args()
330506

331507
# Convert the comma-separated string into a tuple of integers
@@ -369,6 +545,20 @@ def get_params():
369545
else:
370546
params["trials"] = 1
371547

548+
if args.labels is not None:
549+
params["labels"] = args.labels
550+
else:
551+
params["labels"] = False
552+
553+
if args.key is not None:
554+
params["searchKey"] = args.key
555+
else:
556+
# Default to MIR algorithm timings
557+
if params["method"] == "elvira":
558+
params["searchKey"] = "ElviraAlgorithm"
559+
else:
560+
params["searchKey"] = "EquizAlgorithm"
561+
372562
# Generate some sizes.
373563
sides = (50, 100, 200, 500, 1000, 1500, 2000, 4000, 8000)
374564
if params["dimension"] == 3:

0 commit comments

Comments
 (0)