Skip to content

Commit 6bf3862

Browse files
motusbpkroth
andauthored
Better naming and values for MockEnv parameters + unit tests (#769)
* Use `mock_env_range`, `mock_env_seed`, and `mock_env_metrics` instead of just `range`, `seed`, and `metrics` to avoid naming conflicts. * Use integer `mocl_env_seed` values to distinguish between deterministic behavior, random seed, and user-specified seed for `MockEnv`. * Update unit tests and configs to validate the seed behavior. * Add new unit tests for different initializations of the tunable values --------- Co-authored-by: Brian Kroth <[email protected]>
1 parent d1a4658 commit 6bf3862

18 files changed

+84
-51
lines changed

mlos_bench/mlos_bench/DEVNOTES.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Each `Environment` config is a JSON5 file with the following structure:
3434
}
3535
// Environment constructor parameters
3636
// (specific to the Environment class being instantiated):
37-
"seed": 42,
37+
"mock_env_seed": 42,
3838
// ...
3939
}
4040
}

mlos_bench/mlos_bench/config/environments/mock/mock_env.jsonc

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
"linux-hugepages-2048kB",
2020
"redis"
2121
],
22-
"seed": 42, // Seed for the random noise generator. Omit to produce noise-free data.
23-
"range": [60, 120], // Range of the generated output values of the benchmark.
24-
"metrics": ["score"] // Names of fake benchmark metrics to generate. (Default is one metric, "score").
22+
"mock_env_seed": 42, // Seed for the random noise generator. Omit or set to 0 to produce noise-free data.
23+
"mock_env_range": [60, 120], // Range of the generated output values of the benchmark.
24+
"mock_env_metrics": ["score"] // Names of fake benchmark metrics to generate. (Default is one metric, "score").
2525
}
2626
}

mlos_bench/mlos_bench/config/schemas/environments/mock-env-subschema.json

