Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Weak Scale Test #163

Open
wants to merge 6 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions examples/mapping_tester/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ MAPPING_TESTER="${TEST_LOCATION}"/../../tools/mapping-tester/
TEST_CASE_LOCATION="${TEST_LOCATION}"/case

# Generate the run scripts
python3 "${MAPPING_TESTER}"/generate.py --setup "${TEST_LOCATION}"/setup-test.json --outdir "${TEST_CASE_LOCATION}" --template "${MAPPING_TESTER}"/config-template.xml
python3 "${MAPPING_TESTER}"/generate_mapping_test.py --setup "${TEST_LOCATION}"/setup-test.json --outdir "${TEST_CASE_LOCATION}" --template "${MAPPING_TESTER}"/config-template.xml

# Prepare the meshes
python3 "${MAPPING_TESTER}"/preparemeshes.py --setup "${TEST_LOCATION}"/setup-test.json --outdir "${TEST_CASE_LOCATION}" --force
python3 "${MAPPING_TESTER}"/prepare_mapping_teest_meshes.py --setup "${TEST_LOCATION}"/setup-test.json --outdir "${TEST_CASE_LOCATION}" --force

export ASTE_A_MPIARGS=""
export ASTE_B_MPIARGS=""
Expand All @@ -29,4 +29,4 @@ bash ./postprocessall.sh
cd "${TEST_LOCATION}"

# Gather the generated statistics
python3 "${MAPPING_TESTER}"/gatherstats.py --outdir "${TEST_CASE_LOCATION}" --file test-statistics.csv
python3 "${MAPPING_TESTER}"/gather_stats.py --outdir "${TEST_CASE_LOCATION}" --file test-statistics.csv
4 changes: 4 additions & 0 deletions examples/weak_scaling_tester/clean.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/usr/bin/env bash

rm -f test-statistics.csv
rm -fr ./case/
36 changes: 36 additions & 0 deletions examples/weak_scaling_tester/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env bash
set -e -x

# Get the test location
TEST_LOCATION="$(pwd)"
export TEST_LOCATION

# The mapping-tester location
WEAK_SCALING_TESTER="${TEST_LOCATION}"/../../tools/mapping-scaling-tester/

GENERATOR="${TEST_LOCATION}"/../../tools/mesh-generators/generate_halton_mesh.py
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it just using default arguments here? Can you pass the arguments here explicitly?


# The case directory
TEST_CASE_LOCATION="${TEST_LOCATION}"/case

# Generate the run scripts
python3 "${WEAK_SCALING_TESTER}"/generate_scale_test.py --setup "${TEST_LOCATION}"/setup-test.json --outdir "${TEST_CASE_LOCATION}" --template "${WEAK_SCALING_TESTER}"/config-template.xml

# Prepare the meshes
python3 "${WEAK_SCALING_TESTER}"/prepare_scale_meshes.py --setup "${TEST_LOCATION}"/setup-test.json --outdir "${TEST_CASE_LOCATION}" --force -g "${GENERATOR}"
export ASTE_A_MPIARGS=""
export ASTE_B_MPIARGS=""

# Run the actual cases
cd "${TEST_CASE_LOCATION}" && bash ./runall.sh

# Postprocess the test cases
bash ./postprocessall.sh

cd "${TEST_LOCATION}"

# Gather the generated statistics
python3 "${WEAK_SCALING_TESTER}"/gather_stats.py --outdir "${TEST_CASE_LOCATION}" --file test-statistics.csv

