From 3c43503bff0f4c47320b8367cf1930764ab2beef Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Wed, 20 Nov 2019 15:13:38 -0600 Subject: [PATCH 1/7] Remove RestartStep from the Dagrt language. This change removes RestartStep, as it's equivalent to SwitchPhase(). The language version is bumped to 2019.4. The CodeBuilder restart_step() method is kept for convenience and backwards compatibility. This change also fixes the SwitchPhase code lowering in Fortran to exit immediately. --- dagrt/codegen/fortran.py | 4 +-- dagrt/codegen/python.py | 12 --------- dagrt/exec_numpy.py | 10 -------- dagrt/language.py | 51 ++++++++++++++++++++------------------- dagrt/version.py | 2 +- test/test_code_builder.py | 18 -------------- 6 files changed, 28 insertions(+), 69 deletions(-) diff --git a/dagrt/codegen/fortran.py b/dagrt/codegen/fortran.py index 137b30e..496891f 100644 --- a/dagrt/codegen/fortran.py +++ b/dagrt/codegen/fortran.py @@ -2289,13 +2289,11 @@ class CodeGenerator(StructuredCodeGenerator): self.emit("goto 999") - def emit_inst_RestartStep(self, inst): - self.emit("goto 999") - def emit_inst_SwitchPhase(self, inst): self.emit( 'dagrt_state%dagrt_next_phase = ' + self.phase_name_to_phase_sym(inst.next_phase)) + self.emit("goto 999") # }}} diff --git a/dagrt/codegen/python.py b/dagrt/codegen/python.py index cdac431..16e89b7 100644 --- a/dagrt/codegen/python.py +++ b/dagrt/codegen/python.py @@ -88,10 +88,6 @@ class FailStepException(RuntimeError): pass -class RestartStepException(RuntimeError): - pass - - class TransitionEvent(Exception): def __init__(self, next_phase): @@ -352,9 +348,6 @@ class CodeGenerator(StructuredCodeGenerator): yield self.StepFailed(t=self.t) continue - except self.RestartStepException: - continue - except self.TransitionEvent as evt: self.next_phase = evt.next_phase @@ -495,11 +488,6 @@ class CodeGenerator(StructuredCodeGenerator): if not self._has_yield_inst: self._emit('yield') - def emit_inst_RestartStep(self, inst): - self._emit('raise self.RestartStepException()') - if not self._has_yield_inst: - self._emit('yield') - def emit_inst_SwitchPhase(self, inst): assert '\'' not in inst.next_phase self._emit('raise self.TransitionEvent(\'' + inst.next_phase + '\')') diff --git a/dagrt/exec_numpy.py b/dagrt/exec_numpy.py index 0e15304..20fba9b 100644 --- a/dagrt/exec_numpy.py +++ b/dagrt/exec_numpy.py @@ -31,10 +31,6 @@ class FailStepException(Exception): pass -class RestartStepException(Exception): - pass - - class TransitionEvent(Exception): def __init__(self, next_phase): @@ -152,9 +148,6 @@ class NumpyInterpreter(object): yield StepFailed(t=self.context[""]) continue - except RestartStepException: - continue - except TransitionEvent as evt: self.next_phase = evt.next_phase @@ -268,9 +261,6 @@ class NumpyInterpreter(object): def exec_FailStep(self, stmt): raise FailStepException() - def exec_RestartStep(self, stmt): - raise RestartStepException() - def exec_Nop(self, stmt): pass diff --git a/dagrt/language.py b/dagrt/language.py index 2a9955f..e1df884 100644 --- a/dagrt/language.py +++ b/dagrt/language.py @@ -121,7 +121,6 @@ with user code. .. autoclass:: YieldState .. autoclass:: Raise .. autoclass:: FailStep -.. autoclass:: RestartStep .. autoclass:: SwitchPhase Miscellaneous Statements @@ -589,19 +588,6 @@ class FailStep(Statement): exec_method = six.moves.intern("exec_FailStep") - -class RestartStep(Statement): - """Exits the current step. Execution resumes with the next step as normal. - """ - - def get_written_variables(self): - return frozenset() - - def __str__(self): - return "RestartStep{cond}".format(cond=self._condition_printing_suffix()) - - exec_method = six.moves.intern("exec_RestartStep") - # }}} @@ -814,27 +800,41 @@ class ExecutionController(object): class CodeBuilder(object): """ + .. attribute:: label + + The name of the phase being generated + .. attribute:: statements The set of statements generated for the phase - .. automethod:: if_ - .. automethod:: else_ - .. method:: __call__ - Alias for :func:`CodeBuilder.assign`. + Language support: .. automethod:: assign - .. automethod:: fresh_var_name - .. automethod:: fresh_var .. automethod:: assign_implicit - .. automethod:: assign_implicit_1 .. automethod:: yield_state .. automethod:: fail_step - .. automethod:: restart_step .. automethod:: raise_ .. automethod:: switch_phase + + Control flow: + + .. automethod:: if_ + .. automethod:: else_ + + Context manager: + .. automethod:: __enter__ .. automethod:: __exit__ + + Convenience functions: + + .. method:: __call__ + Alias for :func:`CodeBuilder.assign`. + .. automethod:: assign_implicit_1 + .. automethod:: fresh_var_name + .. automethod:: fresh_var + .. automethod:: restart_step """ # This is a dummy variable name representing the "system state", which is @@ -1123,12 +1123,13 @@ class CodeBuilder(object): def fail_step(self): self._add_statement(FailStep()) - def restart_step(self): - self._add_statement(RestartStep()) - def raise_(self, error_condition, error_message=None): self._add_statement(Raise(error_condition, error_message)) + def restart_step(self): + """Equivalent to *switch_phase(self.label)*.""" + self.switch_phase(self.label) + def switch_phase(self, next_phase): self._add_statement(SwitchPhase(next_phase)) diff --git a/dagrt/version.py b/dagrt/version.py index 74bb455..0d96d97 100644 --- a/dagrt/version.py +++ b/dagrt/version.py @@ -1,2 +1,2 @@ -VERSION = (2019, 3) +VERSION = (2019, 4) VERSION_TEXT = ".".join(str(i) for i in VERSION) diff --git a/test/test_code_builder.py b/test/test_code_builder.py index 18dc239..d31fd11 100755 --- a/test/test_code_builder.py +++ b/test/test_code_builder.py @@ -147,24 +147,6 @@ def test_CodeBuilder_nested_condition_with_else_not_taken(python_method_impl): assert result == 3 -def test_CodeBuilder_restart_step(python_method_impl): - with CodeBuilder() as builder1: - builder1("

