Skip to content

Commit 61d8cd4

Browse files
Added python scripts to conduct shared and distributed memory testing on Beskow
1 parent 5db9238 commit 61d8cd4

4 files changed

Lines changed: 299 additions & 5 deletions

File tree

python/BeskowDistributedMemory.py

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
# -----------------------------------------------------------------------------
2+
# Author : Albert Akhriev, albert_akhriev@ie.ibm.com
3+
# Copyright : IBM Research Ireland, 2017-2018
4+
# -----------------------------------------------------------------------------
5+
6+
""" This script runs several simulations with increasing problem size
7+
utilizing all available CPUs. It saves the execution time of each
8+
simulation in a file that can be used to plot the scalability profile.
9+
Essential parameters, listed in the first lines, include the set of
10+
problem sizes and integration period.
11+
Each simulation is twofold. First, we run the Python forward solver that
12+
generates the ground-truth and observations ("ObservationsGenerator.py").
13+
The Python code itself uses the C++ code running in the special mode for
14+
generating sensor locations (scenario "sensors"). Second, the C++ data
15+
assimilation application is launched (scenario "simulation") with
16+
observations generated by "ObservationsGenerator.py".
17+
The results of all the simulations are accumulated in the output
18+
directory and can be visualized later on by the script "Visualize.py".
19+
The configuration file "amdados.conf" is used in all the simulations with
20+
modification of three parameters: grid sizes (number of subdomains) in both
21+
dimensions and integration time. Other parameters remain intact. It is not
22+
recommended to tweak parameters unless their meaning is absolutely clear.
23+
If you had modified the parameters, please, consider to rerun this script
24+
because the results in the output directory a not valid any longer.
25+
The script was designed to fulfil the formal requirements of the
26+
Allscale project.
27+
"""
28+
print(__doc__)
29+
30+
from timeit import default_timer as timer
31+
import os, cmd
32+
from RandObservationsGenerator import InitDependentParams, Amdados2D_quick
33+
from Utility import *
34+
import argparse
35+
36+
37+
# Get subdomain sizes as multiplier factors
38+
39+
## read arguments describing filename, number of nodes and number of threads
40+
##########################
41+
# Arguments and settings #
42+
##########################
43+
parser = argparse.ArgumentParser()
44+
parser.add_argument('filename', type=str, help='filename to write scalability results to')
45+
parser.add_argument('nnodes', type=int, help='number of nodes to execute on')
46+
parser.add_argument('nthreads', type=int, help='number of threads per node')
47+
parser.add_argument('ndomains', type=int, help='number of subdomains')
48+
args = parser.parse_args()
49+
50+
ResultsFileName = args.filename
51+
number_of_nodes = args.nnodes
52+
nthreads = args.nthreads
53+
grid = args.ndomains
54+
55+
56+
57+
# Integration period in seconds.
58+
IntegrationPeriod = 25
59+
IntegrationNsteps = 50
60+
61+
# Configurations for Monitoring and resilience to test
62+
MONITORING = [0]
63+
RESILIENCE = [0]
64+
65+
66+
# Path to the C++ executable.
67+
AMDADOS_EXE = os.path.join(os.getcwd(),"targetcode/amdados_cc")
68+
69+
print('filename = ', ResultsFileName)
70+
print('nnodes = ', number_of_nodes)
71+
print('nthreads = ', nthreads)
72+
print('ndomains = ', grid)
73+
74+
75+
execute_time = np.zeros([1, 7])
76+
77+
if __name__ == "__main__":
78+
try:
79+
# Read configuration file.
80+
conf = Configuration(os.path.join(os.getcwd(),"amdados.conf"))
81+
# Create the output directory, if it does not exist.
82+
conf.output_dir = os.path.join(os.getcwd(),conf.output_dir)
83+
if not os.path.isdir(conf.output_dir):
84+
os.mkdir(conf.output_dir)
85+
# Check existence of "amdados" application executable.
86+
assert os.path.isfile(AMDADOS_EXE), "amdados executable was not found"
87+
## open scalability file and add header
88+
# HeaderTxt = ["ProblemSize,NNodes, NThreads, ALLSCALE_MONITOR, ALLSCALE_RESILIENCE, TotalRuntime, Throughput(Sdom/s)"]
89+
time_file = os.path.join(conf.output_dir, ResultsFileName)
90+
f = open(time_file, 'ab')
91+
i = 0
92+
93+
# Modify parameters given the current grid size.
94+
setattr(conf, "num_subdomains_x", int(grid))
95+
setattr(conf, "num_subdomains_y", int(grid))
96+
setattr(conf, "integration_period", int(IntegrationPeriod))
97+
setattr(conf, "integration_nsteps", int(IntegrationNsteps))
98+
InitDependentParams(conf)
99+
conf.PrintParameters()
100+
config_file = conf.WriteParameterFile(os.path.join(conf.output_dir,"scalability_test.conf"))
101+
os.sync()
102+
# Get the starting time.
103+
start_time = timer()
104+
105+
# Run C++ data assimilation application.
106+
for MonitorFlag in MONITORING:
107+
for ResilienceFlag in RESILIENCE:
108+
print("##################################################")
109+
print("Testing Framework for AllScale project")
110+
print("Simulation by 'amdados' to check scalability and correctness")
111+
print("Testing Configuration Setup")
112+
print("GridSize =", grid, "ALLSCALE_MONITOR = ", MonitorFlag,
113+
"ALLSCALE_RESILIENCE = ", ResilienceFlag)
114+
print("##################################################")
115+
print(AMDADOS_EXE, config_file)
116+
output = subprocess.Popen(["aprun", "-n" +str(number_of_nodes), "-d" + str(nthreads),
117+
AMDADOS_EXE, "--scenario", "benchmark:" +str(grid),"--config", config_file,
118+
"--hpx:threads=" + str(nthreads), "--hpx:bind=none"], stdout=subprocess.PIPE,
119+
env=dict(os.environ, ALLSCALE_MONITOR=str(MonitorFlag), ALLSCALE_RESILIENCE=str(ResilienceFlag)))
120+
output.wait()
121+
# Strip the execution time from stdout, both total simulation time
122+
# and throughput (subdomain/s)
123+
strip_output = str(output.communicate()[0]).split('\\n')
124+
for line in strip_output:
125+
if re.search("Simulation", line):
126+
simtime_string = line
127+
if re.search("Throughput", line):
128+
throughput_string = line
129+
simtime_secs = float(simtime_string.split(' ')[2][:-1])
130+
throughput_secs = float(throughput_string.split(' ')[1])
131+
132+
# Get the execution time and corresponding (global) problem size
133+
# and save the current scalability profile into the file.
134+
problem_size = ( conf.num_subdomains_x * conf.num_subdomains_y )
135+
execute_time[0, :] = [problem_size, number_of_nodes, nthreads, MonitorFlag, ResilienceFlag, simtime_secs, throughput_secs]
136+
i += 1
137+
np.savetxt(f, execute_time)
138+
f.close()
139+
except subprocess.CalledProcessError as error:
140+
traceback.print_exc()
141+
if error.output is not None:
142+
print("ERROR: " + str(error.output))
143+
else:
144+
print("CalledProcessError")
145+
except AssertionError as error:
146+
traceback.print_exc()
147+
print("ERROR: " + str(error.args))
148+
except ValueError as error:
149+
traceback.print_exc()
150+
print("ERROR: " + str(error.args))
151+
except Exception as error:
152+
traceback.print_exc()
153+
print("ERROR: " + str(error.args))
154+

