You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

252 lines
10 KiB

2 years ago
import sys
import os
import json
import pathlib
import argparse
import subprocess
import platform
import re
import numpy
import pandas
from combine_profiles import combine_profiles
def get_machine_info():
if platform.system() == "Windows":
return "Windows machine info not implemented"
if platform.system() == "Darwin":
core_count = int(subprocess.run(
["sysctl", "-n", "machdep.cpu.core_count"],
capture_output=True, text=True).stdout.strip())
brand_string = subprocess.run(
["sysctl", "-n", "machdep.cpu.brand_string"],
capture_output=True, text=True).stdout.strip()
memsize = int(subprocess.run(
["sysctl", "-n", "hw.memsize"],
capture_output=True, text=True).stdout.strip()) / 1024**3
return f"{core_count:d}-core {brand_string}, {memsize} GB memory"
if platform.system() == "Linux":
lscpu = subprocess.run(
["lscpu"], capture_output=True, text=True).stdout
cores_per_socket = int(
re.search(r"Core\(s\) per socket:\s*(\d*)", lscpu).group(1))
sockets = int(
re.search(r"Socket\(s\):\s*(\d*)", lscpu).group(1))
cpu_freq = (
float(re.search(r"CPU max MHz:\s*(.+)", lscpu).group(1)) / 1000)
model_name = re.search(r"Model name:\s*(.+)", lscpu).group(1)
meminfo = subprocess.run(
["cat", "/proc/meminfo"], capture_output=True, text=True).stdout
memsize = (
int(re.search(r"MemTotal:\s*(\d*) kB", meminfo).group(1)) / 1024**2)
return ((f"{sockets}x" if sockets > 1 else "")
+ f"{cores_per_socket}-core {cpu_freq} GHz {model_name}, {memsize:.1f} GB memory")
return ""
def get_fixture_dir():
return (pathlib.Path(__file__).parents[1] / "fixtures").resolve()
def sim_exe_name():
return "rigid_ipc_sim"
def find_sim_exe():
for build_dir in (pathlib.Path("."), pathlib.Path(__file__).parents[1] / "build"):
for sub_dir in "", "release", "debug":
sim_exe = build_dir / sub_dir / sim_exe_name()
if sim_exe.is_file():
return sim_exe.resolve()
return None
def create_parser():
parser = argparse.ArgumentParser(
description="Run all scenes and save a CSV of the results.")
parser.add_argument(
"--sim-exe", metavar=f"path/to/{sim_exe_name()}", type=pathlib.Path,
default=find_sim_exe(), help="path to simulation executable")
parser.add_argument(
"--loglevel", default=3, type=int, choices=range(7),
help="set log level 0=trace, 1=debug, 2=info, 3=warn, 4=error, 5=critical, 6=off")
return parser
def parse_arguments():
parser = create_parser()
args = parser.parse_args()
if args.sim_exe is None:
parser.exit(1, "Simulation executable is required!\n")
return args
def append_stem(p, stem_suffix):
# return p.with_stem(p.stem + stem_suffix)
return p.parent / (p.stem + stem_suffix + p.suffix)
def main():
args = parse_arguments()
fixture_dir = get_fixture_dir()
machine_info = get_machine_info()
weak_1t_df = pandas.DataFrame(columns=[
"num_threads", "num_bodies", "num_vertices", "num_edges", "num_faces",
"timestep", "num_timesteps", "dhat", "eps_d", "avg_num_contacts",
"max_num_contacts", "avg_solver_iterations", "max_solver_iterations",
"avg_step_time", "max_step_time", "total_runtime (s)", "memory (MB)",
"machine"])
max_threads = 64
"""
for thread_count in range(1, max_threads + 1):
scene = (fixture_dir / "3D" / "scalability" /
"weak" / f"{thread_count:02d}threads.json")
sim_output_dir = (pathlib.Path("output") / "3D" / "scalability" /
"weak" / f"{thread_count:02d}threads")
subprocess.run([str(args.sim_exe), --ngui, str(scene.resolve()),
str(sim_output_dir),
"--loglevel", str(args.loglevel),
"--nthreads", str(1)
])
with open(sim_output_dir / "sim.json") as sim_output:
sim_json = json.load(sim_output)
sim_args = sim_json["args"]
sim_stats = sim_json["stats"]
df_row = {
"num_threads": thread_count,
"num_bodies": sim_stats["num_bodies"],
"num_vertices": sim_stats["num_vertices"],
"num_edges": sim_stats["num_edges"],
"num_faces": sim_stats["num_faces"],
"timestep": sim_args["timestep"],
"num_timesteps": sim_stats["num_timesteps"],
"dhat": sim_args["distance_barrier_constraint"]["initial_barrier_activation_distance"],
"eps_d": sim_args["newton_solver"]["velocity_conv_tol"],
"avg_num_contacts": numpy.average(sim_stats["num_contacts"]),
"max_num_contacts": max(sim_stats["num_contacts"]),
"avg_solver_iterations": numpy.average(sim_stats["solver_iterations"]),
"max_solver_iterations": max(sim_stats["solver_iterations"]),
"avg_step_time": numpy.average(sim_stats["step_timings"]),
"max_step_time": max(sim_stats["step_timings"]),
"total_runtime (s)": sum(sim_stats["step_timings"]),
"memory (MB)": sim_stats["memory"] / 1024**2,
"machine": machine_info,
}
weak_1t_df.loc[thread_count] = df_row
weak_1t_df.to_csv("weak-scaling-single-thread.csv", index=False)
print(f"Results written to weak-scaling-single-thread.csv")
"""
weak_df = pandas.DataFrame(columns=[
"num_threads", "num_bodies", "num_vertices", "num_edges", "num_faces",
"timestep", "num_timesteps", "dhat", "eps_d", "avg_num_contacts",
"max_num_contacts", "avg_solver_iterations", "max_solver_iterations",
"avg_step_time", "max_step_time", "total_runtime (s)", "memory (MB)",
"machine"])
for thread_count in range(1, max_threads + 1):
scene = (fixture_dir / "3D" / "scalability" /
"weak" / f"{thread_count:02d}threads.json")
sim_output_dir = (pathlib.Path("output") / "3D" / "scalability" /
"weak" / f"{thread_count:02d}threads")
subprocess.run([str(args.sim_exe), "--ngui", str(scene.resolve()),
str(sim_output_dir),
"--loglevel", str(args.loglevel),
"--nthreads", str(thread_count)
])
with open(sim_output_dir / "sim.json") as sim_output:
sim_json = json.load(sim_output)
sim_args = sim_json["args"]
sim_stats = sim_json["stats"]
df_row = {
"num_threads": thread_count,
"num_bodies": sim_stats["num_bodies"],
"num_vertices": sim_stats["num_vertices"],
"num_edges": sim_stats["num_edges"],
"num_faces": sim_stats["num_faces"],
"timestep": sim_args["timestep"],
"num_timesteps": sim_stats["num_timesteps"],
"dhat": sim_args["distance_barrier_constraint"]["initial_barrier_activation_distance"],
"eps_d": sim_args["newton_solver"]["velocity_conv_tol"],
"avg_num_contacts": numpy.average(sim_stats["num_contacts"]),
"max_num_contacts": max(sim_stats["num_contacts"]),
"avg_solver_iterations": numpy.average(sim_stats["solver_iterations"]),
"max_solver_iterations": max(sim_stats["solver_iterations"]),
"avg_step_time": numpy.average(sim_stats["step_timings"]),
"max_step_time": max(sim_stats["step_timings"]),
"total_runtime (s)": sum(sim_stats["step_timings"]),
"memory (MB)": sim_stats["memory"] / 1024**2,
"machine": machine_info,
}
weak_df.loc[thread_count] = df_row
weak_df.to_csv("weak-scaling.csv", index=False)
print(f"Results written to weak-scaling.csv")
exit(0)
strong_df = pandas.DataFrame(columns=[
"num_threads", "num_bodies", "num_vertices", "num_edges", "num_faces",
"timestep", "num_timesteps", "dhat", "eps_d", "avg_num_contacts",
"max_num_contacts", "avg_solver_iterations", "max_solver_iterations",
"avg_step_time", "max_step_time", "total_runtime (s)", "memory (MB)",
"machine"])
for thread_count in range(1, max_threads + 1):
scene = fixture_dir / "3D" / "scalability" / "strong.json"
sim_output_dir = pathlib.Path(
"output") / "3D" / "scalability" / "strong"
subprocess.run([str(args.sim_exe), "--ngui", str(scene.resolve()),
str(sim_output_dir),
"--loglevel", str(args.loglevel),
"--nthreads", str(thread_count)
])
with open(sim_output_dir / "sim.json") as sim_output:
sim_json = json.load(sim_output)
sim_args = sim_json["args"]
sim_stats = sim_json["stats"]
df_row = {
"num_threads": thread_count,
"num_bodies": sim_stats["num_bodies"],
"num_vertices": sim_stats["num_vertices"],
"num_edges": sim_stats["num_edges"],
"num_faces": sim_stats["num_faces"],
"timestep": sim_args["timestep"],
"num_timesteps": sim_stats["num_timesteps"],
"dhat": sim_args["distance_barrier_constraint"]["initial_barrier_activation_distance"],
"eps_d": sim_args["newton_solver"]["velocity_conv_tol"],
"avg_num_contacts": numpy.average(sim_stats["num_contacts"]),
"max_num_contacts": max(sim_stats["num_contacts"]),
"avg_solver_iterations": numpy.average(sim_stats["solver_iterations"]),
"max_solver_iterations": max(sim_stats["solver_iterations"]),
"avg_step_time": numpy.average(sim_stats["step_timings"]),
"max_step_time": max(sim_stats["step_timings"]),
"total_runtime (s)": sum(sim_stats["step_timings"]),
"memory (MB)": sim_stats["memory"] / 1024**2,
"machine": machine_info,
}
strong_df.loc[thread_count] = df_row
strong_df.to_csv("strong-scaling.csv", index=False)
print(f"Results written to strong-scaling.csv")
if __name__ == "__main__":
main()