forked from ANRGUSC/saga
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexp_benchmarking.py
More file actions
151 lines (133 loc) · 5.84 KB
/
Copy pathexp_benchmarking.py
File metadata and controls
151 lines (133 loc) · 5.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import logging
import pathlib
from typing import List, Optional
from saga.data import Dataset
from saga.schedulers import (
BILScheduler, CpopScheduler, DuplexScheduler, ETFScheduler, FCPScheduler,
FLBScheduler, FastestNodeScheduler, GDLScheduler, HeftScheduler,
MCTScheduler, METScheduler, MaxMinScheduler, MinMinScheduler,
OLBScheduler, WBAScheduler
)
from saga.scheduler import Scheduler
from prepare import load_dataset, prepare_datasets
from scripts.experiments.benchmarking.post_benchmarking import run_analysis
thisdir = pathlib.Path(__file__).parent.resolve()
exclude_schedulers = []
saga_schedulers = {
# Schedulers included in benchmarking results for the paper
# "Comparing Task Graph Scheduling Algorithms: An Adversarial Approach"
# https://arxiv.org/abs/2403.07120
"BIL": BILScheduler,
"CPoP": CpopScheduler,
"Duplex": DuplexScheduler,
"ETF": ETFScheduler,
"FCP": FCPScheduler,
"FLB": FLBScheduler,
"FastestNode": FastestNodeScheduler,
"GDL": GDLScheduler,
"HEFT": HeftScheduler,
"MCT": MCTScheduler,
"MET": METScheduler,
"MaxMin": MaxMinScheduler,
"MinMin": MinMinScheduler,
"OLB": OLBScheduler,
"WBA": WBAScheduler
}
def get_schedulers() -> List[Scheduler]:
"""Get a list of all schedulers.
Returns:
List[Scheduler]: list of schedulers
"""
schedulers = []
for item in saga_schedulers.values():
if (isinstance(item, type) and issubclass(item, Scheduler) and item is not Scheduler):
if item not in exclude_schedulers:
try:
schedulers.append(item())
except TypeError:
logging.warning("Could not instantiate %s with default arguments.", item.__name__)
return schedulers
class TrimmedDataset(Dataset):
def __init__(self, dataset: Dataset, max_instances: int):
super().__init__(dataset.name)
self.dataset = dataset
self.max_instances = max_instances
def __len__(self):
return min(len(self.dataset), self.max_instances)
def __getitem__(self, index):
if index >= len(self):
raise IndexError
return self.dataset[index]
def evaluate_dataset(datadir: pathlib.Path,
resultsdir: pathlib.Path,
dataset_name: str,
max_instances: int = 0,
num_jobs: int = 1,
schedulers: Optional[List[Scheduler]] = None,
overwrite: bool = False):
"""Evaluate a dataset.
Args:
datadir (pathlib.Path): The directory containing the dataset.
resultsdir (pathlib.Path): The directory to save the results.
dataset_name (str): The name of the dataset.
max_instances (int, optional): Maximum number of instances to evaluate. Defaults to 0 (no trimming).
num_jobs (int, optional): The number of jobs to run in parallel. Defaults to 1.
schedulers (Optional[List[Scheduler]], optional): The schedulers to evaluate. Defaults to None (all schedulers).
overwrite (bool, optional): Whether to overwrite existing results. Defaults to False.
"""
logging.info("Evaluating dataset %s.", dataset_name)
savepath = resultsdir.joinpath(f"{dataset_name}.csv")
if savepath.exists() and not overwrite:
logging.info("Results already exist. Skipping.")
return
dataset = load_dataset(datadir, dataset_name)
if max_instances > 0 and len(dataset) > max_instances:
dataset = TrimmedDataset(dataset, max_instances)
logging.info("Loaded dataset %s.", dataset_name)
logging.info("Running comparison for %d schedulers.", len(schedulers))
comparison = dataset.compare(schedulers, num_jobs=num_jobs)
logging.info("Saving results.")
df_comp = comparison.to_df()
savepath.parent.mkdir(exist_ok=True, parents=True)
df_comp.to_csv(savepath)
logging.info("Saved results to %s.", savepath)
def run_experiment(datadir: pathlib.Path,
resultsdir: pathlib.Path,
dataset: str = None,
num_jobs: int = 1,
trim: int = 0,
schedulers: List[Scheduler] = None,
overwrite: bool = False):
"""Run the benchmarking.
Args:
datadir (pathlib.Path): The directory to save the results.
dataset (str, optional): The name of the dataset. Defaults to None (all datasets will be evaluated).
num_jobs (int, optional): The number of jobs to run in parallel. Defaults to 1.
trim (int, optional): Maximum number of instances to evaluate per dataset. Defaults to 0 (no trimming).
schedulers (List[Scheduler], optional): The schedulers to evaluate. Defaults to None (all schedulers).
overwrite (bool, optional): Whether to overwrite existing results. Defaults to False.
"""
resultsdir.mkdir(parents=True, exist_ok=True)
schedulers = schedulers if schedulers else get_schedulers()
default_datasets = [path.stem for path in datadir.glob("*.json")]
dataset_names = [dataset] if dataset else default_datasets
for dataset_name in dataset_names:
evaluate_dataset(
datadir=datadir,
resultsdir=resultsdir,
dataset_name=dataset_name,
max_instances=trim,
num_jobs=num_jobs,
schedulers=schedulers,
overwrite=overwrite
)
def main():
logging.basicConfig(level=logging.INFO)
datadir = thisdir.joinpath("data", "benchmarking")
resultsdir = thisdir.joinpath("results", "benchmarking")
outputdir = thisdir.joinpath("output", "benchmarking")
prepare_datasets(savedir=datadir, skip_existing=True)
run_experiment(datadir=datadir, resultsdir=resultsdir, num_jobs=1, overwrite=False)
run_analysis(resultsdir=resultsdir, outputdir=outputdir)
if __name__ == "__main__":
main()