python/BeskowSharedmemory.py

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# -----------------------------------------------------------------------------
2+
# Author : Albert Akhriev, albert_akhriev@ie.ibm.com
3+
# Copyright : IBM Research Ireland, 2017-2018
4+
# -----------------------------------------------------------------------------
5+
6+
""" This script runs several simulations with increasing problem size
7+
utilizing all available CPUs. It saves the execution time of each
8+
simulation in a file that can be used to plot the scalability profile.
9+
Essential parameters, listed in the first lines, include the set of
10+
problem sizes and integration period.
11+
Each simulation is twofold. First, we run the Python forward solver that
12+
generates the ground-truth and observations ("ObservationsGenerator.py").
13+
The Python code itself uses the C++ code running in the special mode for
14+
generating sensor locations (scenario "sensors"). Second, the C++ data
15+
assimilation application is launched (scenario "simulation") with
16+
observations generated by "ObservationsGenerator.py".
17+
The results of all the simulations are accumulated in the output
18+
directory and can be visualized later on by the script "Visualize.py".
19+
The configuration file "amdados.conf" is used in all the simulations with
20+
modification of three parameters: grid sizes (number of subdomains) in both
21+
dimensions and integration time. Other parameters remain intact. It is not
22+
recommended to tweak parameters unless their meaning is absolutely clear.
23+
If you had modified the parameters, please, consider to rerun this script
24+
because the results in the output directory a not valid any longer.
25+
The script was designed to fulfil the formal requirements of the
26+
Allscale project.
27+
"""
28+
print(__doc__)
29+
30+
from timeit import default_timer as timer
31+
import os, cmd
32+
from RandObservationsGenerator import InitDependentParams, Amdados2D_quick
33+
from Utility import *
34+
35+
# Get subdomain sizes as multiplier factors
36+
37+
38+
nthreads = np.arange(0,32,4)
39+
GridSizes = np.zeros([len(nthreads), 2])
40+
nthreads[0] = 1
41+
GridSizes[0:4, :] = ([4,2], [8,4], [8,8], [12, 8])
42+
for i in range(4, len(nthreads)):
43+
GridSizes[i, :] = [nthreads[i], 8]
44+
problem_size= GridSizes[:,0]*GridSizes[:,1]
45+
46+
print("GridSizes = ", GridSizes)
47+
print("nthreads = ", nthreads)
48+
49+
execute_time = np.zeros([len(nthreads), 4])
50+
# Integration period in seconds.
51+
IntegrationPeriod = 25
52+
IntegrationNsteps = 50
53+
# Path to the C++ executable.
54+
55+
# Path to the C++ executable.
56+
AMDADOS_EXE = os.path.join(os.getcwd(),"targetcode/amdados_cc")
57+
58+
59+
if __name__ == "__main__":
60+
try:
61+
# Read configuration file.
62+
conf = Configuration(os.path.join(os.getcwd(),"amdados.conf"))
63+
# Create the output directory, if it does not exist.
64+
print(conf.output_dir)
65+
conf.output_dir = os.path.join(os.getcwd(),conf.output_dir)
66+
print(conf.output_dir)
67+
68+
if not os.path.isdir(conf.output_dir):
69+
os.mkdir(conf.output_dir)
70+
# Check existence of "amdados" application executable.
71+
assert os.path.isfile(AMDADOS_EXE), "amdados executable was not found"
72+
73+
# For all the grid sizes in the list ...
74+
exe_time_profile = np.zeros((len(GridSizes),2))
75+
for i in range(0, len(nthreads)):
76+
grid = GridSizes[i, :]
77+
Nproc = nthreads[i]
78+
# Modify parameters given the current grid size.
79+
setattr(conf, "num_subdomains_x", int(grid[0]))
80+
setattr(conf, "num_subdomains_y", int(grid[1]))
81+
setattr(conf, "integration_period", int(IntegrationPeriod))
82+
setattr(conf, "integration_nsteps", int(IntegrationNsteps))
83+
InitDependentParams(conf)
84+
conf.PrintParameters()
85+
config_file = conf.WriteParameterFile(os.path.join(conf.output_dir,"scalability_test.conf"))
86+
os.sync()
87+
# Python simulator generates the ground-truth and observations.
88+
Amdados2D_quick(config_file, False)
89+
90+
# Get the starting time.
91+
start_time = timer()
92+
93+
# Run C++ data assimilation application.
94+
print("##################################################")
95+
print("Simulation by 'amdados' application for series of hpx threads")
96+
print("Initial simulations for Oceans paper")
97+
print("##################################################")
98+
print(AMDADOS_EXE, config_file)
99+
output = subprocess.Popen(["aprun", "-n", "1", "-d" + str(Nproc), AMDADOS_EXE, "--scenario", "simulation",
100+
"--config", config_file, "--hpx:threads=" + str(Nproc), "--hpx:bind=none"], stdout=subprocess.PIPE)
101+
output.wait()
102+
os.sync()
103+
104+
# Strip the execution time from stdout, both total simulation time
105+
# and throughput (subdomain/s)
106+
strip_output = str(output.communicate()[0]).split('\\n')
107+
for line in strip_output:
108+
print(line)
109+
if re.search("Simulation", line):
110+
simtime_string = line
111+
if re.search("Throughput", line):
112+
throughput_string = line
113+
print('simtime string =', simtime_string)
114+
simtime_secs = float(simtime_string.split(' ')[2][:-1])
115+
throughput_secs = float(throughput_string.split(' ')[1])
116+
117+
118+
# Get the execution time and corresponding (global) problem size
119+
# and save the current scalability profile into the file.
120+
problem_size = ( conf.num_subdomains_x * conf.num_subdomains_y )
121+
execute_time[i, :] = [problem_size, Nproc, simtime_secs, throughput_secs]
122+
np.savetxt(os.path.join(conf.output_dir, "scalability_performance.txt"),
123+
execute_time)
124+
125+
except subprocess.CalledProcessError as error:
126+
traceback.print_exc()
127+
if error.output is not None:
128+
print("ERROR: " + str(error.output))
129+
else:
130+
print("CalledProcessError")
131+
except AssertionError as error:
132+
traceback.print_exc()
133+
print("ERROR: " + str(error.args))
134+
except ValueError as error:
135+
traceback.print_exc()
136+
print("ERROR: " + str(error.args))
137+
except Exception as error:
138+
traceback.print_exc()
139+
print("ERROR: " + str(error.args))
140+

