Skip to content

Commit 2b018ec

Browse files
BoundedFanout k tiling
1 parent 260747c commit 2b018ec

7 files changed

Lines changed: 446 additions & 3 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
dist-newstyle/
22
cabal.project.local
3+
plans/
34
*.hi
45
*.o
56
*.dyn_hi

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ the first non-singleton dimension, producing a balanced binary tree. Both
5454
implement `Tiling`; `Tile.Tree.contractAnchors` derives the hop tree by
5555
contracting anchor edges.
5656

57+
`BoundedFanout k` treats fan-out as a tiling policy. It keeps child tiles
58+
affine rectangles while ensuring the hop tree exposes at most `k` immediate
59+
communication children whenever `k` is at least the local geometric minimum.
60+
If `k` is below that rectangular minimum, the tiler uses the minimum lawful
61+
fan-out instead.
62+
5763
## Tree
5864

5965
Communication structure is materialized as trees.
@@ -98,4 +104,6 @@ events used by the demo.
98104

99105
The design is explained in [Structured Multicast via Affine Tiling](article/routing-foundations.md).
100106

107+
Bounded fan-out is described in [Bounded Fan-Out Tiling](article/bounded-fanout.md).
108+
101109
The correctness contract is stated in [Cast Routing Correctness via Affine Tiling](article/routing-theorems.md).

app/Main.hs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ main = do
1010
shape = [2, 4]
1111

1212
tiling = BlockPartitioning
13+
bounded = BoundedFanout 2
1314
bisection = Bisection
1415

1516
schedule = buildSchedule BFS tiling members shape
@@ -28,6 +29,7 @@ main = do
2829
]
2930

3031
full = rootTile shape
32+
wide = rootTile [1, 8]
3133
occE = Occlusion (== "E")
3234
jaggedEnvelope = rootTile [3, 3]
3335
jaggedOcclusion = Occlusion (`elem` ["F", "H", "I"])
@@ -62,6 +64,15 @@ main = do
6264
putStrLn "\nbisection send tree:"
6365
putStr (renderSendTree members (sendTree bisection full))
6466

67+
putStrLn "\nwide block-partitioned send tree:"
68+
putStr (renderSendTree members (sendTree tiling wide))
69+
70+
putStrLn "\nwide bounded-fanout-2 send tree:"
71+
putStr (renderSendTree members (sendTree bounded wide))
72+
73+
putStrLn "\nwide bisection send tree:"
74+
putStr (renderSendTree members (sendTree bisection wide))
75+
6576
putStrLn "\nblock-partitioned broadcast schedule:"
6677
print schedule
6778