# Plot the results
python3 "${WEAK_SCALING_TESTER}"/prepare_plots.py --file test-statistics.csv --mode weak_scale
35 changes: 35 additions & 0 deletions examples/weak_scaling_tester/setup-test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"general": {
"testlocation": "${TEST_LOCATION}",
"function": "x+y^2+z^3",
"ranks": {
"A": [
1,2,3,4
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
1,2,3,4
1,2,4

],
"B": [
1,2,3,4
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
1,2,3,4
1,2,4

]
},
"network": "lo0",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"network": "lo0",

This will only work on some systems. I would recommend to not specify any network here. preCICE has a few decent defaults which should be sufficient here.

"syncmode": false,
"numberofpointsperrank": {
"A": 1000,
"B": 1200
}
},
"groups": [
{
"mapping": {
"constraints": [
"consistent"
],
"cases": {
"tps": {
"kind": "rbf-thin-plate-splines",
"options": "use-qr-decomposition=\"1\""
Comment on lines +27 to +29
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is by far the most expensive variant. Which might take too much time.

Suggested change
"tps": {
"kind": "rbf-thin-plate-splines",
"options": "use-qr-decomposition=\"1\""
"Wendland-C6": {
"kind": "rbf-compact-polynomial-c6",
"options": "use-qr-decomposition=\"true\" support-radius=\"1\""

}
}
}
}
]
}
145 changes: 22 additions & 123 deletions tools/mapping-tester/generate.py → tools/mapping-scaling-tester/common.py
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
#! /usr/bin/env python3
#!/usr/bin/env python3

import argparse
import json
import os

from jinja2 import Template


def generateConfig(template, setup):
def generate_config(template, setup):
template = Template(template)
return template.render(setup)

Expand All @@ -20,55 +18,7 @@ def as_iter(something):
return [something]


def generateCases(setup):
meshes = setup["general"]["meshes"]
network = setup["general"].get("network", "lo")
syncmode = setup["general"].get("syncmode", "false")

cases = []
for group in setup["groups"]:
for name, mapping in group["mapping"]["cases"].items():
for constraint in group["mapping"]["constraints"]:
for inname in group["meshes"]["A"]:
infile = meshes["A"][inname]
for outname in group["meshes"]["B"]:
outfile = meshes["B"][outname]
for ranksA, ranksB in zip(
as_iter(setup["general"]["ranks"].get("A", 1)),
as_iter(setup["general"]["ranks"].get("B", 1)),
):
cases.append(
{
"function": setup["general"]["function"],
"mapping": {
"name": name,
"kind": mapping["kind"],
"constraint": constraint,
"options": mapping.get("options", ""),
},
"A": {
"ranks": ranksA,
"mesh": {
"name": inname,
"file": infile,
},
},
"B": {
"ranks": ranksB,
"mesh": {
"name": outname,
"file": outfile,
},
},
"network": network,
"syncmode": syncmode,
}
)

return cases


def getCaseFolders(case):
def get_case_folder(case):
return [
case["mapping"]["name"],
case["mapping"]["constraint"],
Expand All @@ -77,21 +27,21 @@ def getCaseFolders(case):
]


def caseToSortable(case):
def case_to_sortable(case):
parts = case.split(os.path.sep)
kind = parts[0]
mesha, meshb = map(float, parts[-2].split("-"))

kindCost = 0
kind_cost = 0
if kind.startswith("gaussian"):
kindCost = 1
kind_cost = 1
elif kind.startswith("tps"):
kindCost = 2
kind_cost = 2

return (kindCost, -mesha, -meshb)
return (kind_cost, -mesha, -meshb)


def createMasterRunScripts(casemap, dir):
def create_master_run_scripts(casemap, dir):
common = [
"#!/bin/bash",
"",
Expand Down Expand Up @@ -136,28 +86,28 @@ def createMasterRunScripts(casemap, dir):
)


def createRunScript(outdir, path, case):
def create_run_script(outdir, path, case):
amesh = case["A"]["mesh"]["name"]
aranks = case["A"]["ranks"]
ameshLocation = os.path.relpath(
amesh_location = os.path.relpath(
os.path.join(outdir, "meshes", amesh, str(aranks), amesh), path
)

# Generate runner script
acmd = '/usr/bin/time -f %M -a -o memory-A.log precice-aste-run -v -a -p A --data "{}" --mesh {} || kill 0 &'.format(
case["function"], ameshLocation
case["function"], amesh_location
)
if aranks > 1:
acmd = "mpirun -n {} $ASTE_A_MPIARGS {}".format(aranks, acmd)

bmesh = case["B"]["mesh"]["name"]
branks = case["B"]["ranks"]
bmeshLocation = os.path.relpath(
bmesh_location = os.path.relpath(
os.path.join(outdir, "meshes", bmesh, str(branks), bmesh), path
)
mapped_data_name = case["function"] + "(mapped)"
bcmd = '/usr/bin/time -f %M -a -o memory-B.log precice-aste-run -v -a -p B --data "{}" --mesh {} --output mapped || kill 0 &'.format(
mapped_data_name, bmeshLocation
mapped_data_name, bmesh_location
)
if branks > 1:
bcmd = "mpirun -n {} $ASTE_B_MPIARGS {}".format(branks, bcmd)
Expand Down Expand Up @@ -218,12 +168,10 @@ def createRunScript(outdir, path, case):
)
post_content += [joincmd, diffcmd]
else:
[recoveryFileLocation, tmpPrefix] = os.path.split(
os.path.normpath(bmeshLocation)
)
tmprecoveryFile = recoveryFileLocation + "/{}_recovery.json".format(bmesh)
[recovery_file_location, _] = os.path.split(os.path.normpath(bmesh_location))
tmp_recovery_file = recovery_file_location + "/{}_recovery.json".format(bmesh)
joincmd = "precice-aste-join --mesh mapped -r {} -o result.vtk".format(
tmprecoveryFile
tmp_recovery_file
)
diffcmd = 'precice-aste-evaluate --data error --diffdata "{1}" --diff --stats --mesh result.vtk --function "{0}" | tee diff.log'.format(
case["function"], mapped_data_name
Expand All @@ -234,10 +182,10 @@ def createRunScript(outdir, path, case):
)


def setupCases(outdir, template, cases):
def setup_cases(outdir, template, cases):
casemap = {}
for case in cases:
folders = getCaseFolders(case)
folders = get_case_folder(case)
casemap.setdefault(folders[0], []).append(folders[1:])
name = [outdir] + folders
path = os.path.join(*name)
Expand All @@ -246,58 +194,9 @@ def setupCases(outdir, template, cases):
print(f"Generating {path}")
os.makedirs(path, exist_ok=True)
with open(config, "w") as config:
config.write(generateConfig(template, case))
createRunScript(outdir, path, case)
config.write(generate_config(template, case))
create_run_script(outdir, path, case)
print(f"Generated {len(cases)} cases")

print(f"Generating master scripts")
createMasterRunScripts(casemap, outdir)


def parseArguments(args):
parser = argparse.ArgumentParser(description="Generator for a mapping test suite")
parser.add_argument(
"-o",
"--outdir",
default="cases",
help="Directory to generate the test suite in.",
)
parser.add_argument(
"-s",
"--setup",
type=argparse.FileType("r"),
default="setup.json",
help="The test setup file to use.",
)
parser.add_argument(
"-t",
"--template",
type=argparse.FileType("r"),
default="config-template.xml",
help="The precice config template to use.",
)
return parser.parse_args(args)


def main(argv):
# Parse the input arguments
args = parseArguments(argv[1:])
# Parse the json file using the json module
setup = json.load(args.setup)
# Read the xml-template file
template = args.template.read()
# Generate the actual cases
cases = generateCases(setup)
outdir = os.path.normpath(args.outdir)
if os.path.isdir(outdir):
print('Warning: outdir "{}" already exisits.'.format(outdir))

setupCases(outdir, template, cases)

return 0


if __name__ == "__main__":
import sys

sys.exit(main(sys.argv))
create_master_run_scripts(casemap, outdir)
Loading