Skip to content

Commit 25a33d4

Browse files
committed
test lp.distribute_loops
1 parent 98aeedf commit 25a33d4

File tree

1 file changed

+256
-0
lines changed

1 file changed

+256
-0
lines changed

test/test_loop_distribution.py

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
__copyright__ = "Copyright (C) 2021 Kaushik Kulkarni"
2+
3+
__license__ = """
4+
Permission is hereby granted, free of charge, to any person obtaining a copy
5+
of this software and associated documentation files (the "Software"), to deal
6+
in the Software without restriction, including without limitation the rights
7+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
copies of the Software, and to permit persons to whom the Software is
9+
furnished to do so, subject to the following conditions:
10+
11+
The above copyright notice and this permission notice shall be included in
12+
all copies or substantial portions of the Software.
13+
14+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20+
THE SOFTWARE.
21+
"""
22+
23+
import sys
24+
import numpy as np
25+
import pyopencl as cl
26+
import loopy as lp
27+
from loopy.transform.loop_distribution import IllegalLoopDistributionError
28+
import pytest
29+
30+
import logging
31+
logger = logging.getLogger(__name__)
32+
33+
try:
34+
import faulthandler
35+
except ImportError:
36+
pass
37+
else:
38+
faulthandler.enable()
39+
40+
from pyopencl.tools import pytest_generate_tests_for_pyopencl \
41+
as pytest_generate_tests
42+
43+
from loopy.version import LOOPY_USE_LANGUAGE_VERSION_2018_2 # noqa
44+
45+
__all__ = [
46+
"pytest_generate_tests",
47+
"cl" # "cl.create_some_context"
48+
]
49+
50+
51+
def test_hello_loop_distribution(ctx_factory):
52+
ctx = ctx_factory()
53+
54+
t_unit = lp.make_kernel(
55+
"{[i,j]: 0<=i, j<10}",
56+
"""
57+
for i
58+
a[i] = 10 {id=w_a}
59+
for j
60+
b[i, j] = j*a[i] {id=w_b}
61+
end
62+
c[i] = 2*b[i, 5] {id=w_c}
63+
end
64+
""",
65+
seq_dependencies=True)
66+
67+
ref_t_unit = t_unit
68+
69+
knl = lp.distribute_loops(t_unit.default_entrypoint,
70+
insn_match="id:w_b",
71+
outer_inames=frozenset())
72+
t_unit = t_unit.with_kernel(knl)
73+
assert not (knl.id_to_insn["w_a"].within_inames
74+
& knl.id_to_insn["w_b"].within_inames)
75+
assert not (knl.id_to_insn["w_c"].within_inames
76+
& knl.id_to_insn["w_b"].within_inames)
77+
assert not (knl.id_to_insn["w_a"].within_inames
78+
& knl.id_to_insn["w_c"].within_inames)
79+
80+
lp.auto_test_vs_ref(ref_t_unit, ctx, t_unit)
81+
82+
83+
def test_soundness_check(ctx_factory):
84+
ctx = ctx_factory()
85+
86+
# {{{ WAW deps
87+
88+
tunit = lp.make_kernel(
89+
"{[i]: 1<=i<10}",
90+
"""
91+
a[i] = i {id=first_w_a}
92+
a[i-1] = i**2 {id=second_w_a, dep=first_w_a}
93+
"""
94+
)
95+
ref_tunit = tunit
96+
97+
knl = lp.distribute_loops(tunit.default_entrypoint,
98+
"id:second_w_a",
99+
outer_inames=frozenset())
100+
tunit = tunit.with_kernel(knl)
101+
assert not (knl.id_to_insn["first_w_a"].within_inames
102+
& knl.id_to_insn["second_w_a"].within_inames)
103+
lp.auto_test_vs_ref(ref_tunit, ctx, tunit)
104+
105+
tunit = lp.make_kernel(
106+
"{[i]: 0<=i<10}",
107+
"""
108+
a[i] = i {id=first_w_a}
109+
a[i+1] = i**2 {id=second_w_a, dep=first_w_a}
110+
"""
111+
)
112+
113+
with pytest.raises(IllegalLoopDistributionError):
114+
lp.distribute_loops(tunit.default_entrypoint,
115+
"id:second_w_a",
116+
outer_inames=frozenset())
117+
118+
# }}}
119+
120+
# {{{ RAW deps
121+
122+
tunit = lp.make_kernel(
123+
"{[i]: 1<=i<10}",
124+
"""
125+
b[0] = 0 {id=first_w_b}
126+
a[i] = i {id=first_w_a}
127+
b[i] = 2*a[i-1] {id=second_w_b}
128+
""",
129+
seq_dependencies=True,
130+
)
131+
ref_tunit = tunit
132+
133+
knl = lp.distribute_loops(tunit.default_entrypoint,
134+
"id:second_w_b",
135+
outer_inames=frozenset())
136+
tunit = tunit.with_kernel(knl)
137+
assert not (knl.id_to_insn["first_w_a"].within_inames
138+
& knl.id_to_insn["second_w_b"].within_inames)
139+
lp.auto_test_vs_ref(ref_tunit, ctx, tunit)
140+
141+
tunit = lp.make_kernel(
142+
"{[i]: 0<=i<10}",
143+
"""
144+
a[i] = i {id=first_w_a}
145+
b[i] = 2*a[i+1] {id=first_w_b}
146+
""",
147+
seq_dependencies=True
148+
)
149+
150+
with pytest.raises(IllegalLoopDistributionError):
151+
lp.distribute_loops(tunit.default_entrypoint,
152+
"id:first_w_b",
153+
outer_inames=frozenset())
154+
155+
# }}}
156+
157+
# {{{ WAR deps
158+
159+
tunit = lp.make_kernel(
160+
"{[i, j]: 0<=i<10 and 0<=j<11}",
161+
"""
162+
b[j] = j**2
163+
a[i] = b[i+1] {id=first_w_a}
164+
b[i] = 2*a[i] {id=first_w_b}
165+
""",
166+
seq_dependencies=True
167+
)
168+
ref_tunit = tunit
169+
170+
knl = lp.distribute_loops(tunit.default_entrypoint,
171+
"id:first_w_b",
172+
outer_inames=frozenset())
173+
tunit = tunit.with_kernel(knl)
174+
assert not (knl.id_to_insn["first_w_a"].within_inames
175+
& knl.id_to_insn["first_w_b"].within_inames)
176+
lp.auto_test_vs_ref(ref_tunit, ctx, tunit)
177+
178+
tunit = lp.make_kernel(
179+
"{[i]: 1<=i<10}",
180+
"""
181+
b[0] = 0 {id=first_w_b}
182+
a[i] = b[i-1] {id=first_w_a}
183+
b[i] = 2*a[i] {id=second_w_b}
184+
""",
185+
seq_dependencies=True,
186+
)
187+
188+
with pytest.raises(IllegalLoopDistributionError):
189+
lp.distribute_loops(tunit.default_entrypoint,
190+
"id:second_w_b",
191+
outer_inames=frozenset())
192+
193+
# }}}
194+
195+
196+
def test_reduction_inames_get_duplicated(ctx_factory):
197+
ctx = ctx_factory()
198+
199+
tunit = lp.make_kernel(
200+
"{[i, j]: 0<=i<100 and 0<=j<10}",
201+
"""
202+
out1[i] = sum(j, mat1[j] * x1[i, j]) {id=w_out1}
203+
out2[i] = sum(j, mat2[j] * x2[i, j]) {id=w_out2}
204+
""",
205+
)
206+
tunit = lp.add_dtypes(tunit, {"mat1": np.float64,
207+
"mat2": np.float64,
208+
"x1": np.float64,
209+
"x2": np.float64,
210+
})
211+
212+
ref_tunit = tunit
213+
214+
knl = lp.distribute_loops(tunit.default_entrypoint,
215+
"id:w_out2",
216+
outer_inames=frozenset())
217+
tunit = tunit.with_kernel(knl)
218+
219+
assert not (knl.id_to_insn["w_out1"].within_inames
220+
& knl.id_to_insn["w_out2"].within_inames)
221+
assert not (knl.id_to_insn["w_out1"].reduction_inames()
222+
& knl.id_to_insn["w_out2"].reduction_inames())
223+
lp.auto_test_vs_ref(ref_tunit, ctx, tunit)
224+
225+
226+
def test_avoids_unnecessary_loop_distribution(ctx_factory):
227+
ctx = ctx_factory()
228+
tunit = lp.make_kernel(
229+
"{[i]: 0 <= i < 10}",
230+
"""
231+
y0[i] = i {id=w_y0}
232+
y1[i] = i**2 {id=w_y1}
233+
y2[i] = y0[i] + i**3 {id=w_y2}
234+
y3[i] = 2*y2[i] {id=w_y3}
235+
y4[i] = i**4 + y1[i] {id=w_y4}
236+
""")
237+
ref_tunit = tunit
238+
239+
knl = lp.distribute_loops(tunit.default_entrypoint,
240+
insn_match="writes:y2 or writes:y4",
241+
outer_inames=frozenset())
242+
tunit = tunit.with_kernel(knl)
243+
244+
assert (knl.id_to_insn["w_y2"].within_inames
245+
== knl.id_to_insn["w_y4"].within_inames)
246+
lp.auto_test_vs_ref(ref_tunit, ctx, tunit)
247+
248+
249+
if __name__ == "__main__":
250+
if len(sys.argv) > 1:
251+
exec(sys.argv[1])
252+
else:
253+
from pytest import main
254+
main([__file__])
255+
256+
# vim: fdm=marker

0 commit comments

Comments
 (0)