def test_fusetrans_error_not_same_parent(): ''' Check that we reject attempts to fuse loops which don't share the same parent ''' from psyclone.psyGen import Loop, Schedule, Literal from psyclone.transformations import LoopFuseTrans, TransformationError sch1 = Schedule() sch2 = Schedule() loop1 = Loop(variable_name="i", parent=sch1) loop2 = Loop(variable_name="j", parent=sch2) sch1.addchild(loop1) sch2.addchild(loop2) loop1.addchild(Literal("1", parent=loop1)) # start loop1.addchild(Literal("10", parent=loop1)) # stop loop1.addchild(Literal("1", parent=loop1)) # step loop1.addchild(Schedule(parent=loop1)) # loop body loop2.addchild(Literal("1", parent=loop2)) # start loop2.addchild(Literal("10", parent=loop2)) # stop loop2.addchild(Literal("1", parent=loop2)) # step loop2.addchild(Schedule(parent=loop2)) # loop body fuse = LoopFuseTrans() # Try to fuse loops with different parents with pytest.raises(TransformationError) as err: fuse.validate(loop1, loop2) assert "Error in LoopFuse transformation. Loops do not have the " \ "same parent" in str(err.value)
def test_fusetrans_error_incomplete(): ''' Check that we reject attempts to fuse loops which are incomplete. ''' from psyclone.psyGen import Loop, Schedule, Literal, Return from psyclone.transformations import LoopFuseTrans, TransformationError sch = Schedule() loop1 = Loop(variable_name="i", parent=sch) loop2 = Loop(variable_name="j", parent=sch) sch.addchild(loop1) sch.addchild(loop2) fuse = LoopFuseTrans() # Check first loop with pytest.raises(TransformationError) as err: fuse.validate(loop1, loop2) assert "Error in LoopFuse transformation. The first loop does not have " \ "4 children." in str(err.value) loop1.addchild(Literal("start", parent=loop1)) loop1.addchild(Literal("stop", parent=loop1)) loop1.addchild(Literal("step", parent=loop1)) loop1.addchild(Schedule(parent=loop1)) loop1.loop_body.addchild(Return(parent=loop1.loop_body)) # Check second loop with pytest.raises(TransformationError) as err: fuse.validate(loop1, loop2) assert "Error in LoopFuse transformation. The second loop does not have " \ "4 children." in str(err.value) loop2.addchild(Literal("start", parent=loop2)) loop2.addchild(Literal("stop", parent=loop2)) loop2.addchild(Literal("step", parent=loop2)) loop2.addchild(Schedule(parent=loop2)) loop2.loop_body.addchild(Return(parent=loop2.loop_body)) # Validation should now pass fuse.validate(loop1, loop2)
def test_profile_basic(capsys): '''Check basic functionality: node names, schedule view. ''' from psyclone.psyGen import colored, SCHEDULE_COLOUR_MAP Profiler.set_options([Profiler.INVOKES]) _, invoke = get_invoke("test11_different_iterates_over_one_invoke.f90", "gocean1.0", idx=0) assert isinstance(invoke.schedule.children[0], ProfileNode) invoke.schedule.view() out, _ = capsys.readouterr() gsched = colored("GOInvokeSchedule", SCHEDULE_COLOUR_MAP["Schedule"]) loop = Loop().coloured_text profile = invoke.schedule.children[0].coloured_text # Do one test based on schedule view, to make sure colouring # and indentation is correct expected = (gsched + "[invoke='invoke_0', Constant loop bounds=True]\n" " " + profile + "\n" " " + loop + "[type='outer', field_space='go_cv', " "it_space='go_internal_pts']\n") assert expected in out prt = ProfileRegionTrans() # Insert a profile call between outer and inner loop. # This tests that we find the subroutine node even # if it is not the immediate parent. new_sched, _ = prt.apply( invoke.schedule.children[0].children[0].children[0]) new_sched_str = str(new_sched) correct = ("""GOInvokeSchedule(Constant loop bounds=True): ProfileStart[var=profile] GOLoop[id:'', variable:'j', loop_type:'outer'] Literal[value:'2'] Literal[value:'jstop-1'] Literal[value:'1'] Schedule: GOLoop[id:'', variable:'i', loop_type:'inner'] Literal[value:'2'] Literal[value:'istop'] Literal[value:'1'] Schedule: kern call: compute_cv_code End Schedule End GOLoop End Schedule End GOLoop GOLoop[id:'', variable:'j', loop_type:'outer'] Literal[value:'1'] Literal[value:'jstop+1'] Literal[value:'1'] Schedule: GOLoop[id:'', variable:'i', loop_type:'inner'] Literal[value:'1'] Literal[value:'istop+1'] Literal[value:'1'] Schedule: kern call: bc_ssh_code End Schedule End GOLoop End Schedule End GOLoop ProfileEnd End Schedule""") assert correct in new_sched_str Profiler.set_options(None)
def test_psy_data_trans_basic(capsys): '''Check basic functionality: node names, schedule view. ''' _, invoke = get_invoke("test11_different_iterates_over_one_invoke.f90", "gocean1.0", idx=0, dist_mem=False) schedule = invoke.schedule # This test expects constant loop bounds schedule._const_loop_bounds = True data_trans = PSyDataTrans() assert "Create a sub-tree of the PSyIR that has a node of type " \ "PSyDataNode at its root" in str(data_trans) assert data_trans.name == "PSyDataTrans" data_trans.apply(schedule) assert isinstance(invoke.schedule[0], PSyDataNode) schedule.view() out, _ = capsys.readouterr() gsched = colored("GOInvokeSchedule", GOInvokeSchedule._colour) sched = colored("Schedule", Schedule._colour) loop = Loop().coloured_name(True) data = invoke.schedule[0].coloured_name(True) # Do one test based on schedule view, to make sure colouring # and indentation is correct expected = (gsched + "[invoke='invoke_0', Constant loop bounds=True]\n" " 0: " + data + "[]\n" " " + sched + "[]\n" " 0: " + loop + "[type='outer', field_space='go_cv', " "it_space='go_internal_pts']\n") assert expected in out # Insert a DataTrans call between outer and inner loop. # This tests that we find the subroutine node even # if it is not the immediate parent. data_trans.apply(invoke.schedule[0].psy_data_body[0].loop_body[0]) new_sched_str = str(invoke.schedule) correct = ("""GOInvokeSchedule[invoke='invoke_0', \ Constant loop bounds=True]: PSyDataStart[var=psy_data] GOLoop[id:'', variable:'j', loop_type:'outer'] Literal[value:'2', Scalar<INTEGER, UNDEFINED>] Literal[value:'jstop-1', Scalar<INTEGER, UNDEFINED>] Literal[value:'1', Scalar<INTEGER, UNDEFINED>] Schedule: PSyDataStart[var=psy_data_1] GOLoop[id:'', variable:'i', loop_type:'inner'] Literal[value:'2', Scalar<INTEGER, UNDEFINED>] Literal[value:'istop', Scalar<INTEGER, UNDEFINED>] Literal[value:'1', Scalar<INTEGER, UNDEFINED>] Schedule: kern call: compute_cv_code End Schedule End GOLoop PSyDataEnd[var=psy_data_1] End Schedule End GOLoop GOLoop[id:'', variable:'j', loop_type:'outer'] Literal[value:'1', Scalar<INTEGER, UNDEFINED>] Literal[value:'jstop+1', Scalar<INTEGER, UNDEFINED>] Literal[value:'1', Scalar<INTEGER, UNDEFINED>] Schedule: GOLoop[id:'', variable:'i', loop_type:'inner'] Literal[value:'1', Scalar<INTEGER, UNDEFINED>] Literal[value:'istop+1', Scalar<INTEGER, UNDEFINED>] Literal[value:'1', Scalar<INTEGER, UNDEFINED>] Schedule: kern call: bc_ssh_code End Schedule End GOLoop End Schedule End GOLoop PSyDataEnd[var=psy_data] End Schedule""") assert correct in new_sched_str
def test_profile_basic(capsys): '''Check basic functionality: node names, schedule view. ''' Profiler.set_options([Profiler.INVOKES]) _, invoke = get_invoke("test11_different_iterates_over_one_invoke.f90", "gocean1.0", idx=0) assert isinstance(invoke.schedule.children[0], ProfileNode) invoke.schedule.view() out, _ = capsys.readouterr() coloured_schedule = GOSchedule([]).coloured_text coloured_loop = Loop().coloured_text coloured_kern = GOKern().coloured_text coloured_profile = invoke.schedule.children[0].coloured_text # Do one test based on schedule view, to make sure colouring # and indentation is correct correct = ( '''{0}[invoke='invoke_0',Constant loop bounds=True] {3} {1}[type='outer',field_space='go_cv',it_space='go_internal_pts'] {1}[type='inner',field_space='go_cv',it_space='go_internal_pts'] {2} compute_cv_code(cv_fld,p_fld,v_fld) ''' '''[module_inline=False] {1}[type='outer',field_space='go_ct',it_space='go_all_pts'] {1}[type='inner',field_space='go_ct',it_space='go_all_pts'] {2} bc_ssh_code(ncycle,p_fld,tmask) ''' '''[module_inline=False]'''.format(coloured_schedule, coloured_loop, coloured_kern, coloured_profile) ) assert correct in out prt = ProfileRegionTrans() # Insert a profile call between outer and inner loop. # This tests that we find the subroutine node even # if it is not the immediate parent. new_sched, _ = prt.apply(invoke.schedule.children[0] .children[0].children[0]) new_sched_str = str(new_sched) correct = ("""GOSchedule(Constant loop bounds=True): ProfileStart[var=profile] Loop[]: j= lower=2,jstop-1,1 ProfileStart[var=profile_1] Loop[]: i= lower=2,istop,1 kern call: compute_cv_code EndLoop ProfileEnd EndLoop Loop[]: j= lower=1,jstop+1,1 Loop[]: i= lower=1,istop+1,1 kern call: bc_ssh_code EndLoop EndLoop ProfileEnd End Schedule""") assert correct in new_sched_str Profiler.set_options(None)