x", 1) - builder1.restart_step() - builder1("

x", 2) - - with CodeBuilder() as builder2: - builder2.yield_state(var('

x'), 'x', 0, 'final') - - code = DAGCode({ - "state1": builder1.as_execution_phase("state2"), - "state2": builder2.as_execution_phase("state2") - }, "state1") - - result = execute_and_return_single_result(python_method_impl, code) - assert result == 1 - - if __name__ == "__main__": if len(sys.argv) > 1: exec(sys.argv[1]) -- GitLab From d748bb76896f169407859c1a495c9490878cc749 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Wed, 20 Nov 2019 15:22:49 -0600 Subject: [PATCH 2/7] Keep test_CodeBuilder_restart_step --- test/test_code_builder.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/test_code_builder.py b/test/test_code_builder.py index d31fd11..18dc239 100755 --- a/test/test_code_builder.py +++ b/test/test_code_builder.py @@ -147,6 +147,24 @@ def test_CodeBuilder_nested_condition_with_else_not_taken(python_method_impl): assert result == 3 +def test_CodeBuilder_restart_step(python_method_impl): + with CodeBuilder() as builder1: + builder1("

x", 1) + builder1.restart_step() + builder1("

x", 2) + + with CodeBuilder() as builder2: + builder2.yield_state(var('

x'), 'x', 0, 'final') + + code = DAGCode({ + "state1": builder1.as_execution_phase("state2"), + "state2": builder2.as_execution_phase("state2") + }, "state1") + + result = execute_and_return_single_result(python_method_impl, code) + assert result == 1 + + if __name__ == "__main__": if len(sys.argv) > 1: exec(sys.argv[1]) -- GitLab From 23cdbcc8f7dafdc932f8a053e26f4c7c365784dc Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Wed, 20 Nov 2019 15:25:08 -0600 Subject: [PATCH 3/7] Fix test_CodeBuilder_restart_step --- test/test_code_builder.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test_code_builder.py b/test/test_code_builder.py index 18dc239..24dac7a 100755 --- a/test/test_code_builder.py +++ b/test/test_code_builder.py @@ -148,12 +148,12 @@ def test_CodeBuilder_nested_condition_with_else_not_taken(python_method_impl): def test_CodeBuilder_restart_step(python_method_impl): - with CodeBuilder() as builder1: + with CodeBuilder("state1") as builder1: builder1("

x", 1) builder1.restart_step() builder1("

x", 2) - with CodeBuilder() as builder2: + with CodeBuilder("state2") as builder2: builder2.yield_state(var('

x'), 'x', 0, 'final') code = DAGCode({ -- GitLab From 1dcb24d10b157df9d4c50738bc4c1a53e494cd1e Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Wed, 20 Nov 2019 15:38:06 -0600 Subject: [PATCH 4/7] Actually fix test_CodeBuilder_restart_step --- test/test_code_builder.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/test/test_code_builder.py b/test/test_code_builder.py index 24dac7a..c8c3a13 100755 --- a/test/test_code_builder.py +++ b/test/test_code_builder.py @@ -148,21 +148,25 @@ def test_CodeBuilder_nested_condition_with_else_not_taken(python_method_impl): def test_CodeBuilder_restart_step(python_method_impl): + with CodeBuilder("init") as builder_init: + builder_init("

x", "0") + with CodeBuilder("state1") as builder1: - builder1("

x", 1) - builder1.restart_step() - builder1("

x", 2) + builder1("

