summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoshua Bakita <jbakita@cs.unc.edu>2020-10-24 18:15:13 -0400
committerJoshua Bakita <jbakita@cs.unc.edu>2020-10-24 18:15:13 -0400
commit1026e429095b1b6054fe81022bdeb173d7eccb47 (patch)
treef20244062650df30809cacc7bb720b85a78c0356
parent3975bcd4ada118ac66be630b17fd8407aad8ffd8 (diff)
Fixup the case study script
New features: - Checks arguments - Checks that we're root first - Checks if task launches succeed - Checks that a case study is not already running Fixes: - Removes invalid uses of sudo - Fixes use of ',' rather than ';' in resctrl specification - Fixes PID determination - Always launches Level-C tasks as asynchronous threads Additionally converts the whole file to only use spaces and to be directly executable.
-rwxr-xr-x[-rw-r--r--]run_case_study.py274
1 files changed, 185 insertions, 89 deletions
diff --git a/run_case_study.py b/run_case_study.py
index bcbaca6..eff06fe 100644..100755
--- a/run_case_study.py
+++ b/run_case_study.py
@@ -1,3 +1,5 @@
1#!/usr/bin/python3
2# Make sure to run this as root!!!!!
1import os 3import os
2import sys 4import sys
3import re 5import re
@@ -5,35 +7,78 @@ import csv
5import time 7import time
6import subprocess 8import subprocess
7 9
10A_SUITE = 1
11A_BIN = 2
12A_CRIT = 3
13A_PERIOD = 5
14
15P_CORE = 0
16P_CRIT = 1
17P_T1_ID = 2
18P_T2_ID = 5
19
20T_ID = 0
21T_BIN = 1
22T_PERIOD = 2
23T_CCX = 3
24
25CRIT_LEVEL_C = 2
26
8all_pids=[] 27all_pids=[]
9def run(command): 28def run(command):
10 print(command) 29 print(command)
11 os.system(command) 30 os.system(command)
31
12def addpid(pid): 32def addpid(pid):
13 with open("./pids.txt", "a") as f: 33 with open("./pids.txt", "a") as f:
14 f.write(str(pid) + "\n") 34 f.write(str(pid) + "\n")
35def ID2PID(lookupID):
36 res = None
37 # Find benchmark PID (avoid getting shell or numactl PID)
38 try:
39 res = subprocess.check_output("pgrep -af " + lookupID + " | grep -v numactl | cut -d ' ' -f 1", shell=True)
40 except:
41 res = None
42 if res:
43 # Ignore the newline
44 return res.decode("utf-8").strip()
45 else:
46 return None
15 47
16 48def main(pathName):
17def main():
18 with open("./pids.txt", "w") as f: 49 with open("./pids.txt", "w") as f:
19 f.write("") 50 f.write("")
20 51
21 pathName = sys.argv[1]
22 tacle_pairs_path = "./all_pairs" 52 tacle_pairs_path = "./all_pairs"
23 tacle_baseline_path = "./baseline" 53 tacle_baseline_path = "./baseline"
24 dis_path = "./dis" 54 dis_path = "./dis"
55 # List of lists
56 # Each list represents the parameters for a task as:
57 # [id, suite, binary name, criticality level (0-base), pet us (unused), period ms, wss (unused)]
25 all_tasks = [] 58 all_tasks = []
59 # List of lists
60 # Each list represents the parameters for a pairing as:
61 # [core, criticality level (0-base), task 1 ID, task 1 name (unused), task 1 period, task 2 ID, task 2 name, task 2 period]
62 # if task 1 ID = task 2 ID, it's not actually a pair at all
26 levelAB = [] 63 levelAB = []
27 levelC = [] 64 levelC = []
28 levelC_s = [] 65 levelC_s = []
29 dis_inputs = dict() 66 input_cmd = {}
30 dis_inputs["field"] = "./gen_input.py field inputs/Field/in0 2097152" 67 # Load input command for each binary
31 dis_inputs["matrix"] = "gen_input.py matrix inputs/Matrix/in0 2097152" 68 with open("baseline/tacleNames.txt") as f:
32 dis_inputs["neighborhood"] = "./gen_input.py neighborhood inputs/Neighborhood/in0 2097152" 69 for benchName in f:
33 dis_inputs["pointer"] = "./gen_input.py pointer inputs/Pointer/in0 2097152" 70 # TACLeBench doesn't need inputs
34 dis_inputs["transitive"] = "./gen_input.py transitive inputs/Transitive/in0 2097152" 71 input_cmd[benchName.strip()] = "echo ' '"
35 dis_inputs["update"] = "./gen_input.py update inputs/Update/in0 2097152" 72 with open("SD-VBS/sd-vbsNames.txt") as f:
73 for line in f:
74 name, cmd = line.split(maxsplit=1)
75 input_cmd[name.replace("./", "")] = cmd.replace("./", "./SD-VBS/").strip()
76 with open("dis/dis2MbInNames.txt") as f:
77 for line in f:
78 name, cmd = line.split(maxsplit=1)
79 input_cmd[name.replace("./", "")] = cmd.replace("./", "./dis/").strip()
36 80
81 # Load task specifications
37 with open(pathName+"/all_tasks.csv", "r") as csv_file: 82 with open(pathName+"/all_tasks.csv", "r") as csv_file:
38 csv_reader = csv.reader(csv_file, delimiter = ',') 83 csv_reader = csv.reader(csv_file, delimiter = ',')
39 line = 0 84 line = 0
@@ -56,6 +101,7 @@ def main():
56 for row in csv_reader: 101 for row in csv_reader:
57 if(len(row) < 3): 102 if(len(row) < 3):
58 continue 103 continue
104 # Start of a cluster - read definition
59 if(row[0] == "threaded" or row[0] == "solo"): 105 if(row[0] == "threaded" or row[0] == "solo"):
60 threaded = row[0] == "threaded" 106 threaded = row[0] == "threaded"
61 if(row[1] == "4"): 107 if(row[1] == "4"):
@@ -63,6 +109,7 @@ def main():
63 else: 109 else:
64 ccx = "0" 110 ccx = "0"
65 continue 111 continue
112 # Start of a thread speficication
66 if(row[0] != "task id" and row[0] != ""): 113 if(row[0] != "task id" and row[0] != ""):
67 row.append(ccx) 114 row.append(ccx)
68 if(threaded): 115 if(threaded):
@@ -71,9 +118,9 @@ def main():
71 row.append("s") 118 row.append("s")
72 levelC.append(row) 119 levelC.append(row)
73 line += 1 120 line += 1
121 ### Allocate Cache Ways ###
74 run('mount -t resctrl resctrl /sys/fs/resctrl') 122 run('mount -t resctrl resctrl /sys/fs/resctrl')
75 run('sudo echo "L3:0=0000,1=0000,2=0000,3=0000" > sudo /sys/fs/resctrl/schemata') 123# run('echo "L3:0=0000,1=0000,2=0000,3=0000" > /sys/fs/resctrl/schemata')
76
77 with open(pathName+"/l3alloc.csv", "r") as csv_file: 124 with open(pathName+"/l3alloc.csv", "r") as csv_file:
78 csv_reader = csv.reader(csv_file, delimiter = ',') 125 csv_reader = csv.reader(csv_file, delimiter = ',')
79 line = 0 126 line = 0
@@ -86,109 +133,158 @@ def main():
86 # Level C allocation 133 # Level C allocation
87 if(core == 1): 134 if(core == 1):
88 run("mkdir -p /sys/fs/resctrl/level-c-ccx-0") 135 run("mkdir -p /sys/fs/resctrl/level-c-ccx-0")
89 run('sudo echo "L3:0=' + ("%0.4x" % (int("1"*way_C, 2))) + ',1=0000,2=0000,3=0000" > sudo /sys/fs/resctrl/level-c-ccx-0/schemata') 136 run('echo "L3:0=' + ("%0.4x" % (int("1"*way_C, 2))) + ';1=0000;2=0000;3=0000" > /sys/fs/resctrl/level-c-ccx-0/schemata')
90 137
91 if(core == 4): 138 if(core == 4):
92 run("mkdir -p /sys/fs/resctrl/level-c-ccx-1") 139 run("mkdir -p /sys/fs/resctrl/level-c-ccx-1")
93 run('sudo echo "L3:0=0000, 1=' + ("%0.4x" % (int("1"*way_C, 2))) + ',2=0000,3=0000" > sudo /sys/fs/resctrl/level-c-ccx-1/schemata') 140 run('echo "L3:0=0000;1=' + ("%0.4x" % (int("1"*way_C, 2))) + ';2=0000;3=0000" > /sys/fs/resctrl/level-c-ccx-1/schemata')
94 run('mkdir -p /sys/fs/resctrl/level-ab-core-' + str(core)) 141 run('mkdir -p /sys/fs/resctrl/level-ab-core-' + str(core))
95 if(core < 4): 142 if(core < 4):
96 run('sudo echo "L3:0=' + ("%0.4x" % (int("1"*way_AB + "0"*(16-way_AB), 2))) + ',1=0000,2=0000,3=0000" > sudo /sys/fs/resctrl/level-ab-core-' + str(core) + '/schemata') 143 run('echo "L3:0=' + ("%0.4x" % (int("1"*way_AB + "0"*(16-way_AB), 2))) + ';1=0000;2=0000;3=0000" > /sys/fs/resctrl/level-ab-core-' + str(core) + '/schemata')
97 else: 144 else:
98 run('sudo echo "L3:0=0000,1=' + ("%0.4x" % (int("1"*way_AB + "0"*(16-way_AB), 2))) + ',2=0000,3=0000" > sudo /sys/fs/resctrl/level-ab-core-' + str(core) + '/schemata') 145 run('echo "L3:0=0000;1=' + ("%0.4x" % (int("1"*way_AB + "0"*(16-way_AB), 2))) + ';2=0000;3=0000" > /sys/fs/resctrl/level-ab-core-' + str(core) + '/schemata')
99 line += 1 146 line += 1
100 run("sudo rm -rf /dev/shm/*") 147 ### Cleanup Old State ###
148 run("rm -rf /dev/shm/*")
101 pairID = 0 149 pairID = 0
102 i = 0 150 i = 0
103 for task in levelAB: 151 ### Dispatch all the Level-A and -B paired and unpaired tasks ###
104 task1 = int(task[2]) 152 for pairing in levelAB:
105 task2 = int(task[5]) 153 if i > 2:
106 name1 = all_tasks[task1][2] 154 break
107 name2 = all_tasks[task2][2] 155 i += 1
108 if(name1 == "rijndael_e"): 156
109 name1 = "rijndael_enc" 157 task1 = int(pairing[P_T1_ID])
110 158 task2 = int(pairing[P_T2_ID])
111 if(name2 == "rijndael_e"): 159 # Lookup periods and binary location
112 name2 = "rijndael_enc" 160 name1 = all_tasks[task1][A_BIN]
113 period1 = all_tasks[task1][5] 161 name2 = all_tasks[task2][A_BIN]
114 period2 = all_tasks[task2][5] 162 period1 = all_tasks[task1][A_PERIOD]
115 suite1 = all_tasks[task1][1] 163 period2 = all_tasks[task2][A_PERIOD]
116 suite2 = all_tasks[task2][1] 164 suite1 = all_tasks[task1][A_SUITE]
117 core = task[0] 165 suite2 = all_tasks[task2][A_SUITE]
118 criticality = task[1] 166 core = pairing[P_CORE]
167 criticality = pairing[P_CRIT]
119 binary = "" 168 binary = ""
120 binary1 = "" 169 binary1 = ""
121 binary2 = "" 170 binary2 = ""
122 arg = "" 171 arg = ""
123 if(task1 == task2): 172 # If the IDs match, this isn't a pair at all
124 arg = " NULL -1 " + core + " NULL 0 " + period1 + " " + criticality 173 if task1 == task2:
125 174 if suite1 == "TACLe":
126 if(suite1 == "TACLe"): 175 binary = "./baseline/bin/" + name1
127 binary = "./baseline/bin/" + name1 + arg 176 elif suite1 == "SD-VBS":
177 binary = "./SD-VBS/" + name1
178 elif suite1 == "DIS":
179 binary = "./dis/" + name1
128 else: 180 else:
129 binary = dis_inputs[name1] + " | ./dis/" + name1 + arg 181 print("Invalid suite name " + suite1 + " in Level-A/-B tasks! Exiting...")
130 proc = subprocess.Popen([binary], shell = True) 182 exit(1)
131 #print(binary + " &" )
132 pid = proc.pid
133 run("sudo echo " + str(pid) + " > sudo /sys/fs/resctrl/level-ab-core-" + core + "/tasks")
134 addpid(pid)
135 else:
136 pairID += 1
137 arg1 = " NULL -1 " + core + " 0 NULL NULL 0 " + str(pairID) + " " + period1 + " " + criticality
138 arg2 = " NULL -1 " + str(int(core)+16) + " 0 NULL NULL 0 " + str(pairID) + " " + period2 + " " + criticality
139 183
140 if(suite1 == "TACLe"): 184 lookupID = name1 + task1
141 binary1 = "./all_pairs/bin/" + name1 + arg1 185 if ID2PID(lookupID):
142 binary2 = "./all_pairs/bin/" + name2 + arg2 186 print("ERROR: Task ID {} is already running! Did you end the previous case study?".format(lookupID))
187 exit(1)
188 # Arg format: <unique name> <infinite loops> <core> <NULL runID> <no output> <period> <crit lvl>
189 arg = " " + lookupID + " -1 " + core + " NULL 0 " + period1 + " " + criticality
190 bench_tsk = subprocess.Popen(input_cmd[name1] + " | numactl --interleave=all " + binary + arg, shell = True)
191 pid_str = ID2PID(lookupID)
192 if not pid_str:
193 print("Unable to launch {} as a solo task! Exiting...".format(name1))
194 exit(1)
195 # Add this task to the appropriate cache partition (Class of Service in Intel CAT terms)
196 run("echo " + pid_str + " > /sys/fs/resctrl/level-ab-core-" + core + "/tasks")
197 addpid(pid_str)
198 else:
199 if suite1 == "TACLe":
200 binary1 = "./all_pairs/bin/" + name1
201 binary2 = "./all_pairs/bin/" + name2
202 elif suite1 == "SD-VBS":
203 binary1 = "./SD-VBS/" + name1 + "_all"
204 binary2 = "./SD-VBS/" + name2 + "_all"
205 elif suite1 == "DIS":
206 binary1 = "./dis/" + name1 + "_all"
207 binary2 = "./dis/" + name2 + "_all"
143 else: 208 else:
144 binary1 = dis_inputs[name1] + " | ./dis/" + name1 + "_all" + arg1 209 print("Invalid suite name " + suite1 + " in Level-A/-B tasks! Exiting...")
145 binary2 = dis_inputs[name2] + " | ./dis/" + name2 + "_all" + arg2 210 exit(1)
146 proc1 = subprocess.Popen(["sudo numactl --membind=0 " + binary1], shell = True)
147 proc2 = subprocess.Popen(["sudo numactl --membind=1 " + binary2], shell = True)
148 #print("sudo numactl --membind=0 " + binary1 + " &")
149 #print("sudo numactl --membind=1 " + binary2 + " &")
150 pid1 = proc2.pid + 1
151 pid2 = proc2.pid + 3
152
153 run("sudo echo " + str(pid1) + " > sudo /sys/fs/resctrl/level-ab-core-" + core + "/tasks")
154 run("sudo echo " + str(pid2) + " > sudo /sys/fs/resctrl/level-ab-core-" + core + "/tasks")
155 addpid(pid1)
156 addpid(pid2)
157 211
212 pairID += 1 # Used for sem/shm identification in the pair task
213 thread = str(int(core) + 16) # How Linux numbers SMT threads on the 3950X
214 lookupID1 = name1 + str(task1)
215 lookupID2 = name2 + str(task2)
216 if ID2PID(lookupID1) or ID2PID(lookupID2):
217 print("ERROR: Part of the pair containing task IDs {} and {} is already running! Did you end the previous case study?".format(lookupID1, lookupID2))
218 exit(1)
219 # Arg format: <unique name> <infinite loops> <core> <0 other core> <NULL other name> <NULL runID> <no output> <pairID> <period> <crit lvl>
220 arg1 = " " + lookupID1 + " -1 " + core + " 0 NULL NULL 0 " + str(pairID) + " " + period1 + " " + criticality
221 arg2 = " " + lookupID2 + " -1 " + thread + " 0 NULL NULL 0 " + str(pairID) + " " + period2 + " " + criticality
222 bench_tsk1 = subprocess.Popen(input_cmd[name1] + "| numactl --membind=0 " + binary1 + arg1, shell = True)
223 bench_tsk2 = subprocess.Popen(input_cmd[name2] + "| numactl --membind=1 " + binary2 + arg2, shell = True)
224 # Find benchmark PID (avoid getting shell or numactl PID)
225 pid1_str = ID2PID(lookupID1)
226 pid2_str = ID2PID(lookupID2)
227 if not pid1_str or not pid2_str:
228 print("Unable to launch {} and {} in a pair! Exiting...".format(name1, name2))
229 exit(1)
230 # Add this task to the appropriate cache partition (Class of Service in Intel CAT terms)
231 run("echo " + pid1_str + " > /sys/fs/resctrl/level-ab-core-" + core + "/tasks")
232 run("echo " + pid2_str + " > /sys/fs/resctrl/level-ab-core-" + core + "/tasks")
233 addpid(pid1_str)
234 addpid(pid2_str)
235
236 i = 0
237 ### Dispatch all the Level-C tasks ###
158 for task in levelC: 238 for task in levelC:
159 continue 239 if i > 2:
160 i+=1
161 if(i>8):
162 break 240 break
163 tid = int(task[0]) 241 i += 1
164 name = all_tasks[tid][2]
165 period = all_tasks[tid][5]
166 suite = all_tasks[tid][1]
167 ccx = task[3]
168 threaded = task[4] == "t"
169 arg = ""
170 242
171 if(name == "rijndael_e"): 243 tid = int(task[T_ID])
172 name = "rijndael_enc" 244 name = all_tasks[tid][A_BIN]
173 if(not threaded): 245 period = all_tasks[tid][A_PERIOD]
174 arg = " NULL -1 " + ccx + " NULL 0 " + period + " 2" 246 suite = all_tasks[tid][A_SUITE]
175 else: 247 ccx = task[T_CCX]
176 pairID += 1 248
177 arg = " NULL -1 " + ccx + " 0 NULL NULL 0 " + str(pairID) + " " + period + " 2" 249 if suite == "TACLe":
178 if(suite1 == "TACLe"): 250 binary = "./baseline/bin/" + name
179 binary = "./baseline/bin/" + name1 + arg 251 elif suite == "SD-VBS":
252 binary = "./SD-VBS/" + name
253 elif suite == "DIS":
254 binary = "./dis/" + name
180 else: 255 else:
181 binary = dis_inputs[name1] + " | ./dis/" + name1 + "_all" + arg 256 print("Invalid suite name " + suite + " in Level-A/-B tasks! Exiting...")
257 exit(1)
258 # XXX XXX XXX: FIXME when LITMUS is fixed
259 core = str(int(ccx)*4 + 1);
182 260
183 print(binary + " &") 261 lookupID = name + str(tid)
184 proc = subprocess.Popen([binary + " &"], shell = True) 262 if ID2PID(lookupID):
185 pid = proc.pid 263 print("ERROR: Task ID {} is already running! Did you end the previous case study?".format(lookupID))
186 run("sudo echo " + str(pid) + " > sudo /sys/fs/resctrl/level-ab-ccx-" + ccx + "/tasks") 264 exit(1)
265 # Arg format: <unique name> <infinite loops> <core> <NULL runID> <no output> <period> <crit lvl>
266 arg = " " + lookupID + " -1 " + core + " NULL 0 " + period + " " + str(CRIT_LEVEL_C)
267 bench_tsk = subprocess.Popen(input_cmd[name] + " | numactl --interleave=all " + binary + arg, shell=True)
268 # Find benchmark PID (avoid getting shell or numactl PID)
269 pid_str = ID2PID(lookupID)
270 if not pid_str:
271 print("Unable to launch {} as a Level-C thread! Exiting...".format(name))
272 exit(1)
273 # Add this task to the appropriate cache partition (Class of Service in Intel CAT terms)
274 run("echo " + pid_str + " > /sys/fs/resctrl/level-c-ccx-" + ccx + "/tasks")
275 addpid(pid_str)
187 #os.system("/playpen/mc2/liblitmus/release_ts") 276 #os.system("/playpen/mc2/liblitmus/release_ts")
188 #os.system("ls") 277 #os.system("ls")
189 time.sleep(3) 278 time.sleep(3)
190 279
191if __name__ == "__main__": 280if __name__ == "__main__":
192 main() 281 if len(sys.argv) < 2:
282 print("Usage: " + sys.argv[0] + " <task sets path>")
283 exit(1)
284 if os.geteuid() != 0:
285 print("You must run this script as root to enable cache isolation and access LITMUS-RT.")
286 exit(1)
287 pathName = sys.argv[1]
288 main(pathName)
193 289
194 290