Skip to content

Commit f55ae6f

Browse files
committed
Mappings that assign tasks to shards at compile time.
1 parent 2f82427 commit f55ae6f

File tree

2 files changed

+176
-0
lines changed

2 files changed

+176
-0
lines changed

Diff for: plugin/src/regent/flow_mapping.t

+172
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
-- Copyright (c) 2015-2016, Stanford University. All rights reserved.
2+
--
3+
-- This file is dual-licensed under the BSD license (shown below) and
4+
-- Apache version 2.0 license.
5+
--
6+
-- Redistribution and use in source and binary forms, with or without
7+
-- modification, are permitted provided that the following conditions
8+
-- are met:
9+
-- * Redistributions of source code must retain the above copyright
10+
-- notice, this list of conditions and the following disclaimer.
11+
-- * Redistributions in binary form must reproduce the above copyright
12+
-- notice, this list of conditions and the following disclaimer in the
13+
-- documentation and/or other materials provided with the distribution.
14+
-- * Neither the name of NVIDIA CORPORATION nor the names of its
15+
-- contributors may be used to endorse or promote products derived
16+
-- from this software without specific prior written permission.
17+
--
18+
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
19+
-- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20+
-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21+
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22+
-- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23+
-- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24+
-- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25+
-- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26+
-- OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27+
-- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28+
-- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
30+
-- Mappings that statically assign tasks to shards.
31+
32+
-- When the SPMD optimization is used with ForList loops over an index space I
33+
-- as leaves, mappings determine the assignments of indices in I to shards. A
34+
-- careful choice of mapping may reduce communication between nodes, e.g. in
35+
-- the case of a stencil code, it helps to preserve spacial locality by
36+
-- assigning to each node neighboring partitions of the entire grid.
37+
38+
-- A mapping is a function that takes an index in a structured index space
39+
-- (with one domain) and the size of the index space, and returns a "key"
40+
-- for the index. The mapping is provided to the `list_ispace` operator,
41+
-- which sorts the indices in the index space by their keys in ascending order.
42+
-- Then, indices-to-shard assignment takes place according to list's ordering
43+
-- (the first `shard_size` indices go to the first shard, etc.)
44+
45+
-- Currently, which mapping to use is controlled by the command line argument
46+
-- `flow-spmd-mapping`, which only takes integers. The mappings are
47+
-- consequently named by their integer ids starting from 1.
48+
49+
local ast = require("regent/ast")
50+
local std = require("regent/std")
51+
52+
-- WARNING: these mappings only work on 2d structured index spaces.
53+
local mappings = {}
54+
mappings[1] = terra(p : std.int2d, s : std.rect2d) : int -- Column major order.
55+
return p.__ptr.x + p.__ptr.y * s:size().__ptr.x
56+
end
57+
58+
do -- Hilbert curve.
59+
local H = 1
60+
local A = 2
61+
local B = 3
62+
local C = 4
63+
64+
local terra make_int2d(x : int, y : int) : std.int2d
65+
return std.int2d { __ptr = [std.int2d.impl_type] { x = x, y = y } }
66+
end
67+
68+
local terra h(p : std.int2d, size : int, pattern : int) : int
69+
std.assert(p.__ptr.x < size, "x out of range")
70+
std.assert(p.__ptr.y < size, "y out of range")
71+
72+
if size == 1 then
73+
return 0
74+
end
75+
76+
var half = size / 2
77+
var block = half * half
78+
79+
if pattern == H then
80+
if (p.__ptr.x<half) and (p.__ptr.y<half) then
81+
return h(p, size / 2, A)
82+
elseif (p.__ptr.x<half) and (p.__ptr.y>=half) then
83+
return block + h(p - make_int2d(0, half), size / 2, H)
84+
elseif (p.__ptr.x>=half) and (p.__ptr.y>=half) then
85+
return block * 2 + h(p - make_int2d(half, half), size / 2, H)
86+
elseif (p.__ptr.x>=half) and (p.__ptr.y<half) then
87+
return block * 3 + h(p - make_int2d(half, 0), size / 2, B)
88+
else
89+
std.assert(false, "Hilbert curve: impossible.")
90+
end
91+
elseif pattern == A then
92+
if (p.__ptr.x<half) and (p.__ptr.y<half) then
93+
return h(p, size / 2, H)
94+
elseif (p.__ptr.x>=half) and (p.__ptr.y<half) then
95+
return block + h(p - make_int2d(half, 0), size / 2, A)
96+
elseif (p.__ptr.x>=half) and (p.__ptr.y>=half) then
97+
return block * 2 + h(p - make_int2d(half, half), size / 2, A)
98+
elseif (p.__ptr.x<half) and (p.__ptr.y>=half) then
99+
return block * 3 + h(p - make_int2d(0, half), size / 2, C)
100+
else
101+
std.assert(false, "Hilbert curve: impossible.")
102+
end
103+
elseif pattern == B then
104+
if (p.__ptr.x>=half) and (p.__ptr.y>=half) then
105+
return h(p - make_int2d(half, half), size / 2, C)
106+
elseif (p.__ptr.x<half) and (p.__ptr.y>=half) then
107+
return block + h(p - make_int2d(0, half), size / 2, B)
108+
elseif (p.__ptr.x<half) and (p.__ptr.y<half) then
109+
return block * 2 + h(p, size / 2, B)
110+
elseif (p.__ptr.x>=half) and (p.__ptr.y<half) then
111+
return block * 3 + h(p - make_int2d(half, 0), size / 2, H)
112+
else
113+
std.assert(false, "Hilbert curve: impossible.")
114+
end
115+
elseif pattern == C then
116+
if (p.__ptr.x>=half) and (p.__ptr.y>=half) then
117+
return h(p - make_int2d(half, half), size / 2, B)
118+
elseif (p.__ptr.x>=half) and (p.__ptr.y<half) then
119+
return block + h(p - make_int2d(half, 0), size / 2, C)
120+
elseif (p.__ptr.x<half) and (p.__ptr.y<half) then
121+
return block * 2 + h(p, size / 2, C)
122+
elseif (p.__ptr.x<half) and (p.__ptr.y>=half) then
123+
return block * 3 + h(p - make_int2d(0, half), size / 2, A)
124+
else
125+
std.assert(false, "Hilbert curve: impossible.")
126+
end
127+
else
128+
std.assert(false, "Hilbert curve: unknown pattern.")
129+
end
130+
end
131+
132+
mappings[2] = terra(p : std.int2d, s : std.rect2d) : int
133+
var size = s:size()
134+
if size.__ptr.x == 2 * size.__ptr.y then
135+
-- Special case for when x == 2*y and y is a power of 2.
136+
var half = size.__ptr.y
137+
if (p - s.lo).__ptr.x < half then
138+
return h(p - s.lo, half, H)
139+
else
140+
return h(p - s.lo - make_int2d(half, 0), half, H) + half * half
141+
end
142+
end
143+
144+
std.assert(size.__ptr.x == size.__ptr.y, "Hilbert curve: plane should be square.")
145+
std.assert((size.__ptr.x and (size.__ptr.x - 1)) == 0, "Hilbert curve: size should be power of two.")
146+
return h(p - s.lo, size.__ptr.x, H)
147+
end
148+
end
149+
150+
mappings[3] = terra(p : std.int2d, s : std.rect2d) : int -- Random shuffle.
151+
return [std.c.rand]()
152+
end
153+
154+
local spmd_mapping, spmd_mapping_key_type = false, false
155+
local mapping_id = std.config["flow-spmd-mapping"]
156+
if mapping_id > 0 then
157+
if mappings[mapping_id] then
158+
local mapping_fn = mappings[mapping_id]
159+
spmd_mapping = ast.typed.expr.Function {
160+
value = mapping_fn,
161+
expr_type = mapping_fn.type,
162+
annotations = ast.default_annotations(),
163+
span = ast.trivial_span(),
164+
}
165+
spmd_mapping_key_type = mapping_fn.returntype
166+
else
167+
error("flow_mappings: mapping " .. mapping_id .. " does not exist.")
168+
end
169+
end
170+
171+
-- Exports the chosen mapping.
172+
return { fn = spmd_mapping, key_type = spmd_mapping_key_type}

Diff for: plugin/src/regent/flow_spmd.t

+4
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ local report = require("common/report")
5050
local std = require("regent/std")
5151
local vectorize_loops = require("regent/vectorize_loops")
5252

53+
local spmd_mapping = require("regent/flow_mapping")
54+
5355
-- Configuration Variables
5456

5557
-- Setting this flag configures the number of SPMD tasks assigned to
@@ -5049,6 +5051,8 @@ local function issue_global_vars_creation_forlist(cx, loop_nid, nparts_nid,
50495051
values = terralib.newlist({
50505052
ast.typed.expr.ListIspace {
50515053
ispace = bound_label.value,
5054+
mapping = spmd_mapping.fn,
5055+
key_type = spmd_mapping.key_type,
50525056
expr_type = part_indices_type,
50535057
annotations = ast.default_annotations(),
50545058
span = span,

0 commit comments

Comments
 (0)