x", "

x + 1") + with builder1.if_("

x == 1"): + builder1.restart_step() with CodeBuilder("state2") as builder2: - builder2.yield_state(var('

x'), 'x', 0, 'final') + builder2.yield_state(var("

x"), "x", 0, "final") code = DAGCode({ + "init": builder_init.as_execution_phase("state1"), "state1": builder1.as_execution_phase("state2"), "state2": builder2.as_execution_phase("state2") - }, "state1") + }, "init") - result = execute_and_return_single_result(python_method_impl, code) - assert result == 1 + result = execute_and_return_single_result(python_method_impl, code, max_steps=4) + assert result == 2 if __name__ == "__main__": -- GitLab From 06b08316d1634f14120cae4a4984534ae1393c52 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Wed, 20 Nov 2019 19:48:36 -0600 Subject: [PATCH 5/7] * Add a name attribute to each phase * Make the cb constructor arg mandatory * Rename the cb constructor arg from "label" to "name", to fit with the name attribute * Add a DAGCode.from_phases_list() classmethod * Remove old DAGCode classmethods that take statement lists, as they don't fit with the new interface --- dagrt/language.py | 44 ++++++++++++++----------------- test/test_ast.py | 4 ++- test/test_builtins.py | 11 ++++---- test/test_code_builder.py | 51 +++++++++++++++++++----------------- test/test_codegen.py | 15 ++++++----- test/test_codegen_fortran.py | 8 +++--- test/test_codegen_python.py | 48 +++++++++++++++++---------------- test/utils.py | 34 ++++++++++++++++++++++++ 8 files changed, 129 insertions(+), 86 deletions(-) diff --git a/dagrt/language.py b/dagrt/language.py index e1df884..17a71e7 100644 --- a/dagrt/language.py +++ b/dagrt/language.py @@ -595,6 +595,10 @@ class FailStep(Statement): class ExecutionPhase(RecordWithoutPickling): """ + .. attribute:: name + + name of this phase + .. attribute:: depends_on a list of statement IDs that need to be accomplished @@ -613,8 +617,9 @@ class ExecutionPhase(RecordWithoutPickling): will actually be executed. """ - def __init__(self, next_phase, statements): + def __init__(self, name, next_phase, statements): super(ExecutionPhase, self).__init__( + name=name, next_phase=next_phase, statements=statements) @@ -647,23 +652,11 @@ class DAGCode(RecordWithoutPickling): """ @classmethod - def create_with_steady_phase(cls, statements): - phases = {'main': ExecutionPhase( - next_phase='main', statements=statements)} - return cls(phases, 'main') - - @classmethod - def _create_with_init_and_step(cls, init_statements, main_statements): - phases = {} - phases['initialization'] = ExecutionPhase( - next_phase='main', - statements=init_statements) - - phases['main'] = ExecutionPhase( - next_phase='main', - statements=main_statements) - - return cls(phases, 'initialization') + def from_phases_list(cls, phases, initial_phase): + name_to_phase = dict() + for phase in phases: + name_to_phase[phase.name] = phase + return cls(name_to_phase, initial_phase) def __init__(self, phases, initial_phase): assert not isinstance(phases, list) @@ -800,7 +793,7 @@ class ExecutionController(object): class CodeBuilder(object): """ - .. attribute:: label + .. attribute:: name The name of the phase being generated @@ -842,11 +835,11 @@ class CodeBuilder(object): # side effects. _EXECUTION_STATE = "" - def __init__(self, label="phase"): + def __init__(self, name): """ - :arg label: The name of the phase to generate + :arg name: The name of the phase to generate """ - self.label = label + self.name = name self.statements = [] # Maps variables to the sequentially last statement to write them @@ -932,7 +925,7 @@ class CodeBuilder(object): self._seen_var_names |= read_variables | written_variables def next_statement_id(self): - return "%s_%d" % (self.label, len(self.statements)) + return "%s_%d" % (self.name, len(self.statements)) @memoize_method def _var_name_generator(self, prefix): @@ -1127,8 +1120,8 @@ class CodeBuilder(object): self._add_statement(Raise(error_condition, error_message)) def restart_step(self): - """Equivalent to *switch_phase(self.label)*.""" - self.switch_phase(self.label) + """Equivalent to *switch_phase(self.name)*.""" + self.switch_phase(self.name) def switch_phase(self, next_phase): self._add_statement(SwitchPhase(next_phase)) @@ -1145,6 +1138,7 @@ class CodeBuilder(object): :arg next_phase: The name of the default next phase """ return ExecutionPhase( + name=self.name, next_phase=next_phase, statements=frozenset(self.statements)) diff --git a/test/test_ast.py b/test/test_ast.py index 50db7e8..4e0f9b2 100755 --- a/test/test_ast.py +++ b/test/test_ast.py @@ -31,6 +31,8 @@ from dagrt.codegen.dag_ast import (IfThen, IfThenElse, Block, StatementWrapper, create_ast_from_phase, simplify_ast) from dagrt.language import Statement, DAGCode +from utils import create_DAGCode_with_steady_phase + import pytest @@ -58,7 +60,7 @@ def test_create_ast(): return hash(self._state()) nop = ComparableNop(condition=x, id="nop", depends_on=()) - code = DAGCode.create_with_steady_phase([nop]) + code = create_DAGCode_with_steady_phase([nop]) ast = create_ast_from_phase(code, "main") assert ast == IfThen(x, StatementWrapper(nop.copy(condition=True))) diff --git a/test/test_builtins.py b/test/test_builtins.py index 59bbb6c..f4d219e 100755 --- a/test/test_builtins.py +++ b/test/test_builtins.py @@ -35,7 +35,8 @@ from utils import ( # noqa execute_and_return_single_result, RawCodeBuilder, python_method_impl_interpreter as pmi_int, - python_method_impl_codegen as pmi_cg) + python_method_impl_codegen as pmi_cg, + create_DAGCode_with_steady_phase) @pytest.mark.parametrize(('obj, len_'), [(np.ones(0), 0), @@ -51,7 +52,7 @@ def test_len(python_method_impl, obj, len_): expression=var('x'), component_id='', depends_on=['assign_1'])) cbuild.commit() - code = DAGCode.create_with_steady_phase(cbuild.statements) + code = create_DAGCode_with_steady_phase(cbuild.statements) result = execute_and_return_single_result(python_method_impl, code) assert result == len_ @@ -67,7 +68,7 @@ def test_isnan(python_method_impl, value): expression=var('x'), component_id='', depends_on=['assign_1'])) cbuild.commit() - code = DAGCode.create_with_steady_phase(cbuild.statements) + code = create_DAGCode_with_steady_phase(cbuild.statements) result = execute_and_return_single_result(python_method_impl, code) assert result == np.isnan(value) @@ -98,7 +99,7 @@ def test_norm(python_method_impl, order, norm_suffix, test_vector): expression=var('n'), component_id='', depends_on=['assign_2'])) cbuild.commit() - code = DAGCode.create_with_steady_phase(cbuild.statements) + code = create_DAGCode_with_steady_phase(cbuild.statements) result = execute_and_return_single_result(python_method_impl, code) assert np.allclose(result, true_norm(test_vector)) @@ -115,7 +116,7 @@ def test_dot_product(python_method_impl, x, y): expression=var('x'), component_id='', depends_on=['assign_1'])) cbuild.commit() - code = DAGCode.create_with_steady_phase(cbuild.statements) + code = create_DAGCode_with_steady_phase(cbuild.statements) result = execute_and_return_single_result(python_method_impl, code) assert result == np.vdot(x, y) diff --git a/test/test_code_builder.py b/test/test_code_builder.py index c8c3a13..f90f763 100755 --- a/test/test_code_builder.py +++ b/test/test_code_builder.py @@ -12,7 +12,9 @@ from utils import ( # noqa python_method_impl_interpreter as pmi_int, python_method_impl_codegen as pmi_cg) -from utils import execute_and_return_single_result +from utils import ( + execute_and_return_single_result, + create_DAGCode_with_steady_phase) __copyright__ = "Copyright (C) 2014 Matt Wala" @@ -39,86 +41,86 @@ THE SOFTWARE. def test_CodeBuilder_yield(python_method_impl): - with CodeBuilder() as builder: + with CodeBuilder("phase") as builder: builder.yield_state(1, 'x', 0, 'final') - code = DAGCode.create_with_steady_phase(builder.statements) + code = create_DAGCode_with_steady_phase(builder.statements) result = execute_and_return_single_result(python_method_impl, code) assert result == 1 def test_CodeBuilder_assign(python_method_impl): - with CodeBuilder() as builder: + with CodeBuilder("phase") as builder: builder(var('x'), 1) builder.yield_state(var('x'), 'x', 0, 'final') - code = DAGCode.create_with_steady_phase(builder.statements) + code = create_DAGCode_with_steady_phase(builder.statements) result = execute_and_return_single_result(python_method_impl, code) assert result == 1 def test_CodeBuilder_condition(python_method_impl): - with CodeBuilder() as builder: + with CodeBuilder("phase") as builder: builder(var('x'), 1) with builder.if_(var('x'), '==', 1): builder(var('x'), 2) builder.yield_state(var('x'), 'x', 0, 'final') - code = DAGCode.create_with_steady_phase(builder.statements) + code = create_DAGCode_with_steady_phase(builder.statements) result = execute_and_return_single_result(python_method_impl, code) assert result == 2 def test_CodeBuilder_write_ordering(python_method_impl): - with CodeBuilder() as builder: + with CodeBuilder("phase") as builder: builder("y", "1") builder("x", "y") builder("y", "2") builder("z", "y") builder.yield_state(var('x'), 'x', 0, 'final') - code = DAGCode.create_with_steady_phase(builder.statements) + code = create_DAGCode_with_steady_phase(builder.statements) result = execute_and_return_single_result(python_method_impl, code) assert result == 1 def test_CodeBuilder_condition_with_else(python_method_impl): - with CodeBuilder() as builder: + with CodeBuilder("phase") as builder: builder(var('x'), 1) with builder.if_(var('x'), '!=', 1): builder(var('x'), 2) with builder.else_(): builder(var('x'), 3) builder.yield_state(var('x'), 'x', 0, 'final') - code = DAGCode.create_with_steady_phase(builder.statements) + code = create_DAGCode_with_steady_phase(builder.statements) result = execute_and_return_single_result(python_method_impl, code) assert result == 3 def test_CodeBuilder_condition_with_else_not_taken(python_method_impl): - with CodeBuilder() as builder: + with CodeBuilder("phase") as builder: builder(var('x'), 1) with builder.if_(var('x'), '==', 1): builder(var('x'), 2) with builder.else_(): builder(var('x'), 3) builder.yield_state(var('x'), 'x', 0, 'final') - code = DAGCode.create_with_steady_phase(builder.statements) + code = create_DAGCode_with_steady_phase(builder.statements) result = execute_and_return_single_result(python_method_impl, code) assert result == 2 def test_CodeBuilder_nested_condition(python_method_impl): - with CodeBuilder() as builder: + with CodeBuilder("phase") as builder: builder(var('x'), 1) with builder.if_(var('x'), '==', 1): builder(var('x'), 2) with builder.if_(var('x'), '==', 2): builder(var('x'), 3) builder.yield_state(var('x'), 'x', 0, 'final') - code = DAGCode.create_with_steady_phase(builder.statements) + code = create_DAGCode_with_steady_phase(builder.statements) result = execute_and_return_single_result(python_method_impl, code) assert result == 3 def test_CodeBuilder_nested_condition_with_else(python_method_impl): - with CodeBuilder() as builder: + with CodeBuilder("phase") as builder: builder(var('x'), 1) with builder.if_(var('x'), '==', 1): builder(var('x'), 2) @@ -127,13 +129,13 @@ def test_CodeBuilder_nested_condition_with_else(python_method_impl): with builder.else_(): builder(var('x'), 4) builder.yield_state(var('x'), 'x', 0, 'final') - code = DAGCode.create_with_steady_phase(builder.statements) + code = create_DAGCode_with_steady_phase(builder.statements) result = execute_and_return_single_result(python_method_impl, code) assert result == 4 def test_CodeBuilder_nested_condition_with_else_not_taken(python_method_impl): - with CodeBuilder() as builder: + with CodeBuilder("phase") as builder: builder(var('x'), 1) with builder.if_(var('x'), '==', 1): builder(var('x'), 2) @@ -142,7 +144,7 @@ def test_CodeBuilder_nested_condition_with_else_not_taken(python_method_impl): with builder.else_(): builder(var('x'), 4) builder.yield_state(var('x'), 'x', 0, 'final') - code = DAGCode.create_with_steady_phase(builder.statements) + code = create_DAGCode_with_steady_phase(builder.statements) result = execute_and_return_single_result(python_method_impl, code) assert result == 3 @@ -159,11 +161,12 @@ def test_CodeBuilder_restart_step(python_method_impl): with CodeBuilder("state2") as builder2: builder2.yield_state(var("

x"), "x", 0, "final") - code = DAGCode({ - "init": builder_init.as_execution_phase("state1"), - "state1": builder1.as_execution_phase("state2"), - "state2": builder2.as_execution_phase("state2") - }, "init") + phases = [ + builder_init.as_execution_phase(next_phase="state1"), + builder1.as_execution_phase(next_phase="state2"), + builder2.as_execution_phase(next_phase="state2") + ] + code = DAGCode.from_phases_list(phases, "init") result = execute_and_return_single_result(python_method_impl, code, max_steps=4) assert result == 2 diff --git a/test/test_codegen.py b/test/test_codegen.py index 6051878..4f33b8d 100755 --- a/test/test_codegen.py +++ b/test/test_codegen.py @@ -11,7 +11,10 @@ from dagrt.codegen.analysis import verify_code from pymbolic import var -from utils import RawCodeBuilder +from utils import ( + RawCodeBuilder, + create_DAGCode_with_init_and_main_phases, + create_DAGCode_with_steady_phase) __copyright__ = "Copyright (C) 2014 Andreas Kloeckner, Matt Wala" @@ -57,7 +60,7 @@ def test_circular_dependency_detection(): expression=var('y'), component_id='', depends_on=['assign'])) cbuild.commit() - code = DAGCode._create_with_init_and_step( + code = create_DAGCode_with_init_and_main_phases( init_statements=[], main_statements=cbuild.statements) with pytest.raises(CodeGenerationError): @@ -74,7 +77,7 @@ def test_missing_dependency_detection(): expression=var('y'), component_id='', depends_on=['assign']) ]) - code = DAGCode._create_with_init_and_step( + code = create_DAGCode_with_init_and_main_phases( init_statements=[], main_statements=statements) with pytest.raises(CodeGenerationError): @@ -85,10 +88,10 @@ def test_missing_state_detection(): """Check that the code generator detects there is a missing state.""" from dagrt.language import CodeBuilder - with CodeBuilder(label="state_1") as cb: + with CodeBuilder(name="state_1") as cb: cb.switch_phase("state_2") - code = DAGCode.create_with_steady_phase(statements=cb.statements) + code = create_DAGCode_with_steady_phase(statements=cb.statements) with pytest.raises(CodeGenerationError): verify_code(code) @@ -115,7 +118,7 @@ def test_cond_detection(): component_id='', depends_on=['assign2'])) cbuild.commit() - code = DAGCode._create_with_init_and_step( + code = create_DAGCode_with_init_and_main_phases( init_statements=[], main_statements=cbuild.statements) with pytest.raises(CodeGenerationError): diff --git a/test/test_codegen_fortran.py b/test/test_codegen_fortran.py index 35c4522..c6fafec 100755 --- a/test/test_codegen_fortran.py +++ b/test/test_codegen_fortran.py @@ -33,6 +33,8 @@ from utils import RawCodeBuilder from dagrt.utils import run_fortran +from utils import create_DAGCode_with_steady_phase + #skip = pytest.mark.skipif(True, reason="not fully implemented") @@ -52,7 +54,7 @@ def test_basic_codegen(): expression=0, component_id='state', depends_on=[])) cbuild.commit() - code = DAGCode.create_with_steady_phase(cbuild.statements) + code = create_DAGCode_with_steady_phase(cbuild.statements) codegen = f.CodeGenerator("simple", user_type_map={ "state": f.ArrayType( @@ -69,7 +71,7 @@ class MatrixInversionFailure(object): def test_arrays_and_linalg(): from dagrt.function_registry import base_function_registry as freg - with CodeBuilder(label="primary") as cb: + with CodeBuilder(name="primary") as cb: cb("n", "4") cb("nodes", "`array`(n)") cb("vdm", "`array`(n*n)") @@ -93,7 +95,7 @@ def test_arrays_and_linalg(): with cb.if_("`norm_2`(myzero) > 10**(-8)"): cb.raise_(MatrixInversionFailure) - code = DAGCode.create_with_steady_phase(cb.statements) + code = create_DAGCode_with_steady_phase(cb.statements) codegen = f.CodeGenerator( 'arrays', diff --git a/test/test_codegen_python.py b/test/test_codegen_python.py index aeabd58..57be981 100755 --- a/test/test_codegen_python.py +++ b/test/test_codegen_python.py @@ -36,7 +36,9 @@ from pymbolic import var from utils import ( # noqa RawCodeBuilder, python_method_impl_interpreter as pmi_int, - python_method_impl_codegen as pmi_cg) + python_method_impl_codegen as pmi_cg, + create_DAGCode_with_init_and_main_phases, + create_DAGCode_with_steady_phase) def test_basic_codegen(): @@ -48,7 +50,7 @@ def test_basic_codegen(): expression=0, component_id='', depends_on=[])) cbuild.commit() - code = DAGCode._create_with_init_and_step( + code = create_DAGCode_with_init_and_main_phases( init_statements=[], main_statements=cbuild.statements) codegen = PythonCodeGenerator(class_name='Method') @@ -59,7 +61,7 @@ def test_basic_codegen(): hist = [s for s in method.run(max_steps=2)] assert len(hist) == 3 assert isinstance(hist[0], method.StepCompleted) - assert hist[0].current_phase == 'initialization' + assert hist[0].current_phase == 'init' assert isinstance(hist[1], method.StateComputed) assert hist[1].state_component == 0 assert isinstance(hist[2], method.StepCompleted) @@ -82,7 +84,7 @@ def test_basic_conditional_codegen(): expression=var('y'), component_id='', depends_on=['branch'])) cbuild.commit() - code = DAGCode._create_with_init_and_step( + code = create_DAGCode_with_init_and_main_phases( init_statements=[], main_statements=cbuild.statements) codegen = PythonCodeGenerator(class_name='Method') @@ -116,7 +118,7 @@ def test_basic_assign_rhs_codegen(): depends_on=['assign_rhs2']) ) cbuild.commit() - code = DAGCode._create_with_init_and_step( + code = create_DAGCode_with_init_and_main_phases( init_statements=[], main_statements=cbuild.statements) codegen = PythonCodeGenerator(class_name='Method') @@ -146,7 +148,7 @@ def test_basic_raise_codegen(): cbuild.add_and_get_ids(Raise(TimeStepUnderflow, "underflow", id="raise")) cbuild.commit() - code = DAGCode._create_with_init_and_step( + code = create_DAGCode_with_init_and_main_phases( init_statements=[], main_statements=cbuild.statements) codegen = PythonCodeGenerator(class_name="Method") @@ -173,7 +175,7 @@ def test_basic_fail_step_codegen(): cbuild = RawCodeBuilder() cbuild.add_and_get_ids(FailStep(id="fail")) cbuild.commit() - code = DAGCode._create_with_init_and_step( + code = create_DAGCode_with_init_and_main_phases( init_statements=[], main_statements=cbuild.statements) codegen = PythonCodeGenerator(class_name="Method") @@ -204,7 +206,7 @@ def test_local_name_distinctness(): expression=var('y^') + var('y*'), component_id='y', depends_on=['assign_y^', 'assign_y*'])) cbuild.commit() - code = DAGCode._create_with_init_and_step( + code = create_DAGCode_with_init_and_main_phases( init_statements=[], main_statements=cbuild.statements) codegen = PythonCodeGenerator(class_name='Method') @@ -231,7 +233,7 @@ def test_global_name_distinctness(): expression=var('

y^') + var('

y*'), component_id='y', depends_on=['assign_y^', 'assign_y*'])) cbuild.commit() - code = DAGCode._create_with_init_and_step( + code = create_DAGCode_with_init_and_main_phases( init_statements=[], main_statements=cbuild.statements) codegen = PythonCodeGenerator(class_name='Method') @@ -252,7 +254,7 @@ def test_function_name_distinctness(): expression=var('y^')() + var('y*')(), component_id='y')) cbuild.commit() - code = DAGCode._create_with_init_and_step( + code = create_DAGCode_with_init_and_main_phases( init_statements=[], main_statements=cbuild.statements) codegen = PythonCodeGenerator(class_name='Method') @@ -269,18 +271,20 @@ def test_function_name_distinctness(): def test_switch_phases(python_method_impl): from dagrt.language import CodeBuilder, ExecutionPhase - with CodeBuilder(label="state_1") as builder_1: + with CodeBuilder(name="state_1") as builder_1: builder_1(var("x"), 1) builder_1.switch_phase("state_2") - with CodeBuilder(label="state_2") as builder_2: + with CodeBuilder(name="state_2") as builder_2: builder_2.yield_state(var("x"), 'x', 0, 'final') code = DAGCode( phases={ "state_1": ExecutionPhase( + name="state_1", next_phase="state_1", statements=builder_1.statements), "state_2": ExecutionPhase( + name="state_2", next_phase="state_2", statements=builder_2.statements) }, @@ -295,7 +299,7 @@ def test_switch_phases(python_method_impl): def get_IfThenElse_test_code_and_expected_result(): from dagrt.expression import IfThenElse - with CodeBuilder(label="primary") as cb: + with CodeBuilder(name="primary") as cb: cb(var("c1"), IfThenElse(True, 0, 1)) cb(var("c2"), IfThenElse(False, 0, 1)) cb(var("c3"), IfThenElse(IfThenElse(True, True, False), 0, 1)) @@ -309,7 +313,7 @@ def get_IfThenElse_test_code_and_expected_result(): cb.yield_state(tuple(var("c" + str(i)) for i in range(1, 11)), "result", 0, "final") - code = DAGCode.create_with_steady_phase(cb.statements) + code = create_DAGCode_with_steady_phase(cb.statements) return (code, (0, 1, 0, 1, 0, 1, 1, 2, 1, 2)) @@ -331,20 +335,20 @@ def test_IfThenElse_expansion(python_method_impl): def test_arrays_and_looping(python_method_impl): - with CodeBuilder(label="primary") as cb: + with CodeBuilder(name="primary") as cb: cb("myarray", "`array`(20)") cb("myarray[i]", "i", loops=[("i", 0, 20)]) cb.yield_state("myarray[15]", "result", 0, "final") from utils import execute_and_return_single_result - code = DAGCode.create_with_steady_phase(cb.statements) + code = create_DAGCode_with_steady_phase(cb.statements) result = execute_and_return_single_result(python_method_impl, code) assert result == 15 def test_arrays_and_linalg(python_method_impl): - with CodeBuilder(label="primary") as cb: + with CodeBuilder(name="primary") as cb: cb("n", "4") cb("nodes", "`array`(n)") cb("vdm", "`array`(n*n)") @@ -369,7 +373,7 @@ def test_arrays_and_linalg(python_method_impl): from utils import execute_and_return_single_result - code = DAGCode.create_with_steady_phase(cb.statements) + code = create_DAGCode_with_steady_phase(cb.statements) result = execute_and_return_single_result(python_method_impl, code) result = result.reshape(4, 4, order="F") @@ -378,7 +382,7 @@ def test_arrays_and_linalg(python_method_impl): def test_svd(python_method_impl): - with CodeBuilder(label="primary") as cb: + with CodeBuilder(name="primary") as cb: cb("n", 3) cb("nodes", "`array`(n)") cb("vdm", "`array`(n*n)") @@ -407,7 +411,7 @@ def test_svd(python_method_impl): from utils import execute_and_return_single_result - code = DAGCode.create_with_steady_phase(cb.statements) + code = create_DAGCode_with_steady_phase(cb.statements) result = execute_and_return_single_result(python_method_impl, code) assert la.norm(result) < 1e-10 @@ -416,11 +420,11 @@ def test_svd(python_method_impl): def test_class_preamble(): from dagrt.language import CodeBuilder - with CodeBuilder(label="primary") as cb: + with CodeBuilder(name="primary") as cb: cb.assign("", " +

") cb.yield_state("f()", "f", 0, "final") - code = DAGCode.create_with_steady_phase(cb.statements) + code = create_DAGCode_with_steady_phase(cb.statements) from dagrt.codegen import PythonCodeGenerator import dagrt.function_registry as freg diff --git a/test/utils.py b/test/utils.py index a56b16f..351baac 100644 --- a/test/utils.py +++ b/test/utils.py @@ -24,6 +24,7 @@ THE SOFTWARE. """ import numpy as np # noqa +import dagrt.language as lang # {{{ things to pass for python_method_impl @@ -56,6 +57,39 @@ def execute_and_return_single_result(python_method_impl, code, initial_context={ return state_component +# {{{ create a DAGCode with a single, repeatedly executed phase + +def create_DAGCode_with_steady_phase(statements): + name = "main" + phases = [ + lang.ExecutionPhase( + name=name, + next_phase=name, + statements=statements) + ] + return lang.DAGCode.from_phases_list(phases, name) + +# }}} + + +# {{{ create a DAGCode with an "init" phase and a "main" phase + +def create_DAGCode_with_init_and_main_phases(init_statements, main_statements): + phases = [ + lang.ExecutionPhase( + name="init", + next_phase="main", + statements=init_statements), + lang.ExecutionPhase( + name="main", + next_phase="main", + statements=main_statements) + ] + return lang.DAGCode.from_phases_list(phases, "init") + +# }}} + + # {{{ low-level code building utility class RawCodeBuilder(object): -- GitLab From 21e78fe96e90c46105b89a1551127b79a57cd684 Mon Sep 17 00:00:00 2001 From: Matt Wala Date: Wed, 20 Nov 2019 19:55:20 -0600 Subject: [PATCH 6/7] flake8/pylint fixes --- dagrt/transform.py | 1 + test/test_ast.py | 2 +- test/test_builtins.py | 1 - test/test_codegen.py | 1 - test/test_codegen_fortran.py | 2 +- 5 files changed, 3 insertions(+), 4 deletions(-) diff --git a/dagrt/transform.py b/dagrt/transform.py index a6c8023..8de4a9e 100644 --- a/dagrt/transform.py +++ b/dagrt/transform.py @@ -38,6 +38,7 @@ def fuse_two_phases(phase_name, phase1, phase2): phase1.statements, phase2.statements) return ExecutionPhase( + name=phase1.name, next_phase=phase1.next_phase, statements=new_statements ) diff --git a/test/test_ast.py b/test/test_ast.py index 4e0f9b2..49dca5d 100755 --- a/test/test_ast.py +++ b/test/test_ast.py @@ -29,7 +29,7 @@ from pymbolic.primitives import LogicalNot from dagrt.codegen.dag_ast import (IfThen, IfThenElse, Block, StatementWrapper, create_ast_from_phase, simplify_ast) -from dagrt.language import Statement, DAGCode +from dagrt.language import Statement from utils import create_DAGCode_with_steady_phase diff --git a/test/test_builtins.py b/test/test_builtins.py index f4d219e..3837a82 100755 --- a/test/test_builtins.py +++ b/test/test_builtins.py @@ -28,7 +28,6 @@ import pytest import sys from dagrt.language import Assign, YieldState -from dagrt.language import DAGCode from pymbolic import var from utils import ( # noqa diff --git a/test/test_codegen.py b/test/test_codegen.py index 4f33b8d..98d5b33 100755 --- a/test/test_codegen.py +++ b/test/test_codegen.py @@ -5,7 +5,6 @@ import pytest import sys from dagrt.language import Assign, YieldState -from dagrt.language import DAGCode from dagrt.codegen import CodeGenerationError from dagrt.codegen.analysis import verify_code diff --git a/test/test_codegen_fortran.py b/test/test_codegen_fortran.py index c6fafec..166978a 100755 --- a/test/test_codegen_fortran.py +++ b/test/test_codegen_fortran.py @@ -26,7 +26,7 @@ THE SOFTWARE. import sys from dagrt.language import YieldState -from dagrt.language import DAGCode, CodeBuilder +from dagrt.language import CodeBuilder import dagrt.codegen.fortran as f from utils import RawCodeBuilder -- GitLab From eb87fbcfb97d7dff08e88961f34d67cbd26b9cae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20Kl=C3=B6ckner?= Date: Fri, 22 Nov 2019 00:17:36 +0100 Subject: [PATCH 7/7] DAGCode.from_phases_list: Complain about duplicate phase names --- dagrt/language.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dagrt/language.py b/dagrt/language.py index 17a71e7..2449707 100644 --- a/dagrt/language.py +++ b/dagrt/language.py @@ -655,6 +655,8 @@ class DAGCode(RecordWithoutPickling): def from_phases_list(cls, phases, initial_phase): name_to_phase = dict() for phase in phases: + if phase.name in name_to_phase: + raise ValueError("duplicate phase name '%s'" % phase.name) name_to_phase[phase.name] = phase return cls(name_to_phase, initial_phase) -- GitLab