loopy icon indicating copy to clipboard operation
loopy copied to clipboard

[Usability] Callables that are (unintentional) entrypoints cause type errors

Open inducer opened this issue 3 years ago • 0 comments

Consider this code (from @xywei):


import pyopencl as cl
import numpy as np
import loopy as lp

inline = False

ctx = cl.create_some_context()
queue = cl.CommandQueue(ctx)
n = 4

x = np.random.rand(n, n, n, n, n)
y = np.random.rand(n, n, n, n, n)

grandchild_knl = lp.make_kernel(
        "{[i, j]:0<= i, j< 4}",
        """
        c[i, j] = 2*a[i, j] + 3*b[i, j]
        """, name="linear_combo1")

child_knl = lp.make_kernel(
        "{[i, j]:0<=i, j < 4}",
        """
        [i, j]: g[i, j] = linear_combo1([i, j]: e[i, j], [i, j]: f[i, j])
        """, name="linear_combo2")

parent_knl = lp.make_kernel(
        "{[i, j, k, l, m]: 0<=i, j, k, l, m<4}",
        """
        [j, l]: z[i, j, k, l, m] = linear_combo2([j, l]: x[i, j, k, l, m],
                                                 [j, l]: y[i, j, k, l, m])
        """,
        kernel_data=[
            lp.GlobalArg(
                name="x, y",
                dtype=np.float64,
                shape=(n, n, n, n, n)),
            ...],
        name="mmmmain"
        )

knl = lp.merge([grandchild_knl, child_knl, parent_knl])

if inline:
    knl = lp.inline_callable_kernel(knl, "linear_combo2")
    knl = lp.inline_callable_kernel(knl, "linear_combo1")

evt, (out, ) = knl(queue, x=x, y=y, entrypoint="mmmmain")

print(knl)

assert (np.linalg.norm(2*x+3*y-out)/(
    np.linalg.norm(2*x+3*y))) < 1e-15

It crashes with

Traceback (most recent call last):
  File "/home/andreas/tmp/xiaoyu-type-bug/type-bug.py", line 48, in <module>
    evt, (out, ) = knl(queue, x=x, y=y, entrypoint="mmmmain")
  File "/home/andreas/src/loopy/loopy/translation_unit.py", line 347, in __call__
    return pex(*args, **kwargs)
  File "/home/andreas/src/loopy/loopy/target/pyopencl_execution.py", line 368, in __call__
    translation_unit_info = self.translation_unit_info(entrypoint,
  File "/home/andreas/src/pytools/pytools/__init__.py", line 706, in wrapper
    result = function(obj, *args, **kwargs)
  File "/home/andreas/src/loopy/loopy/target/pyopencl_execution.py", line 292, in translation_unit_info
    codegen_result = generate_code_v2(program)
  File "/home/andreas/src/loopy/loopy/codegen/__init__.py", line 751, in generate_code_v2
    program = infer_unknown_types(program, expect_completion=True)
  File "/home/andreas/src/loopy/loopy/type_inference.py", line 1051, in infer_unknown_types
    raise LoopyError("could not determine type of"
loopy.diagnostic.LoopyError: could not determine type of 'b' of kernel 'linear_combo1'.

If child_knl and grandchild_knl weren't marked as entrypoints (because make_kernel, not make_function), the type inference failure would be avoided. On the one hand, that's correct: We've still got the entrypoint versions of those callables hanging around, untyped, preventing codegen. OTOH, the fix isn't very discoverable. It'd be nice if the message said, "Hey, this error is for entrypoint you're not currently trying to call. Did you mean for this callable to be an entrypoint?"

inducer avatar Mar 22 '22 05:03 inducer