+5-5
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@
1919
},
2020
{
2121
"properties": {
22-
"seed": {
22+
"mock_env_seed": {
2323
"type": "integer",
24-
"description": "Seed for the random number generator",
25-
"default": 0
24+
"description": "Seed for the random number generator. Set to -1 for deterministic behavior, 0 for default randomness.",
25+
"default": -1
2626
},
27-
"range": {
27+
"mock_env_range": {
2828
"type": "array",
2929
"description": "Range of the random number generator",
3030
"items": {
@@ -33,7 +33,7 @@
3333
"minItems": 2,
3434
"maxItems": 2
3535
},
36-
"metrics": {
36+
"mock_env_metrics": {
3737
"type": "array",
3838
"description": "Names of fake benchmark metrics to be generate",
3939
"items": {

mlos_bench/mlos_bench/environments/mock_env.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
from mlos_bench.environments.status import Status
1818
from mlos_bench.environments.base_environment import Environment
1919
from mlos_bench.tunables import Tunable, TunableGroups, TunableValue
20-
from mlos_bench.util import nullable
2120

2221
_LOG = logging.getLogger(__name__)
2322

@@ -49,18 +48,19 @@ def __init__(self,
4948
global_config : dict
5049
Free-format dictionary of global parameters (e.g., security credentials)
5150
to be mixed in into the "const_args" section of the local config.
52-
Optional arguments are `seed`, `range`, and `metrics`.
51+
Optional arguments are `mock_env_seed`, `mock_env_range`, and `mock_env_metrics`.
52+
Set `mock_env_seed` to -1 for deterministic behavior, 0 for default randomness.
5353
tunables : TunableGroups
5454
A collection of tunable parameters for *all* environments.
5555
service: Service
5656
An optional service object. Not used by this class.
5757
"""
5858
super().__init__(name=name, config=config, global_config=global_config,
5959
tunables=tunables, service=service)
60-
seed = self.config.get("seed")
61-
self._random = nullable(random.Random, seed)
62-
self._range = self.config.get("range")
63-
self._metrics = self.config.get("metrics", ["score"])
60+
seed = int(self.config.get("mock_env_seed", -1))
61+
self._random = random.Random(seed or None) if seed >= 0 else None
62+
self._range = self.config.get("mock_env_range")
63+
self._metrics = self.config.get("mock_env_metrics", ["score"])
6464
self._is_ready = True
6565

6666
def run(self) -> Tuple[Status, datetime, Optional[Dict[str, TunableValue]]]:

mlos_bench/mlos_bench/optimizers/mock_optimizer.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def suggest(self) -> TunableGroups:
6161
"""
6262
tunables = super().suggest()
6363
if self._start_with_defaults:
64-
_LOG.info("Use default values for the first trial")
64+
_LOG.info("Use default tunable values")
6565
self._start_with_defaults = False
6666
else:
6767
for (tunable, _group) in tunables:

mlos_bench/mlos_bench/tests/config/cli/mock-bench.jsonc

+4-3
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414

1515
"environment": "environments/mock/mock_env.jsonc",
1616

17-
"tunable_values": [
18-
"tunable-values/tunable-values-example.jsonc"
19-
],
17+
// Use default values for tunables unless otherwise specified
18+
// "tunable_values": [
19+
// "tunable-values/tunable-values-example.jsonc"
20+
// ],
2021

2122
"globals": ["globals/global_test_config.jsonc"],
2223

mlos_bench/mlos_bench/tests/config/schemas/environments/test-cases/bad/invalid/mock_env-bad-metric-type.jsonc

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "mock_env-full",
33
"class": "mlos_bench.environments.mock_env.MockEnv",
44
"config": {
5-
"metrics": [
5+
"mock_env_metrics": [
66
{"bad": "metric type"}
77
]
88
}

mlos_bench/mlos_bench/tests/config/schemas/environments/test-cases/bad/invalid/mock_env-const-args-list-obj.jsonc

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "partial mock env",
33
"class": "mlos_bench.environments.MockEnv",
44
"config": {
5-
"seed": 42,
5+
"mock_env_seed": 42,
66
"const_args": {
77
"foo": "bar",
88
"int": 1,

mlos_bench/mlos_bench/tests/config/schemas/environments/test-cases/bad/invalid/mock_env-const-args-nested-list.jsonc

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "partial mock env",
33
"class": "mlos_bench.environments.MockEnv",
44
"config": {
5-
"seed": 42,
5+
"mock_env_seed": 42,
66
"const_args": {
77
"foo": "bar",
88
"int": 1,

mlos_bench/mlos_bench/tests/config/schemas/environments/test-cases/bad/invalid/mock_env-missing-metric.jsonc

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "mock_env-full",
33
"class": "mlos_bench.environments.mock_env.MockEnv",
44
"config": {
5-
"metrics": [
5+
"mock_env_metrics": [
66
// needs at least one element
77
]
88
}

mlos_bench/mlos_bench/tests/config/schemas/environments/test-cases/bad/invalid/mock_env-missing-name.jsonc

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
// "name": "missing name is invalid",
33
"class": "mlos_bench.environments.MockEnv",
44
"config": {
5-
"seed": 42
5+
"mock_env_seed": 42
66
}
77
}

mlos_bench/mlos_bench/tests/config/schemas/environments/test-cases/good/full/mock_env-full.jsonc

+3-3
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,9 @@
2020
"required_args": [
2121
"foo"
2222
],
23-
"range": [0, 1],
24-
"seed": 42,
25-
"metrics": [
23+
"mock_env_range": [0, 1],
24+
"mock_env_seed": 42,
25+
"mock_env_metrics": [
2626
"latency",
2727
"cost"
2828
]

mlos_bench/mlos_bench/tests/config/schemas/environments/test-cases/good/partial/mock_env-const-args.jsonc

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "partial mock env",
33
"class": "mlos_bench.environments.MockEnv",
44
"config": {
5-
"seed": 42,
5+
"mock_env_seed": 42,
66
"const_args": {
77
"foo": "bar",
88
"int": 1,

mlos_bench/mlos_bench/tests/config/tunable-values/tunable-values-example.jsonc

+4-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
{
33
"$schema": "https://raw.githubusercontent.com/microsoft/MLOS/main/mlos_bench/mlos_bench/config/schemas/tunables/tunable-values-schema.json",
44

5-
"sched_migration_cost_ns": 500000,
6-
"sched_latency_ns": 12000000,
5+
// Values that are different from the defaults
6+
// in order to test --tunable-values handling in OneShotOptimizer.
7+
"sched_migration_cost_ns": 400000,
8+
"sched_latency_ns": 10000000,
79
"sched_child_runs_first": "0",
810
"sched_tunable_scaling": "1"
911
}

mlos_bench/mlos_bench/tests/conftest.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ def mock_env(tunable_groups: TunableGroups) -> MockEnv:
4040
name="Test Env",
4141
config={
4242
"tunable_params": ["provision", "boot", "kernel"],
43-
"seed": SEED,
44-
"range": [60, 120],
45-
"metrics": ["score"],
43+
"mock_env_seed": SEED,
44+
"mock_env_range": [60, 120],
45+
"mock_env_metrics": ["score"],
4646
},
4747
tunables=tunable_groups
4848
)
@@ -57,8 +57,9 @@ def mock_env_no_noise(tunable_groups: TunableGroups) -> MockEnv:
5757
name="Test Env No Noise",
5858
config={
5959
"tunable_params": ["provision", "boot", "kernel"],
60-
"range": [60, 120],
61-
"metrics": ["score", "other_score"],
60+
"mock_env_seed": -1,
61+
"mock_env_range": [60, 120],
62+
"mock_env_metrics": ["score", "other_score"],
6263
},
6364
tunables=tunable_groups
6465
)

mlos_bench/mlos_bench/tests/environments/composite_env_test.py

+10-10
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ def composite_env(tunable_groups: TunableGroups) -> CompositeEnv:
4141
"EnvId": 1,
4242
},
4343
"required_args": ["vmName", "someConst", "global_param"],
44-
"range": [60, 120],
45-
"metrics": ["score"],
44+
"mock_env_range": [60, 120],
45+
"mock_env_metrics": ["score"],
4646
}
4747
},
4848
{
@@ -56,8 +56,8 @@ def composite_env(tunable_groups: TunableGroups) -> CompositeEnv:
5656
"global_param": "local"
5757
},
5858
"required_args": ["vmName"],
59-
"range": [60, 120],
60-
"metrics": ["score"],
59+
"mock_env_range": [60, 120],
60+
"mock_env_metrics": ["score"],
6161
}
6262
},
6363
{
@@ -70,8 +70,8 @@ def composite_env(tunable_groups: TunableGroups) -> CompositeEnv:
7070
"EnvId": 3,
7171
},
7272
"required_args": ["vmName", "vm_server_name", "vm_client_name"],
73-
"range": [60, 120],
74-
"metrics": ["score"],
73+
"mock_env_range": [60, 120],
74+
"mock_env_metrics": ["score"],
7575
}
7676
}
7777
]
@@ -193,8 +193,8 @@ def nested_composite_env(tunable_groups: TunableGroups) -> CompositeEnv:
193193
"vm_server_name",
194194
"global_param"
195195
],
196-
"range": [60, 120],
197-
"metrics": ["score"],
196+
"mock_env_range": [60, 120],
197+
"mock_env_metrics": ["score"],
198198
}
199199
},
200200
# ...
@@ -218,8 +218,8 @@ def nested_composite_env(tunable_groups: TunableGroups) -> CompositeEnv:
218218
"config": {
219219
"tunable_params": ["boot"],
220220
"required_args": ["vmName", "EnvId", "vm_client_name"],
221-
"range": [60, 120],
222-
"metrics": ["score"],
221+
"mock_env_range": [60, 120],
222+
"mock_env_metrics": ["score"],
223223
}
224224
},
225225
# ...

mlos_bench/mlos_bench/tests/launcher_in_process_test.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,14 @@
1717
("argv", "expected_score"), [
1818
([
1919
"--config", "mlos_bench/mlos_bench/tests/config/cli/mock-bench.jsonc",
20-
], 65.6742),
20+
"--trial_config_repeat_count", "5",
21+
"--mock_env_seed", "-1", # Deterministic Mock Environment.
22+
], 67.40329),
2123
([
2224
"--config", "mlos_bench/mlos_bench/tests/config/cli/mock-opt.jsonc",
2325
"--trial_config_repeat_count", "3",
2426
"--max_suggestions", "3",
27+
"--mock_env_seed", "42", # Noisy Mock Environment.
2528
], 64.53897),
2629
]
2730
)