article/bounded-fanout.md

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
# Bounded Fan-Out Tiling
2+
3+
`BlockPartitioning` is latency-oriented. It decomposes one dimension at a time
4+
and gives a shallow communication tree, but the local fan-out can be large.
5+
6+
For a `1 x 8` tile:
7+
8+
```text
9+
A B C D E F G H
10+
```
11+
12+
block partitioning asks `A` to send directly to every other member:
13+
14+
```text
15+
A
16+
├─ B
17+
├─ C
18+
├─ D
19+
├─ E
20+
├─ F
21+
├─ G
22+
└─ H
23+
```
24+
25+
`Bisection` is a low-fan-out reference point. It keeps local branching small
26+
by making the tree deeper:
27+
28+
```text
29+
A
30+
├─ E
31+
│ ├─ G
32+
│ │ └─ H
33+
│ └─ F
34+
├─ C
35+
│ └─ D
36+
└─ B
37+
```
38+
39+
`BoundedFanout k` exposes this tradeoff as a tiling parameter.
40+
41+
Large `k` gives shallow, block-partitioning-like schedules. Small feasible `k`
42+
gives deeper, bisection-like schedules with lower local fan-out. The
43+
interpolation is behavioral rather than structural: `BoundedFanout` computes a
44+
local rectangular frontier, while `BlockPartitioning` and `Bisection` use
45+
different decomposition shapes.
46+
47+
## Geometric Minimum
48+
49+
The fan-out cap is constrained by geometry.
50+
51+
With affine rectangular child tiles and a corner root, each active dimension
52+
contributes one necessary frontier region away from the root. The minimum
53+
lawful fan-out is therefore:
54+
55+
```haskell
56+
minimumFanout tile =
57+
length [n | n <- sizes (space tile), n > 1]
58+
```
59+
60+
For:
61+
62+
```text
63+
A B
64+
C D
65+
```
66+
67+
the root is `A`. The non-root ranks separate into two necessary rectangular
68+
frontier pieces:
69+
70+
```text
71+
[B]
72+
[C D]
73+
```
74+
75+
There is no single affine rectangle covering `B C D` while excluding `A`.
76+
Using one child would require either a jagged region, a child containing the
77+
root, or an incomplete cover.
78+
79+
So:
80+
81+
```text
82+
[4] minimumFanout = 1
83+
[2,2] minimumFanout = 2
84+
[2,2,2] minimumFanout = 3
85+
```
86+
87+
`BoundedFanout k` respects the requested cap when geometry permits it. If the
88+
requested cap is below the rectangular minimum, the tiler uses the geometric
89+
minimum instead:
90+
91+
```haskell
92+
effectiveFanout tile k =
93+
max k (minimumFanout tile)
94+
```
95+
96+
The core law is:
97+
98+
```haskell
99+
length (children (BoundedFanout k) tile)
100+
<= effectiveFanout tile k
101+
```
102+
103+
and when the requested cap is feasible:
104+
105+
```haskell
106+
minimumFanout tile <= k
107+
==> length (children (BoundedFanout k) tile) <= k
108+
```
109+
110+
The fallback is local. A high-dimensional root may require more than the
111+
requested cap, but interior tiles often have fewer active dimensions after
112+
earlier splits. At those interior tiles, the requested cap is honored again.
113+
114+
## Relations
115+
116+
A tiling returns structural children as `TileNode`s. Each child has a
117+
`Relation` to its parent:
118+
119+
```haskell
120+
data Relation
121+
= Root
122+
| Anchor Split
123+
| Sibling Split
124+
```
125+
126+
A `Sibling` has a distinct root and becomes a communication child. An `Anchor`
127+
preserves the parent root. The tree layer derives the hop tree by contracting
128+
anchor edges.
129+
130+
`BlockPartitioning` uses anchors recursively:
131+
132+
```text
133+
parent
134+
├─ sibling for dim 0
135+
└─ anchor for dim 0
136+
├─ sibling for dim 1
137+
└─ anchor for dim 1
138+
```
139+
140+
Here anchors are load-bearing for decomposition: later dimensions are
141+
discovered by recursively decomposing the anchor.
142+
143+
`BoundedFanout` uses the same relation algebra without modification:
144+
145+
```text
146+
parent
147+
├─ sibling frontier for dim 0
148+
├─ sibling frontier for dim 1
149+
└─ anchor root point
150+
```
151+
152+
The anchor is terminal. It exists to preserve structural cover of the parent
153+
tile, not to discover more communication children.
154+
155+
This is why the same `contractAnchors` operation works for both tilers:
156+
157+
- for `BlockPartitioning`, it removes recursive anchors and promotes later
158+
siblings;
159+
- for `BoundedFanout`, it removes only the singleton root anchor, leaving the
160+
already-computed bounded frontier.
161+
162+
So `Relation` is not a block-partitioning artifact. It is the vocabulary that
163+
separates structural cover from communication.
164+
165+
## Local Frontier
166+
167+
`BoundedFanout` keeps the rectangular affine model.
168+
169+
It does not introduce jagged regions, and it does not patch fan-out in the
170+
scheduler. The tiler computes the full local frontier in one decomposition
171+
step.
172+
173+
For active dimensions `d0`, `d1`, and `d2`, the frontier is:
174+
175+
```text
176+
d0 away from root
177+
d0 anchored, d1 away from root
178+
d0 anchored, d1 anchored, d2 away from root
179+
```
180+
181+
The remaining root point is a terminal anchor. Since that anchor has no
182+
children, anchor contraction cannot promote additional communication nodes into
183+
the hop frontier.
184+
185+
For `BoundedFanout 2` over `1 x 8`, the first hop is:
186+
187+
```text
188+
[B C D E]
189+
[F G H]
190+
```
191+
192+
and the send tree is:
193+
194+
```text
195+
A
196+
├─ B
197+
│ ├─ C
198+
│ │ └─ D
199+
│ └─ E
200+
└─ F
201+
├─ G
202+
└─ H
203+
```
204+
205+
The root fan-out is bounded by `2`, and the depth increases accordingly.
206+
207+
## Interpretation
208+
209+
The tradeoff now lives in the tiling algebra:
210+
211+
```text
212+
BlockPartitioning
213+
shallow, potentially high fan-out
214+
215+
Bisection
216+
low-fan-out reference point
217+
218+
BoundedFanout k
219+
tunable fan-out/depth tradeoff
220+
```
221+
222+
The schedule and executor do not need special cases. They read the hop tree
223+
produced by the tiler.
224+

0 commit comments

Comments
 (0)