Skip to content
Browse files

Modified tree connection compression to handle trees with arbirtary d…

…egree and

added a quad-tree example as a test case.
  • Loading branch information...
1 parent 55de1ba commit 7fd6d4a0c783d6bcd317820cab83a2220e33cacc @jameshanlon jameshanlon committed Jan 26, 2012
Showing with 109 additions and 30 deletions.
  1. +48 −30 compiler/insertconns.py
  2. +60 −0 test/examples/quadtree.sire
  3. +1 −0 test/xs1/tests.py
View
78 compiler/insertconns.py
@@ -147,12 +147,12 @@ def create_range_conn(s, chan, i_elem, group):
self.connect_type(chan, master))
return ast.StmtIf(cond, conn, s) if s else conn
- def create_tree_conn(tab, scope, chan, phase, base_indices_value,
+ def create_tree_conn(tab, scope, chan, phase, group_size, base_indices_value,
loc_base, loc_diff, connid_min, connid_offset, connid_diff, i_elem):
location = ast.ExprBinop('-', i_elem,
ast.ExprSingle(ast.ElemNumber(base_indices_value)))
location = ast.ExprBinop('/', ast.ElemGroup(location),
- ast.ExprSingle(ast.ElemNumber(2)))
+ ast.ExprSingle(ast.ElemNumber(group_size)))
location = ast.ExprBinop('*', ast.ElemNumber(loc_diff),
ast.ExprSingle(ast.ElemGroup(location)))
location = ast.ExprBinop('+', ast.ElemNumber(loc_base),
@@ -161,10 +161,12 @@ def create_tree_conn(tab, scope, chan, phase, base_indices_value,
chanend.symbol = Symbol(chan.chanend, self.chanend_type(chan),
None, scope=T_SCOPE_PROC)
elem0 = chan.elems[phase]
- connid = ast.ExprBinop('+', i_elem,
- ast.ExprSingle(ast.ElemNumber(connid_offset)))
+ #connid = ast.ExprBinop('+', i_elem,
+ # ast.ExprSingle(ast.ElemNumber(connid_offset)))
+ connid = ast.ExprBinop('-', i_elem,
+ ast.ExprSingle(ast.ElemNumber(phase)))
connid = ast.ExprBinop('rem', ast.ElemGroup(connid),
- ast.ExprSingle(ast.ElemNumber(2)))
+ ast.ExprSingle(ast.ElemNumber(group_size)))
connid = ast.ExprBinop('*', ast.ElemGroup(connid),
ast.ExprSingle(ast.ElemNumber(connid_diff)))
connid = ast.ExprBinop('+', ast.ElemGroup(connid),
@@ -235,6 +237,8 @@ def conn_diff_groups(chan, s, i_elem, d=DEBUG_COMPRESSION):
if len(groups) == len(chan.elems):
debug(d, 'Aborting group diff compression.')
return None
+
+ debug(d, 'Diff compression successful.')
# Construct connection syntax
s = None
@@ -249,7 +253,8 @@ def conn_diff_groups(chan, s, i_elem, d=DEBUG_COMPRESSION):
def conn_tree_groups(chan, s, i_elem, d=DEBUG_COMPRESSION):
"""
Compress connections based on monotonically increasing or decreasing
- sets with the same target destination. Assume sets are of size 2.
+ sets with the same target destination. Within a set, connection IDs can
+ be monotonically increasing or decreasing.
"""
locs = []
debug(d, 'Locations:')
@@ -258,20 +263,25 @@ def conn_tree_groups(chan, s, i_elem, d=DEBUG_COMPRESSION):
locs.append((x, loc))
debug(d, ' {:>4} : {}[{}] -> {}'.format(x.indices_value, chan.name, x.index, loc))
- # Only consider more than three conditions
- if len(locs) <= 3:
- debug(d, 'Aborting tree compression.')
- return None
-
# Separate the first odd element if there is one
phase = 0
if locs[0][1] != locs[1][1]:
odd_elem = locs[0][0]
locs = locs[1:]
phase = 1
+ # Count the group size
+ group_size = 1
+ while group_size < len(locs) and locs[group_size-1][1] == locs[group_size][1]:
+ group_size += 1
+
+ # Only consider connections with more than one group
+ if len(locs) <= group_size+1:
+ debug(d, 'Aborting tree compression.')
+ return None
+
# Set parameters
- loc_diff = locs[2][1]-locs[1][1]
+ loc_diff = locs[group_size][1]-locs[group_size-1][1]
loc_base = locs[0][1]
base_indices_value = locs[0][0].indices_value
connidA = tab.lookup_connid(chan.name, locs[0][0].index, scope)
@@ -282,25 +292,29 @@ def conn_tree_groups(chan, s, i_elem, d=DEBUG_COMPRESSION):
# Print some debug info
debug(d, 'Attempting tree compression.')
+ debug(d, ' Group size: {}'.format(group_size))
debug(d, ' Location base: {}'.format(loc_base))
debug(d, ' Location diff: {}'.format(loc_diff))
debug(d, ' Base ival: {}'.format(base_indices_value))
debug(d, ' ConnID base: {}'.format(connidA))
debug(d, ' ConnID diff: {}'.format(connid_diff))
- # Check each pair
- end = 1+(math.floor((len(locs)-1)/2)*2)
- debug(d, 'Checking pairs 1 to {}'.format(end))
- for (x, y) in zip(locs[:-1:2], locs[1::2]):
- debug(d, ' {} and {}'.format(y[1], x[1]))
- if x[1] != y[1]:
- debug(d, 'Aborting tree compression.')
- return None
+ # Check each group contains the same location
+ debug(d, 'Checking groups...')
+ i = 0
+ while i*group_size < len(locs):
+ debug(d, ' Group {}'.format(i))
+ for j in range(1, group_size):
+ if locs[i*group_size][1] != locs[(i*group_size)+j][1]:
+ debug(d, 'Aborting tree compression.')
+ return None
+ i += 1
- # Check each step between pairs
- debug(d, 'Checking diffs 1 to {}'.format(end))
- for (x, y) in zip(locs[1::2], locs[2::2]):
- debug(d, ' {} and {}'.format(y[1], x[1]))
+ # Check each step between groups has same location and connection diffs
+ debug(d, 'Checking diffs...')
+ for (i, (x, y)) in enumerate(
+ zip(locs[1::group_size], locs[group_size::group_size])):
+ debug(d, ' Group {} and {}: {} and {}'.format(i, i+1, y[1], x[1]))
connidX = tab.lookup_connid(chan.name, x[0].index, scope)
connidY = tab.lookup_connid(chan.name, y[0].index, scope)
connid_diff_ = connidX - connidY
@@ -309,29 +323,33 @@ def conn_tree_groups(chan, s, i_elem, d=DEBUG_COMPRESSION):
return None
# Check matching computed location
- debug(d, 'Matching form, checking computed:')
+ debug(d, 'Checking computed...')
+ debug(d, 'connid_min = {}'.format(connid_min))
+ debug(d, 'connid_off = {}'.format(connid_offset))
if phase == 1:
connid = tab.lookup_connid(chan.name, odd_elem.index, scope)
debug(d, ' {}: connid={}'.format(odd_elem.indices_value, connid))
for (elem, loc) in locs:
computed_loc = loc_base + (loc_diff * (math.floor(
- ((elem.indices_value - base_indices_value))/2)))
+ ((elem.indices_value - base_indices_value))/group_size)))
connid = tab.lookup_connid(chan.name, elem.index, scope)
- computed_connid = (connid_min +
- ((elem.indices_value + connid_offset) % 2) * connid_diff)
+ #computed_connid = (connid_min + ((elem.indices_value + connid_offset) % group_size) * connid_diff)
+ computed_connid = (connid_min + ((elem.indices_value - phase) % group_size) * connid_diff)
debug(d, ' {}: connid={}, loc={} computed({}, {})'
.format(elem.indices_value, connid, loc,
computed_connid, computed_loc))
assert computed_loc == loc
assert computed_connid == connid
+
+ debug(d, 'Tree compression successful.')
# Construct connection syntax
if phase == 0:
- return create_tree_conn(tab, scope, chan, phase,
+ return create_tree_conn(tab, scope, chan, phase, group_size,
base_indices_value, loc_base, loc_diff,
connid_min, connid_offset, connid_diff, i_elem)
else:
- s = create_tree_conn(tab, scope, chan, phase,
+ s = create_tree_conn(tab, scope, chan, phase, group_size,
base_indices_value, loc_base, loc_diff,
connid_min, connid_offset, connid_diff, i_elem)
return create_single_conn(s, chan, scope, i_elem, odd_elem)
View
60 test/examples/quadtree.sire
@@ -0,0 +1,60 @@
+val DEGREE is 4;
+val LEAVES is 16;
+val BRANCHES is LEAVES/(DEGREE-1);
+
+% Send a token down, then sum values up.
+proc branch(chanend root,
+ chanend c0,
+ chanend c1,
+ chanend c2,
+ chanend c3) is
+{ var a;
+ var b;
+ var c;
+ var d;
+ var v;
+
+ root ? v;
+ assert v = 0;
+
+ % Down
+ c0 ! v;
+ c1 ! v;
+ c2 ! v;
+ c3 ! v;
+
+ % Up
+ c0 ? a;
+ c1 ? b;
+ c2 ? c;
+ c3 ? d;
+
+ root ! a+b+c+d
+}
+
+% Receive a token and send back a 1.
+proc leaf(chanend c) is
+{ var v;
+ c ? v;
+ assert v = 0;
+ c ! 1
+}
+
+proc main() is
+{ chan c[BRANCHES+LEAVES];
+ var v;
+ var i;
+ { c[0] ! 0;
+ c[0] ? v;
+ assert v = LEAVES
+ } ||
+ par i in [0 for LEAVES] do
+ leaf(c[BRANCHES + i]) ||
+ par i in [0 for BRANCHES] do
+ branch(c[i],
+ c[(DEGREE*i)+1],
+ c[(DEGREE*i)+2],
+ c[(DEGREE*i)+3],
+ c[(DEGREE*i)+4])
+}
+
View
1 test/xs1/tests.py
@@ -55,6 +55,7 @@
Test('array2d_composite', [16], p=[('N','2')]),
Test('tree', [4], p=[('D','1')]),
Test('tree', [16], p=[('D','2')]),
+ Test('quadtree', [22]),
Test('cube2d', [4]),
Test('cube3d', [16]),
Test('distributed-array', [5], p=[('N', '4')]),

0 comments on commit 7fd6d4a

Please sign in to comment.
Something went wrong with that request. Please try again.