python/ObservationsGenerator.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@
1717
from Utility import *
1818

1919
# Full-path name of C++ executable.
20-
AMDADOS_EXE = "targetcode/amdados_cc"
21-
20+
AMDADOS_EXE = os.path.join(os.getcwd(),"targetcode/amdados_cc")
2221

2322
def Amdados2D(config_file, demo):
2423
""" Advection-diffusion PDE forward solver.
@@ -41,7 +40,7 @@ def Amdados2D(config_file, demo):
4140
print("generating a new one ...")
4241
assert os.path.exists(AMDADOS_EXE), (
4342
"Application 'amdados' must be built before running this script")
44-
subprocess.run([AMDADOS_EXE, "--scenario", "sensors",
43+
subprocess.run(["aprun", "-n", "1", AMDADOS_EXE, "--scenario", "sensors",
4544
"--config", config_file], check=True)
4645
subprocess.run("sync", check=True)
4746
print("")

python/RandObservationsGenerator.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
from Utility import *
1111

1212
# Full-path name of C++ executable.
13-
AMDADOS_EXE = "targetcode/amdados_cc"
13+
AMDADOS_EXE = os.path.join(os.getcwd(),"targetcode/amdados_cc")
14+
1415

1516

1617
def Amdados2D_quick(config_file, demo):
@@ -34,7 +35,7 @@ def Amdados2D_quick(config_file, demo):
3435
print("generating a new one ...")
3536
assert os.path.exists(AMDADOS_EXE), (
3637
"Application 'amdados' must be built before running this script")
37-
amdados = subprocess.Popen([AMDADOS_EXE, "--scenario", "sensors",
38+
amdados = subprocess.Popen(["aprun", "-n", "1", AMDADOS_EXE, "--scenario", "sensors",
3839
"--config", config_file])
3940
amdados.wait()
4041
print("")

0 commit comments

Comments
 (0)