mlos_bench/mlos_bench/tests/launcher_run_test.py

+31-5
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,9 @@ def _launch_main_app(root_path: str, local_exec_service: LocalExecService,
5252
# temp_dir = '/tmp'
5353
log_path = path_join(temp_dir, "mock-test.log")
5454
(return_code, _stdout, _stderr) = local_exec_service.local_exec(
55-
[f"./mlos_bench/mlos_bench/run.py {cli_config} --log_file '{log_path}'"],
55+
["./mlos_bench/mlos_bench/run.py" +
56+
" --config_path ./mlos_bench/mlos_bench/tests/config/" +
57+
f" {cli_config} --log_file '{log_path}'"],
5658
cwd=root_path)
5759
assert return_code == 0
5860

@@ -74,14 +76,35 @@ def _launch_main_app(root_path: str, local_exec_service: LocalExecService,
7476
def test_launch_main_app_bench(root_path: str, local_exec_service: LocalExecService) -> None:
7577
"""
7678
Run mlos_bench command-line application with mock benchmark config
77-
and check the results in the log.
79+
and default tunable values and check the results in the log.
80+
"""
81+
_launch_main_app(
82+
root_path, local_exec_service,
83+
" --config cli/mock-bench.jsonc" +
84+
" --trial_config_repeat_count 5" +
85+
" --mock_env_seed -1", # Deterministic Mock Environment.
86+
[
87+
f"^{_RE_DATE} run\\.py:\\d+ " +
88+
r"_main INFO Final score: \{'score': 67\.40\d+\}\s*$",
89+
]
90+
)
91+
92+
93+
def test_launch_main_app_bench_values(
94+
root_path: str, local_exec_service: LocalExecService) -> None:
95+
"""
96+
Run mlos_bench command-line application with mock benchmark config
97+
and user-specified tunable values and check the results in the log.
7898
"""
7999
_launch_main_app(
80100
root_path, local_exec_service,
81-
"--config mlos_bench/mlos_bench/tests/config/cli/mock-bench.jsonc",
101+
" --config cli/mock-bench.jsonc" +
102+
" --tunable_values tunable-values/tunable-values-example.jsonc" +
103+
" --trial_config_repeat_count 5" +
104+
" --mock_env_seed -1", # Deterministic Mock Environment.
82105
[
83106
f"^{_RE_DATE} run\\.py:\\d+ " +
84-
r"_main INFO Final score: \{'score': 65\.67\d+\}\s*$",
107+
r"_main INFO Final score: \{'score': 67\.11\d+\}\s*$",
85108
]
86109
)
87110

@@ -93,7 +116,10 @@ def test_launch_main_app_opt(root_path: str, local_exec_service: LocalExecServic
93116
"""
94117
_launch_main_app(
95118
root_path, local_exec_service,
96-
"--config mlos_bench/mlos_bench/tests/config/cli/mock-opt.jsonc --trial_config_repeat_count 3 --max_suggestions 3",
119+
"--config cli/mock-opt.jsonc" +
120+
" --trial_config_repeat_count 3" +
121+
" --max_suggestions 3" +
122+
" --mock_env_seed 42", # Noisy Mock Environment.
97123
[
98124
# Iteration 1: Expect first value to be the baseline
99125
f"^{_RE_DATE} mlos_core_optimizer\\.py:\\d+ " +

0 commit comments

Comments
 (0)