diff options
Diffstat (limited to 'sweep_gr_sims.py')
-rw-r--r-- | sweep_gr_sims.py | 118 |
1 files changed, 69 insertions, 49 deletions
diff --git a/sweep_gr_sims.py b/sweep_gr_sims.py index f11ee64..661af56 100644 --- a/sweep_gr_sims.py +++ b/sweep_gr_sims.py @@ -2,10 +2,12 @@ import subprocess import time import struct +import random import math import statistics import tempfile import itertools +from collections import defaultdict from os import path import tqdm @@ -22,52 +24,70 @@ SIMULATION_DURATION = 30.0 # seconds realtime MAX_CONCURRENT_PROCESSES = 8 -with tempfile.TemporaryDirectory() as tmpdir: - - jobs = list(enumerate(itertools.product(SIMS, AMPLITUDES_MILLIHERTZ))) - print(f'Will launch {len(jobs)} simulation jobs in {math.ceil(len(jobs)/MAX_CONCURRENT_PROCESSES):.0f} batches of {MAX_CONCURRENT_PROCESSES}') - - def start_processes(jobs): - for i, (sim, ampl_mhz) in jobs: - berfile = path.join(tmpdir, f'berfile_{i}') - proc = subprocess.Popen(['/usr/bin/python2', sim, - '--signal-strength', str(ampl_mhz), - '--ber-file', berfile], - stdin=subprocess.PIPE, stdout=subprocess.DEVNULL) - yield proc, sim, ampl_mhz, berfile - - results = { sim: ([], [], []) for sim in SIMS } - for n, i in enumerate(range(0, len(jobs), MAX_CONCURRENT_PROCESSES)): - batch = jobs[i:][:MAX_CONCURRENT_PROCESSES] - print(f'Starting batch {n}... ', end='') - processes = list(start_processes(batch)) - print('done.') - - print('Waiting for simulation:') - for _ in tqdm.trange(1000): - time.sleep(SIMULATION_DURATION/1000) - - print('Terminating processes...', end='') - for proc, *_ in processes: - proc.communicate(b'\n', timeout=10) - - for proc, *_ in processes: - proc.wait(5) - print('done.') - - print('Processing simulation results') - for _proc, sim, ampl_mhz, berfile in processes: - - with open(berfile, 'rb') as f: - data = f.read() - - floats = struct.unpack(f'{len(data)//4}f', data) - ber = statistics.mean(floats[-256:]) - stdev = statistics.stdev(floats[-256:]) - - amplitudes, bers, stdevs = results[sim] - amplitudes.append(ampl_mhz) - bers.append(ber) - stdevs.append(stdev) - -print(results) +def run_simulation( + duration = SIMULATION_DURATION, + simulations = SIMS, + forklimit = MAX_CONCURRENT_PROCESSES, + amplitudes:'list(millihertz)' = AMPLITUDES_MILLIHERTZ, + terminate_timeout:'s' = 5.0, + communicate_timeout:'s' = 10.0, + repeat_runs = 1, + shuffle = False, + tqdm = tqdm.tqdm + ): + with tempfile.TemporaryDirectory() as tmpdir: + + jobs = list(enumerate(itertools.product(simulations, amplitudes * repeat_runs))) + if shuffle: + random.shuffle(jobs) + nchunks = int(math.ceil(len(jobs)/forklimit)) + + def start_processes(jobs): + for i, (sim, ampl_mhz) in jobs: + berfile = path.join(tmpdir, f'berfile_{i}') + proc = subprocess.Popen(['/usr/bin/python2', sim, + '--signal-strength', str(ampl_mhz), + '--ber-file', berfile], + stdin=subprocess.PIPE, stdout=subprocess.DEVNULL) + yield proc, sim, ampl_mhz, berfile + + results = { sim: defaultdict(lambda: ([], [])) for sim in simulations } + with tqdm(total = nchunks * duration, bar_format='{l_bar}{bar}| {elapsed}<{remaining}') as tq: + tq.write(f'Will launch {len(jobs)} simulation jobs in {nchunks} batches of {forklimit}') + for n, i in enumerate(range(0, len(jobs), forklimit)): + batch = jobs[i:][:forklimit] + tq.write(f'Starting batch {n+1}/{nchunks}...') + processes = list(start_processes(batch)) + tq.write('done.') + + tq.write('Waiting for simulation:') + for _ in range(100): + time.sleep(duration/100) + tq.update(duration/100) + + tq.write('Terminating processes...') + for proc, *_ in processes: + proc.communicate(b'\n', timeout=communicate_timeout) + + for proc, *_ in processes: + proc.wait(terminate_timeout) + tq.write('done.') + + tq.write('Processing simulation results') + for _proc, sim, ampl_mhz, berfile in processes: + + with open(berfile, 'rb') as f: + data = f.read() + + floats = struct.unpack(f'{len(data)//4}f', data) + ber = statistics.mean(floats[-256:]) + stdev = statistics.stdev(floats[-256:]) + + bers, stdevs = results[sim][ampl_mhz] + bers.append(ber) + stdevs.append(stdev) + + return results + +if __name__ == '__main__': + print(run_simulation()) |