Skip to content

Commit f749eb7

Browse files
committed
at: more flexible use of sweep
- improved folder naming scheeme to be sequential in time - allow for bins and results to live in different folders - add Dockerfile for easy testing Signed-off-by: Vitor Bandeira <[email protected]>
1 parent cbdc8b4 commit f749eb7

File tree

4 files changed

+59
-49
lines changed

4 files changed

+59
-49
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"PLACE_DENSITY_LB_ADDON": {
3+
"type": "float",
4+
"minmax": [
5+
0.0,
6+
0.2
7+
],
8+
"step": 0.05
9+
}
10+
}

tools/AutoTuner/Dockerfile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# syntax=docker/dockerfile:1
2+
FROM openroad/orfs:latest
3+
WORKDIR /OpenROAD-flow-scripts/tools/AutoTuner
4+
RUN pip install --no-cache-dir --upgrade pip && \
5+
pip install --no-cache-dir -r requirements.txt && \
6+
pip install --no-cache-dir --no-deps .

tools/AutoTuner/src/autotuner/distributed.py

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
from uuid import uuid4 as uuid
6969
from collections import namedtuple
7070
from multiprocessing import cpu_count
71+
import time
7172

7273
import numpy as np
7374
import torch
@@ -91,7 +92,6 @@
9192
parse_config,
9293
read_config,
9394
read_metrics,
94-
prepare_ray_server,
9595
CONSTRAINTS_SDC,
9696
FASTROUTE_TCL,
9797
)
@@ -101,9 +101,18 @@
101101
# The worst of optimized metric
102102
ERROR_METRIC = 9e99
103103
# Path to the FLOW_HOME directory
104-
ORFS_FLOW_DIR = os.path.abspath(
105-
os.path.join(os.path.dirname(__file__), "../../../../flow")
106-
)
104+
if "ORFS_FLOW_DIR" in os.environ:
105+
ORFS_FLOW_DIR = os.environ["ORFS_FLOW_DIR"]
106+
else:
107+
ORFS_FLOW_DIR = os.path.abspath(
108+
os.path.join(os.path.dirname(__file__), "../../../../flow")
109+
)
110+
if "INSTALL_PATH" in os.environ:
111+
INSTALL_PATH = os.environ["INSTALL_PATH"]
112+
else:
113+
INSTALL_PATH = os.path.abspath(os.path.join(ORFS_FLOW_DIR, "../tools/install"))
114+
LOCAL_DIR = ""
115+
107116
# Global variable for args
108117
args = None
109118

@@ -448,7 +457,7 @@ def parse_arguments():
448457

449458
# If the experiment name is the default, add a UUID to the end.
450459
if args.experiment == "test":
451-
id = str(uuid())[:8]
460+
id = time.strftime("%Y%m%d-%H%M%S") + "-" + str(uuid())[:4]
452461
args.experiment = f"{args.mode}-{id}"
453462
else:
454463
args.experiment += f"-{args.mode}"
@@ -558,31 +567,38 @@ def save_best(results):
558567

559568
def sweep():
560569
"""Run sweep of parameters"""
561-
if args.server is not None:
562-
# For remote sweep we create the following directory structure:
563-
# 1/ 2/ 3/ 4/
564-
# <repo>/<logs>/<platform>/<design>/
565-
repo_dir = os.path.abspath(LOCAL_DIR + "/../" * 4)
566-
else:
567-
repo_dir = os.path.abspath(os.path.join(ORFS_FLOW_DIR, ".."))
570+
repo_dir = os.path.abspath(os.path.join(ORFS_FLOW_DIR, ".."))
568571
print(f"[INFO TUN-0012] Log folder {LOCAL_DIR}.")
569-
queue = Queue()
570572
parameter_list = list()
573+
total_combinations = 1
571574
for name, content in config_dict.items():
575+
print(f"[INFO TUN-0013] Sweeping {name} over {content}.")
572576
if not isinstance(content, list):
573577
print(f"[ERROR TUN-0015] {name} sweep is not supported.")
574578
sys.exit(1)
575579
if content[-1] == 0:
576580
print("[ERROR TUN-0014] Sweep does not support step value zero.")
577581
sys.exit(1)
578-
parameter_list.append([{name: i} for i in np.arange(*content)])
582+
parameter_list.append([{name: i} for i in np.round(np.arange(*content), 4).tolist()])
583+
total_combinations *= len(parameter_list[-1])
584+
print(f"[INFO TUN-0017] Total of {total_combinations} combinations.")
585+
if total_combinations > 1000:
586+
print(
587+
"[WARN TUN-0033] The total number of combinations is very large."
588+
" Do you wish to continue? (y/n)"
589+
)
590+
if input().lower() != "y":
591+
sys.exit(1)
579592
parameter_list = list(product(*parameter_list))
593+
queue = Queue()
580594
for parameter in parameter_list:
581-
temp = dict()
595+
params_to_sweep = dict()
582596
for value in parameter:
583-
temp.update(value)
584-
queue.put([args, repo_dir, temp, SDC_ORIGINAL, FR_ORIGINAL, INSTALL_PATH])
585-
workers = [consumer.remote(queue) for _ in range(args.jobs)]
597+
params_to_sweep.update(value)
598+
queue.put([args, repo_dir, params_to_sweep, SDC_ORIGINAL, FR_ORIGINAL, INSTALL_PATH])
599+
max_jobs = min(args.jobs, queue.qsize())
600+
print(f"[INFO TUN-0008] Starting sweep with {max_jobs} workers.")
601+
workers = [consumer.remote(queue) for _ in range(max_jobs)]
586602
print("[INFO TUN-0009] Waiting for results.")
587603
ray.get(workers)
588604
print("[INFO TUN-0010] Sweep complete.")
@@ -592,14 +608,13 @@ def main():
592608
global args, SDC_ORIGINAL, FR_ORIGINAL, LOCAL_DIR, INSTALL_PATH, ORFS_FLOW_DIR, config_dict, reference, best_params
593609
args = parse_arguments()
594610

