From 192ce5e1d45935e3ccac6d09e7e8763caeb8f9db Mon Sep 17 00:00:00 2001 From: Yiwei Yang <40686366+victoryang00@users.noreply.github.com> Date: Thu, 29 Feb 2024 19:11:24 -0800 Subject: [PATCH] push windows Signed-off-by: victoryang00 --- artifact/bench_windows.py | 107 +++++++++----------- artifact/result/windows.csv | 192 +++++++++++++++--------------------- artifact/result/windows.pdf | Bin 1205 -> 15579 bytes 3 files changed, 127 insertions(+), 172 deletions(-) diff --git a/artifact/bench_windows.py b/artifact/bench_windows.py index 6a58409..ae6c258 100644 --- a/artifact/bench_windows.py +++ b/artifact/bench_windows.py @@ -3,6 +3,7 @@ import numpy as np import matplotlib.pyplot as plt from collections import defaultdict +from concurrent.futures import ThreadPoolExecutor, TimeoutError cmd = [ "linpack", @@ -33,7 +34,7 @@ arg = [ [], ["stories110M.bin", "-z", "tokenizer.bin", "-t", "0.0"], - ["./ORBvoc.txt,", "./TUM3.yaml", "./", "./associations/fr1_xyz.txt"], + ["./ORBvoc.txt", "./TUM3.yaml", "./", "./associations/fr1_xyz.txt"], [], [], [], @@ -71,25 +72,7 @@ def run_mvvm(): lines = output.split("\n") for line in lines: if line.__contains__("Execution time:"): - exec_time = line.split(" ")[-2] - print(exec, exec_time) - results.append((exec, exec_time)) # discover 4 aot_variant - return results - - -def run_wamr(): - results = [] - results1 = [] - for _ in range(common_util.trial): - for i in range(len(cmd)): - aot = cmd[i] + "-pure.aot" - results1.append(common_util.run(aot, arg[i], envs[i])) - # print the results - for exec, output in results1: - lines = output.split("\n") - for line in lines: - if line.__contains__("Execution time:"): - exec_time = line.split(" ")[-2] + exec_time = line.split()[-2] print(exec, exec_time) results.append((exec, exec_time)) # discover 4 aot_variant return results @@ -101,25 +84,39 @@ def run_native(): for _ in range(common_util.trial): for i in range(len(cmd)): aot = cmd[i] - results1.append( - common_util.run_native(aot, folder[i], arg[i], envs[i]), - ) + with ThreadPoolExecutor(max_workers=1) as executor: + future = executor.submit(lambda: results.append(common_util.run_native(aot, folder[i], arg[i], envs[i]))) + try: + result = future.result(timeout=100) # 5 seconds timeout + except TimeoutError: + print("Operation timed out") + # results1.append( + # common_util.run_native(aot, folder[i], arg[i], envs[i]), + # ) for exec, output in results1: print(exec, output) lines = output.split("\n") for line in lines: if line.__contains__("elapsed"): - # Split the time string into minutes, seconds, and milliseconds - minutes, seconds = line.split(" ")[2].replace("elapsed", "").split(":") - seconds, milliseconds = seconds.split(".") - - # Convert each part to seconds (note that milliseconds are converted and added as a fraction of a second) - total_seconds = ( - int(minutes) * 60 + int(seconds) + int(milliseconds) / 1000 - ) - - print(total_seconds) - exec_time = total_seconds + try: + minutes, seconds = line.split()[2].replace("elapsed", "").split(":") + seconds, milliseconds = seconds.split(".") + + # Convert each part to seconds (note that milliseconds are converted and added as a fraction of a second) + total_seconds = ( + int(minutes) * 60 + int(seconds) + int(milliseconds) / 1000 + ) + + print(total_seconds) + exec_time = total_seconds + except: + try: + from datetime import datetime + + time_object = datetime.strptime(line.split()[2].replace("elapsed", ""), "%H:%M:%S").time() + print(time_object) + except: + exec_time = float(line.split()[0].replace("user", "")) results.append((exec, exec_time)) return results @@ -130,7 +127,7 @@ def write_to_csv(filename): with open(filename, "a+", newline="") as csvfile: writer = csv.writer(csvfile) # Optionally write headers - writer.writerow(["name", "mvvm", "wamr", "native"]) + writer.writerow(["name", "mvvm", "native"]) # Write the data for idx, row in enumerate(mvvm_results): @@ -138,7 +135,6 @@ def write_to_csv(filename): [ row[0], row[1], - wamr_results[idx][1], native_results[idx][1], ] ) @@ -150,14 +146,14 @@ def read_from_csv(filename): next(reader) results = [] for row in reader: - results.append((row[0], float(row[1]), float(row[2]), float(row[3]))) + results.append((row[0], float(row[1]), float(row[2]))) return results # print the results def plot(result, file_name="windows.pdf"): workloads = defaultdict(list) - for workload, mvvm, wamr, native in result: + for workload, mvvm, native in result: workloads[ workload.replace("OMP_NUM_THREADS=", "") .replace("-g15", "") @@ -172,18 +168,16 @@ def plot(result, file_name="windows.pdf"): .replace("./associations/fr1_xyz.txt", "") .replace("./", "") .strip() - ].append((mvvm, wamr, native)) + ].append((mvvm, native)) # Calculate the medians and standard deviations for each workload statistics = {} for workload, times in workloads.items(): - mvvms, wamr,native = zip(*times) + mvvms, native = zip(*times) statistics[workload] = { "mvvm_median": np.median(mvvms), - "wamr_median": np.median(wamr), "native_median": np.median(native), "mvvm_std": np.std(mvvms), - "wamr_std": np.std(wamr), "native_std": np.std(native), } font = {"size": 14} @@ -193,7 +187,7 @@ def plot(result, file_name="windows.pdf"): # Plotting fig, ax = plt.subplots(figsize=(15, 7)) # Define the bar width and positions - bar_width = 0.7 / 3 + bar_width = 0.7 /2 index = np.arange(len(statistics)) # Plot the bars for each workload @@ -212,15 +206,6 @@ def plot(result, file_name="windows.pdf"): ) ax.bar( index[i] + bar_width, - stats["wamr_median"], - bar_width, - yerr=stats["wamr_std"], - capsize=5, - color="red", - label="WAMR" if i == 0 else "", - ) - ax.bar( - index[i] + 2 * bar_width, stats["native_median"], bar_width, yerr=stats["native_std"], @@ -230,7 +215,7 @@ def plot(result, file_name="windows.pdf"): ) # Labeling and formatting ax.set_ylabel("Time(s)") - ax.set_xticks(index + bar_width / 2) + ax.set_xticks(index + bar_width ) ticklabel = (x.replace("a=b", "") for x in list(statistics.keys())) ax.set_xticklabels(ticklabel, fontsize=10) ax.legend() @@ -243,13 +228,13 @@ def plot(result, file_name="windows.pdf"): if __name__ == "__main__": - mvvm_results = run_mvvm() - wamr_results = run_wamr() - native_results = run_native() + # mvvm_results = run_mvvm() + # wamr_results = run_wamr() + # native_results = run_native() # print the results - print(mvvm_results) - print(wamr_results) - print(native_results) + mvvm_results=run_mvvm() + # wamr_results=run_wamr() + native_results=run_native() write_to_csv("windows.csv") - # results = read_from_csv("windows.csv") - # plot(results) + results = read_from_csv("windows.csv") + plot(results) diff --git a/artifact/result/windows.csv b/artifact/result/windows.csv index 0434222..817eea9 100644 --- a/artifact/result/windows.csv +++ b/artifact/result/windows.csv @@ -1,111 +1,81 @@ -name,mvvm,wamr,native -a=b linpack.aot,65.257584,23.685475,29.01 -OMP_NUM_THREADS=1 llama.aot stories110M.bin -z tokenizer.bin -t 0.0,48.162543,23.685475,13.02 -"a=b rgbd_tum.aot ./ORBvoc.txt, ./TUM3.yaml ./ ./associations/fr1_xyz.txt",872.773619,23.685475,0.008 -OMP_NUM_THREADS=1 bt.aot,872.773619,23.685475,31.071 -OMP_NUM_THREADS=1 cg.aot,22.757516,23.685475,12.033 -OMP_NUM_THREADS=1 ep.aot,0.000539,23.685475,0.004 -OMP_NUM_THREADS=1 ft.aot,31.111255,23.685475,31.005 -OMP_NUM_THREADS=1 lu.aot,0.024766,23.685475,0.004 -OMP_NUM_THREADS=1 mg.aot,20.22196,23.685475,10.052 -OMP_NUM_THREADS=1 sp.aot,20.22196,23.685475,0.06 -a=b redis.aot,20.22196,23.685475,0.004 -a=b linpack.aot,21.222971,23.071749,29.094 -OMP_NUM_THREADS=1 llama.aot stories110M.bin -z tokenizer.bin -t 0.0,21.222971,23.071749,13.023 -"a=b rgbd_tum.aot ./ORBvoc.txt, ./TUM3.yaml ./ ./associations/fr1_xyz.txt",825.783301,23.071749,0.004 -OMP_NUM_THREADS=1 bt.aot,825.783301,23.071749,31.049 -OMP_NUM_THREADS=1 cg.aot,23.273768,23.071749,12.012 -OMP_NUM_THREADS=1 ep.aot,0.000604,23.071749,0.002 -OMP_NUM_THREADS=1 ft.aot,34.869603,23.071749,29.077 -OMP_NUM_THREADS=1 lu.aot,0.027421,23.071749,0.003 -OMP_NUM_THREADS=1 mg.aot,21.568194,23.071749,10.008 -OMP_NUM_THREADS=1 sp.aot,21.568194,23.071749,0.059 -a=b redis.aot,21.568194,23.071749,0.002 -a=b linpack.aot,24.285947,22.907635,29.091 -OMP_NUM_THREADS=1 llama.aot stories110M.bin -z tokenizer.bin -t 0.0,24.285947,22.907635,13.009 -"a=b rgbd_tum.aot ./ORBvoc.txt, ./TUM3.yaml ./ ./associations/fr1_xyz.txt",861.7128,22.907635,0.004 -OMP_NUM_THREADS=1 bt.aot,861.7128,22.907635,31.005 -OMP_NUM_THREADS=1 cg.aot,24.943927,22.907635,11.097 -OMP_NUM_THREADS=1 ep.aot,0.000552,22.907635,0.002 -OMP_NUM_THREADS=1 ft.aot,35.43775,22.907635,30.044 -OMP_NUM_THREADS=1 lu.aot,0.024445,22.907635,0.003 -OMP_NUM_THREADS=1 mg.aot,21.484104,22.907635,10.008 -OMP_NUM_THREADS=1 sp.aot,21.484104,22.907635,0.057 -a=b redis.aot,21.484104,22.907635,0.002 -a=b linpack.aot,21.571797,23.432488,28.08 -OMP_NUM_THREADS=1 llama.aot stories110M.bin -z tokenizer.bin -t 0.0,21.571797,23.432488,13.009 -"a=b rgbd_tum.aot ./ORBvoc.txt, ./TUM3.yaml ./ ./associations/fr1_xyz.txt",852.130692,23.432488,0.004 -OMP_NUM_THREADS=1 bt.aot,852.130692,23.432488,31.013 -OMP_NUM_THREADS=1 cg.aot,24.996387,23.432488,12.023 -OMP_NUM_THREADS=1 ep.aot,0.00054,23.432488,0.002 -OMP_NUM_THREADS=1 ft.aot,34.067451,23.432488,29.015 -OMP_NUM_THREADS=1 lu.aot,0.029147,23.432488,0.003 -OMP_NUM_THREADS=1 mg.aot,21.092533,23.432488,10.02 -OMP_NUM_THREADS=1 sp.aot,21.092533,23.432488,0.058 -a=b redis.aot,21.092533,23.432488,0.002 -a=b linpack.aot,21.317692,22.04948,29.099 -OMP_NUM_THREADS=1 llama.aot stories110M.bin -z tokenizer.bin -t 0.0,21.317692,22.04948,13.014 -"a=b rgbd_tum.aot ./ORBvoc.txt, ./TUM3.yaml ./ ./associations/fr1_xyz.txt",855.494118,22.04948,0.004 -OMP_NUM_THREADS=1 bt.aot,855.494118,22.04948,32.011 -OMP_NUM_THREADS=1 cg.aot,24.755341,22.04948,11.085 -OMP_NUM_THREADS=1 ep.aot,0.000491,22.04948,0.002 -OMP_NUM_THREADS=1 ft.aot,33.525148,22.04948,29.02 -OMP_NUM_THREADS=1 lu.aot,0.023048,22.04948,0.003 -OMP_NUM_THREADS=1 mg.aot,20.931011,22.04948,9.081 -OMP_NUM_THREADS=1 sp.aot,20.931011,22.04948,0.061 -a=b redis.aot,20.931011,22.04948,0.002 -a=b linpack.aot,21.744898,22.17191,30.086 -OMP_NUM_THREADS=1 llama.aot stories110M.bin -z tokenizer.bin -t 0.0,21.744898,22.17191,13.074 -"a=b rgbd_tum.aot ./ORBvoc.txt, ./TUM3.yaml ./ ./associations/fr1_xyz.txt",842.886785,22.17191,0.004 -OMP_NUM_THREADS=1 bt.aot,842.886785,22.17191,30.073 -OMP_NUM_THREADS=1 cg.aot,24.598304,22.17191,12.029 -OMP_NUM_THREADS=1 ep.aot,0.000423,22.17191,0.002 -OMP_NUM_THREADS=1 ft.aot,33.236581,22.17191,29.073 -OMP_NUM_THREADS=1 lu.aot,0.025789,22.17191,0.003 -OMP_NUM_THREADS=1 mg.aot,21.231102,22.17191,10.051 -OMP_NUM_THREADS=1 sp.aot,21.231102,22.17191,0.059 -a=b redis.aot,21.231102,22.17191,0.002 -a=b linpack.aot,21.170858,21.879022,30.022 -OMP_NUM_THREADS=1 llama.aot stories110M.bin -z tokenizer.bin -t 0.0,21.170858,21.879022,13.035 -"a=b rgbd_tum.aot ./ORBvoc.txt, ./TUM3.yaml ./ ./associations/fr1_xyz.txt",841.635191,21.879022,0.004 -OMP_NUM_THREADS=1 bt.aot,841.635191,21.879022,31.097 -OMP_NUM_THREADS=1 cg.aot,24.747761,21.879022,12.036 -OMP_NUM_THREADS=1 ep.aot,0.000422,21.879022,0.002 -OMP_NUM_THREADS=1 ft.aot,33.843813,21.879022,29.097 -OMP_NUM_THREADS=1 lu.aot,0.02354,21.879022,0.003 -OMP_NUM_THREADS=1 mg.aot,21.320099,21.879022,10.008 -OMP_NUM_THREADS=1 sp.aot,21.320099,21.879022,0.057 -a=b redis.aot,21.320099,21.879022,0.002 -a=b linpack.aot,22.022136,21.401152,28.093 -OMP_NUM_THREADS=1 llama.aot stories110M.bin -z tokenizer.bin -t 0.0,22.022136,21.401152,13.033 -"a=b rgbd_tum.aot ./ORBvoc.txt, ./TUM3.yaml ./ ./associations/fr1_xyz.txt",849.786345,21.401152,0.004 -OMP_NUM_THREADS=1 bt.aot,849.786345,21.401152,30.032 -OMP_NUM_THREADS=1 cg.aot,24.168857,21.401152,11.067 -OMP_NUM_THREADS=1 ep.aot,0.000439,21.401152,0.002 -OMP_NUM_THREADS=1 ft.aot,34.130708,21.401152,27.094 -OMP_NUM_THREADS=1 lu.aot,0.026111,21.401152,0.003 -OMP_NUM_THREADS=1 mg.aot,22.90108,21.401152,9.086 -OMP_NUM_THREADS=1 sp.aot,22.90108,21.401152,0.056 -a=b redis.aot,22.90108,21.401152,0.002 -a=b linpack.aot,23.213674,21.673556,28.047 -OMP_NUM_THREADS=1 llama.aot stories110M.bin -z tokenizer.bin -t 0.0,23.213674,21.673556,12.089 -"a=b rgbd_tum.aot ./ORBvoc.txt, ./TUM3.yaml ./ ./associations/fr1_xyz.txt",857.563863,21.673556,0.004 -OMP_NUM_THREADS=1 bt.aot,857.563863,21.673556,29.03 -OMP_NUM_THREADS=1 cg.aot,25.684547,21.673556,11.056 -OMP_NUM_THREADS=1 ep.aot,0.000533,21.673556,0.002 -OMP_NUM_THREADS=1 ft.aot,36.856358,21.673556,27.056 -OMP_NUM_THREADS=1 lu.aot,0.025263,21.673556,0.003 -OMP_NUM_THREADS=1 mg.aot,21.693797,21.673556,10.053 -OMP_NUM_THREADS=1 sp.aot,21.693797,21.673556,0.06 -a=b redis.aot,21.693797,21.673556,0.002 -a=b linpack.aot,23.564979,23.490303,29.065 -OMP_NUM_THREADS=1 llama.aot stories110M.bin -z tokenizer.bin -t 0.0,23.564979,23.490303,13.028 -"a=b rgbd_tum.aot ./ORBvoc.txt, ./TUM3.yaml ./ ./associations/fr1_xyz.txt",865.143924,23.490303,0.004 -OMP_NUM_THREADS=1 bt.aot,865.143924,23.490303,30.027 -OMP_NUM_THREADS=1 cg.aot,25.359335,23.490303,12.018 -OMP_NUM_THREADS=1 ep.aot,0.000653,23.490303,0.002 -OMP_NUM_THREADS=1 ft.aot,35.618984,23.490303,27.087 -OMP_NUM_THREADS=1 lu.aot,0.029986,23.490303,0.003 -OMP_NUM_THREADS=1 mg.aot,22.961563,23.490303,10.016 -OMP_NUM_THREADS=1 sp.aot,22.961563,23.490303,0.06 -a=b redis.aot,22.961563,23.490303,0.002 +name,mvvm,native +a=b linpack.aot,36.875728,25.089 +a=b rgbd_tum.aot ./ORBvoc.txt ./TUM3.yaml ./ ./associations/fr1_xyz.txt,760.961321,12.049 +OMP_NUM_THREADS=1 cg.aot,20.553871,96.003 +OMP_NUM_THREADS=1 ep.aot,0.000519,28.055 +OMP_NUM_THREADS=1 ft.aot,27.5285,10.057 +OMP_NUM_THREADS=1 lu.aot,0.023669,0.002 +OMP_NUM_THREADS=1 mg.aot,18.439463,24.097 +a=b redis.aot,34.938116,0.003 +a=b linpack.aot,36.463317,9.017 +a=b rgbd_tum.aot ./ORBvoc.txt ./TUM3.yaml ./ ./associations/fr1_xyz.txt,742.233683,0.051 +OMP_NUM_THREADS=1 cg.aot,21.159921,0.051 +OMP_NUM_THREADS=1 ep.aot,0.000514,26.001 +OMP_NUM_THREADS=1 ft.aot,27.590321,12.054 +OMP_NUM_THREADS=1 lu.aot,0.024134,97.0 +OMP_NUM_THREADS=1 mg.aot,18.545828,29.005 +a=b redis.aot,34.812165,10.071 +a=b linpack.aot,36.913629,0.002 +a=b rgbd_tum.aot ./ORBvoc.txt ./TUM3.yaml ./ ./associations/fr1_xyz.txt,748.680853,25.043 +OMP_NUM_THREADS=1 cg.aot,20.662478,0.003 +OMP_NUM_THREADS=1 ep.aot,0.000424,9.002 +OMP_NUM_THREADS=1 ft.aot,27.951032,0.051 +OMP_NUM_THREADS=1 lu.aot,0.022966,0.051 +OMP_NUM_THREADS=1 mg.aot,18.514203,25.003 +a=b redis.aot,34.982459,12.043 +a=b linpack.aot,36.834715,88.071 +a=b rgbd_tum.aot ./ORBvoc.txt ./TUM3.yaml ./ ./associations/fr1_xyz.txt,755.615254,27.05 +OMP_NUM_THREADS=1 cg.aot,20.635818,10.048 +OMP_NUM_THREADS=1 ep.aot,0.000407,0.003 +OMP_NUM_THREADS=1 ft.aot,27.45233,23.062 +OMP_NUM_THREADS=1 lu.aot,0.023021,0.003 +OMP_NUM_THREADS=1 mg.aot,18.777736,9.004 +a=b redis.aot,34.910377,0.053 +a=b linpack.aot,36.670241,0.053 +a=b rgbd_tum.aot ./ORBvoc.txt ./TUM3.yaml ./ ./associations/fr1_xyz.txt,754.313282,25.04 +OMP_NUM_THREADS=1 cg.aot,20.773552,12.042 +OMP_NUM_THREADS=1 ep.aot,0.000427,87.076 +OMP_NUM_THREADS=1 ft.aot,27.558167,27.045 +OMP_NUM_THREADS=1 lu.aot,0.023717,10.042 +OMP_NUM_THREADS=1 mg.aot,18.574712,0.002 +a=b redis.aot,34.847002,23.079 +a=b linpack.aot,37.00937,0.003 +a=b rgbd_tum.aot ./ORBvoc.txt ./TUM3.yaml ./ ./associations/fr1_xyz.txt,799.227787,9.003 +OMP_NUM_THREADS=1 cg.aot,24.116978,0.052 +OMP_NUM_THREADS=1 ep.aot,0.000501,0.052 +OMP_NUM_THREADS=1 ft.aot,28.097015,25.016 +OMP_NUM_THREADS=1 lu.aot,0.022781,12.041 +OMP_NUM_THREADS=1 mg.aot,18.495219,89.088 +a=b redis.aot,35.798685,27.058 +a=b linpack.aot,36.814429,10.046 +a=b rgbd_tum.aot ./ORBvoc.txt ./TUM3.yaml ./ ./associations/fr1_xyz.txt,743.609241,0.002 +OMP_NUM_THREADS=1 cg.aot,21.472738,24.009 +OMP_NUM_THREADS=1 ep.aot,0.000507,0.003 +OMP_NUM_THREADS=1 ft.aot,27.901536,9.011 +OMP_NUM_THREADS=1 lu.aot,0.022625,0.052 +OMP_NUM_THREADS=1 mg.aot,18.491945,0.052 +a=b redis.aot,35.126543,26.035 +a=b linpack.aot,37.132155,12.028 +a=b rgbd_tum.aot ./ORBvoc.txt ./TUM3.yaml ./ ./associations/fr1_xyz.txt,762.204546,83.044 +OMP_NUM_THREADS=1 cg.aot,23.295101,27.082 +OMP_NUM_THREADS=1 ep.aot,0.000545,10.056 +OMP_NUM_THREADS=1 ft.aot,37.508713,0.002 +OMP_NUM_THREADS=1 lu.aot,0.024291,27.004 +OMP_NUM_THREADS=1 mg.aot,19.495638,0.003 +a=b redis.aot,36.892017,9.007 +a=b linpack.aot,19.805608,0.052 +a=b rgbd_tum.aot ./ORBvoc.txt ./TUM3.yaml ./ ./associations/fr1_xyz.txt,785.371629,7.09 +OMP_NUM_THREADS=1 cg.aot,20.722234,25.097 +OMP_NUM_THREADS=1 ep.aot,0.000427,12.047 +OMP_NUM_THREADS=1 ft.aot,27.942502,86.088 +OMP_NUM_THREADS=1 lu.aot,0.023177,27.04 +OMP_NUM_THREADS=1 mg.aot,18.482471,10.044 +a=b redis.aot,35.381083,0.002 +a=b linpack.aot,37.148041,24.065 +a=b rgbd_tum.aot ./ORBvoc.txt ./TUM3.yaml ./ ./associations/fr1_xyz.txt,757.206547,0.003 +OMP_NUM_THREADS=1 cg.aot,20.886888,9.018 +OMP_NUM_THREADS=1 ep.aot,0.000421,0.053 +OMP_NUM_THREADS=1 ft.aot,27.930926,0.017 +OMP_NUM_THREADS=1 lu.aot,0.022977,25.085 +OMP_NUM_THREADS=1 mg.aot,18.825622,12.038 +a=b redis.aot,37.090249,86.066 diff --git a/artifact/result/windows.pdf b/artifact/result/windows.pdf index 28e7d038b3641fa871a8f66258daad6aabc81b9d..f2f8e9cc9cbffde64f0b0d90daaf3e5b4462e3ac 100644 GIT binary patch literal 15579 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 Kh1GP`A^!)+TysVM delta 490 zcmcazxs`JR8>2jzzHe$uW};Jmg+jD~0T7y)8R%Ik7@L^tnJL67Ojcq{$+%qZse9VT zkGH5isDSU;CHD`Lx_9!3ZfdZIJ?Nmw-Emr!NAymk#oW^jCr&>#GBm!hnPF4W0-a>x zU|VB_^9<)sJ$U5x_z@GswldK>T&Z~}#U(|liMb$Feo_{fp%Kth5X0PjG9#CayfKt( zW20ba2UBDM7o4nQ-ZpuT0q5k6=F-d-dWMtFo7+18X-zJDXP~hqnfZAxi6yBD8ZK5w z21X_ZMn>j_7Di@IMetnnH z2Bt=)m|`Yom||w;m|_+d7-D7ymXq&WsEY!9gl?08>11h36$t|q3ryq9EDa`i+ejN5 wnkeW8<>!|u7y?5iNI~B-FD+le5EN!XAdeN7Bo>u`y=7ry&ZVmA>hHz{03DfyXaE2J