def test_mpi_passes(self): run_config = CompiledOperationSpecification.read([ os.path.abspath("tests/fixtures/plain/distributed_mpi_file.yml"), { "kind": "compiled_operation" }, ]) run_config = CompiledOperationSpecification.apply_context(run_config) assert run_config.version == 1.05 assert run_config.is_mpi_job_run assert run_config.termination is None assert run_config.run.launcher.replicas == 1 assert run_config.run.launcher.to_dict() == { "replicas": 1, "container": { "name": "polyaxon-main", "image": "mpioperator/tensorflow-benchmarks:latest", "command": ["mpirun", "python", "run.py"], }, } assert run_config.run.launcher.environment is None assert run_config.run.worker.replicas == 2 assert run_config.run.worker.environment.affinity is None assert run_config.run.worker.environment.node_selector is not None assert isinstance(run_config.run.worker.environment.tolerations, list) assert run_config.run.worker.to_dict()["container"] == { "name": "polyaxon-main", "image": "mpioperator/tensorflow-benchmarks:latest", "command": ["mpirun", "python", "run.py"], "resources": { "limits": { "nvidia.com/gpu": 1 } }, }
def test_matrix_file_passes_int_float_types(self): run_config = V1CompiledOperation.read( [ reader.read( os.path.abspath( "tests/fixtures/pipelines/matrix_file_with_int_float_types.yml" ) ), {"kind": "compiled_operation"}, ] ) run_config = CompiledOperationSpecification.apply_context(run_config) assert run_config.version == 1.05 assert run_config.is_dag_run is True assert run_config.has_pipeline is True assert run_config.schedule is None assert run_config.run.concurrency == 4 assert isinstance(run_config.run, V1Dag) assert run_config.run.early_stopping is None assert run_config.run.kind == V1Dag.IDENTIFIER assert len(run_config.run.operations) == 2 assert len(run_config.run.components) == 1 template_grid = run_config.run.operations[1].parallel assert isinstance(template_grid, V1GridSearch) assert isinstance(template_grid.params["param1"], V1HpChoice) assert isinstance(template_grid.params["param2"], V1HpChoice) assert template_grid.params["param1"].to_dict() == { "kind": "choice", "value": [1, 2], } assert template_grid.params["param2"].to_dict() == { "kind": "choice", "value": [3.3, 4.4], } assert template_grid.concurrency == 2 assert template_grid.early_stopping is None
def test_patch_experiment_without_io_and_params_raises(self): content = { "version": 1.05, "kind": "component", "run": { "kind": V1RunKind.JOB, "container": { "name": "polyaxon-main", "image": "test/test:latest", "command": "train", }, }, } config = V1Component.read(content) assert config.to_dict() == content content = { "version": 1.05, "kind": "compiled_operation", "run": { "kind": V1RunKind.JOB, "container": { "name": "polyaxon-main", "image": "test/test:latest", "command": "train", }, }, } config = V1CompiledOperation.read(content) config = CompiledOperationSpecification.apply_context(config) assert config.to_dict() == content # Add params params = {"params": {"lr": 0.1}} with self.assertRaises(ValidationError): config.patch(values=params)
def test_build_run_pipeline(self): run_config = V1CompiledOperation.read( [ os.path.abspath("tests/fixtures/pipelines/build_run_pipeline.yml"), {"kind": "compiled_operation"}, ] ) run_config = CompiledOperationSpecification.apply_context(run_config) assert len(run_config.run.operations) == 2 assert run_config.run.operations[0].name == "build" assert run_config.run.operations[1].name == "run" assert run_config.is_dag_run is True assert run_config.has_pipeline is True assert run_config.schedule is None assert len(run_config.run.components) == 2 assert run_config.run.components[0].name == "experiment-template" assert run_config.run.components[0].termination.to_dict() == {"maxRetries": 2} assert run_config.run.components[0].run.to_dict() == { "kind": V1RunKind.JOB, "environment": { "nodeSelector": {"polyaxon": "experiments"}, "serviceAccountName": "service", "imagePullSecrets": ["secret1", "secret2"], }, "container": { "image": "{{ image }}", "command": ["python3", "main.py"], "args": "--lr={{ lr }}", "name": "polyaxon-main", "resources": {"requests": {"cpu": 1}}, }, } assert run_config.run.components[1].name == "build-template" assert run_config.run.components[1].run.container.image == "base" assert run_config.run.operations[0].name == "build" # Create a an op spec run_config.run.set_op_component("run") assert run_config.run.operations[1].has_component_reference is True job_config = run_config.run.get_op_spec_by_index(1) assert {p: job_config.params[p].to_dict() for p in job_config.params} == { "image": {"value": "outputs.docker-image", "ref": "ops.build"}, "lr": {"value": 0.001}, } run_config = OperationSpecification.compile_operation(job_config) run_config.apply_params({"image": {"value": "foo"}, "lr": {"value": 0.001}}) run_config = CompiledOperationSpecification.apply_context(run_config) run_config = CompiledOperationSpecification.apply_run_contexts(run_config) assert run_config.termination.to_dict() == {"maxRetries": 2} assert run_config.run.to_dict() == { "kind": V1RunKind.JOB, "environment": { "nodeSelector": {"polyaxon": "experiments"}, "serviceAccountName": "service", "imagePullSecrets": ["secret1", "secret2"], }, "container": { "image": "foo", "command": ["python3", "main.py"], "args": "--lr=0.001", "name": "polyaxon-main", "resources": {"requests": {"cpu": 1}}, }, }
def test_required_inputs_with_params(self): run_config = V1CompiledOperation.read([ os.path.abspath("tests/fixtures/typing/required_inputs.yml"), { "kind": "compiled_operation" }, ]) with self.assertRaises(ValidationError): CompiledOperationSpecification.apply_context(run_config) assert run_config.inputs[0].value is None assert run_config.inputs[1].value is None run_config.apply_params(params={ "loss": { "value": "bar" }, "flag": { "value": False } }) assert run_config.inputs[0].value == "bar" assert run_config.inputs[1].value is False run_config = CompiledOperationSpecification.apply_context(run_config) run_config = CompiledOperationSpecification.apply_run_contexts( run_config) assert run_config.version == 1.1 assert run_config.tags == ["foo", "bar"] assert run_config.run.container.image == "my_image" assert run_config.run.container.command == ["/bin/sh", "-c"] assert run_config.run.container.args == "video_prediction_train --loss=bar " run_config = V1CompiledOperation.read([ os.path.abspath("tests/fixtures/typing/required_inputs.yml"), { "kind": "compiled_operation" }, ]) assert run_config.inputs[0].value is None assert run_config.inputs[1].value is None run_config.apply_params(params={ "loss": { "value": "bar" }, "flag": { "value": True } }) assert run_config.inputs[0].value == "bar" assert run_config.inputs[1].value is True run_config = CompiledOperationSpecification.apply_context(run_config) run_config = CompiledOperationSpecification.apply_run_contexts( run_config) assert run_config.version == 1.1 assert run_config.tags == ["foo", "bar"] assert run_config.run.container.image == "my_image" assert run_config.run.container.command == ["/bin/sh", "-c"] assert (run_config.run.container.args == "video_prediction_train --loss=bar --flag") # Adding extra value raises with self.assertRaises(ValidationError): run_config.validate_params( params={ "loss": { "value": "bar" }, "flag": { "value": True }, "value": { "value": 1.1 }, }) with self.assertRaises(PolyaxonfileError): check_polyaxonfile( polyaxonfile=os.path.abspath( "tests/fixtures/typing/required_inputs.yml"), params={ "loss": { "value": "bar" }, "value": { "value": 1.1 } }, is_cli=False, ) # Adding non valid params raises with self.assertRaises(ValidationError): run_config.validate_params(params={"value": {"value": 1.1}})
def test_apply_context_raises_with_required_inputs(self): content = { "version": 1.05, "kind": "component", "inputs": [ { "name": "lr", "type": types.FLOAT }, { "name": "num_steps", "type": types.INT }, ], "run": { "kind": V1RunKind.JOB, "container": { "name": "polyaxon-main", "image": "test/test:latest", "command": "train", }, }, } component_config = V1Component.read(content) assert component_config.to_dict() == content content = { "version": 1.05, "kind": "compiled_operation", "inputs": [ { "name": "lr", "type": types.FLOAT }, { "name": "num_steps", "type": types.INT }, ], "run": { "kind": V1RunKind.JOB, "container": { "name": "polyaxon-main", "image": "test/test:latest", "command": "train", }, }, } run_config = V1CompiledOperation.read(content) # Raise because required inputs are not met with self.assertRaises(ValidationError): CompiledOperationSpecification.apply_context(run_config) # Validation for template should pass validated_params = run_config.validate_params() assert { "lr": None, "num_steps": None } == {p.name: p.param.value for p in validated_params} # Validation for non template should raise with self.assertRaises(ValidationError): run_config.validate_params(is_template=False)
def test_patch_experiment_with_optional_inputs(self): content = { "version": 1.05, "kind": "compiled_operation", "inputs": [ { "name": "lr", "type": types.FLOAT, "value": 0.6, "isOptional": True }, { "name": "num_steps", "type": types.INT, "value": 16, "isOptional": True, }, ], "run": { "kind": V1RunKind.JOB, "container": { "name": "polyaxon-main", "image": "test/test:latest", "command": "train", }, }, } config = V1CompiledOperation.read(content) assert config.inputs[0].value == 0.6 assert config.inputs[1].value == 16 config = CompiledOperationSpecification.apply_context(config) validated_params = config.validate_params() assert { "lr": 0.6, "num_steps": 16 } == {p.name: p.param.value for p in validated_params} assert config.inputs[0].value == 0.6 assert config.inputs[1].value == 16 with self.assertRaises(ValidationError): # not valid params = {"params": {"lr": 0.1}} config.patch(values=params) # Add env assert config.run.container.resources is None env = { "run": { "container": { "resources": { "requests": { "gpu": 1, "tpu": 1 }, "limits": { "gpu": 1, "tpu": 1 }, } } } } config = config.patch(values=env) assert config.run.container.resources == { "requests": { "gpu": 1, "tpu": 1 }, "limits": { "gpu": 1, "tpu": 1 }, } # Patch with unsupported spec matrix = {"hptuning": {"params": {"lr": {"values": [0.1, 0.2]}}}} with self.assertRaises(ValidationError): config.patch(values=matrix) # Patch with unsupported spec wrong_config = {"lr": {"values": [0.1, 0.2]}} with self.assertRaises(ValidationError): config.patch(values=wrong_config)
def test_apply_context_passes_with_required_inputs_and_params(self): content = { "version": 1.05, "kind": "component", "inputs": [ { "name": "lr", "type": types.FLOAT }, { "name": "num_steps", "type": types.INT }, ], "run": { "kind": V1RunKind.JOB, "container": { "name": "polyaxon-main", "image": "test/test:latest", "command": "train", }, }, } component_config = V1Component.read(content) assert component_config.to_dict() == content content = { "version": 1.05, "kind": "compiled_operation", "inputs": [ { "name": "lr", "type": types.FLOAT }, { "name": "num_steps", "type": types.INT }, ], "run": { "kind": V1RunKind.JOB, "container": { "name": "polyaxon-main", "image": "test/test:latest", "command": "train", }, }, } run_config = V1CompiledOperation.read(content) # no params with self.assertRaises(ValidationError): CompiledOperationSpecification.apply_context(run_config) params = {"lr": {"value": 0.1}, "num_steps": {"value": 100}} assert run_config.inputs[0].value is None assert run_config.inputs[1].value is None validated_params = run_config.validate_params(params=params) run_config.apply_params(params=params) assert params == {p.name: p.param.to_dict() for p in validated_params} assert run_config.inputs[0].value == 0.1 assert run_config.inputs[1].value == 100 run_config = CompiledOperationSpecification.apply_context(run_config) updated_content = { "version": 1.05, "kind": "compiled_operation", "inputs": [ { "name": "lr", "type": types.FLOAT, "isOptional": True, "value": 0.1 }, { "name": "num_steps", "type": types.INT, "isOptional": True, "value": 100, }, ], "run": { "kind": V1RunKind.JOB, "container": { "name": "polyaxon-main", "image": "test/test:latest", "command": "train", }, }, } assert run_config.to_dict() == updated_content env = { "run": { "container": { "resources": { "requests": { "gpu": 1, "tpu": 1 }, "limits": { "gpu": 1, "tpu": 1 }, } } } } run_config = run_config.patch(values=env) assert (run_config.run.container.resources == env["run"]["container"] ["resources"])