611+
LOCAL_DIR = os.path.join(ORFS_FLOW_DIR, f"logs/{args.platform}/{args.design}")
595612
# Read config and original files before handling where to run in case we
596613
# need to upload the files.
597614
config_dict, SDC_ORIGINAL, FR_ORIGINAL = read_config(
598615
os.path.abspath(args.config), args.mode, getattr(args, "algorithm", None)
599616
)
600617

601-
LOCAL_DIR, ORFS_FLOW_DIR, INSTALL_PATH = prepare_ray_server(args)
602-
603618
if args.mode == "tune":
604619
best_params = set_best_params(args.platform, args.design)
605620
search_algo = set_algorithm(

tools/AutoTuner/src/autotuner/utils.py

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,8 @@
4040
import yaml
4141
import subprocess
4242
import sys
43-
import uuid
43+
from uuid import uuid4 as uuid
4444
import time
45-
from multiprocessing import cpu_count
4645
from datetime import datetime
4746

4847
import numpy as np
@@ -319,9 +318,8 @@ def openroad(
319318
if install_path is None:
320319
install_path = os.path.join(base_dir, "tools/install")
321320

322-
export_command = f"export PATH={install_path}/OpenROAD/bin"
323-
export_command += f":{install_path}/yosys/bin:$PATH"
324-
export_command += " && "
321+
export_command = f"export OPENROAD_EXE={install_path}/OpenROAD/bin/openroad &&"
322+
export_command += f" export YOSYS_EXE={install_path}/yosys/bin/yosys &&"
325323

326324
make_command = export_command
327325
if args.memory_limit is not None:
@@ -610,28 +608,6 @@ def read_tune_pbt(name, this):
610608
return config, sdc_file, fr_file
611609

612610

613-
def prepare_ray_server(args):
614-
"""
615-
Prepares Ray server and returns basic directories.
616-
"""
617-
# Connect to remote Ray server if any, otherwise will run locally
618-
if args.server is not None:
619-
# Connect to ray server before first remote execution.
620-
ray.init(f"ray://{args.server}:{args.port}")
621-
print("[INFO TUN-0001] Connected to Ray server.")
622-
# Common variables used for local and remote runs.
623-
orfs_dir = getattr(args, "orfs", None)
624-
orfs_flow_dir = os.path.abspath(
625-
os.path.join(orfs_dir, "flow")
626-
if orfs_dir
627-
else os.path.join(os.path.dirname(__file__), "../../../../flow")
628-
)
629-
local_dir = f"logs/{args.platform}/{args.design}"
630-
local_dir = os.path.join(orfs_flow_dir, local_dir)
631-
install_path = os.path.abspath(os.path.join(orfs_flow_dir, "../tools/install"))
632-
return local_dir, orfs_flow_dir, install_path
633-
634-
635611
@ray.remote
636612
def openroad_distributed(
637613
args,
@@ -643,6 +619,8 @@ def openroad_distributed(
643619
variant=None,
644620
):
645621
"""Simple wrapper to run openroad distributed with Ray."""
622+
if variant is None and len(config) != 1:
623+
variant = "multiple-params"
646624
config = parse_config(
647625
config=config,
648626
base_dir=repo_dir,
@@ -655,11 +633,12 @@ def openroad_distributed(
655633
if variant is None:
656634
variant = config.replace(" ", "_").replace("=", "_")
657635
t = time.time()
636+
id = time.strftime("%Y%m%d-%H%M%S") + "-" + str(uuid())[:4]
658637
metric_file = openroad(
659638
args=args,
660639
base_dir=repo_dir,
661640
parameters=config,
662-
flow_variant=f"{uuid.uuid4()}-{variant}" if variant else f"{uuid.uuid4()}",
641+
flow_variant=f"{id}-{variant}" if variant else id,
663642
install_path=install_path,
664643
)
665644
duration = time.time() - t
@@ -671,7 +650,7 @@ def consumer(queue):
671650
"""consumer"""
672651
while not queue.empty():
673652
next_item = queue.get()
674-
name = next_item[1]
653+
name = next_item[2]
675654
print(f"[INFO TUN-0007] Scheduling run for parameter {name}.")
676655
ray.get(openroad_distributed.remote(*next_item))
677656
print(f"[INFO TUN-0008] Finished run for parameter {name}.")

0 commit comments

Comments
 (0)