diff --git a/environment.yml b/environment.yml index 7f402a11d3..f294eb3164 100644 --- a/environment.yml +++ b/environment.yml @@ -26,6 +26,7 @@ dependencies: - black==20.8b1 - pytest-cov - pytest-xdist + - pexpect variables: CHANNELS: -c defaults -c numba -c intel -c numba/label/dev -c dppy/label/dev --override-channels CHANNELS_DEV: -c dppy/label/dev -c defaults -c numba -c intel -c numba/label/dev --override-channels diff --git a/numba_dppy/examples/debug/dppy_numba_basic.py b/numba_dppy/examples/debug/dppy_numba_basic.py new file mode 100644 index 0000000000..d90a734d90 --- /dev/null +++ b/numba_dppy/examples/debug/dppy_numba_basic.py @@ -0,0 +1,79 @@ +# Copyright 2020, 2021 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import argparse + +import dpctl +import numba +import numpy as np + +import numba_dppy as dppy + + +def func(param_a, param_b): + param_c = param_a + 10 # Set breakpoint + param_d = param_b * 0.5 + result = param_c + param_d + return result + + +dppy_func = dppy.func(debug=True)(func) +numba_func = numba.njit(debug=True)(func) + + +@dppy.kernel(debug=True) +def dppy_kernel(a_in_kernel, b_in_kernel, c_in_kernel): + i = dppy.get_global_id(0) + c_in_kernel[i] = dppy_func(a_in_kernel[i], b_in_kernel[i]) + + +@numba.njit(debug=True) +def numba_func_driver(a, b, c): + for i in range(len(c)): + c[i] = numba_func(a[i], b[i]) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + "--api", + required=False, + default="numba", + choices=["numba", "numba-dppy"], + help="Start the version of functions using numba or numba-dppy API", + ) + + args = parser.parse_args() + + print("Using API:", args.api) + + global_size = 10 + N = global_size + + a = np.arange(N, dtype=np.float32) + b = np.arange(N, dtype=np.float32) + c = np.empty_like(a) + + if args.api == "numba-dppy": + device = dpctl.select_default_device() + with dppy.offload_to_sycl_device(device): + dppy_kernel[global_size, dppy.DEFAULT_LOCAL_SIZE](a, b, c) + else: + numba_func_driver(a, b, c) + + print("Done...") + + +if __name__ == "__main__": + main() diff --git a/numba_dppy/tests/test_debug_dppy_numba.py b/numba_dppy/tests/test_debug_dppy_numba.py new file mode 100644 index 0000000000..28f66f6f97 --- /dev/null +++ b/numba_dppy/tests/test_debug_dppy_numba.py @@ -0,0 +1,83 @@ +#! /usr/bin/env python +# Copyright 2021 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import pathlib +import shutil +import sys + +import pytest + +import numba_dppy + +pexpect = pytest.importorskip("pexpect") + +pytestmark = pytest.mark.skipif( + not shutil.which("gdb-oneapi"), + reason="IntelĀ® Distribution for GDB* is not available", +) + + +# TODO: go to helper +class gdb: + def __init__(self): + self.spawn() + self.setup_gdb() + + def __del__(self): + self.teardown_gdb() + + def spawn(self): + env = os.environ.copy() + env["NUMBA_OPT"] = "0" + + self.child = pexpect.spawn("gdb-oneapi -q python", env=env, encoding="utf-8") + # self.child.logfile = sys.stdout + + def setup_gdb(self): + self.child.expect("(gdb)", timeout=5) + self.child.sendline("set breakpoint pending on") + self.child.expect("(gdb)", timeout=5) + self.child.sendline("set style enabled off") # disable colors symbols + + def teardown_gdb(self): + self.child.expect("(gdb)", timeout=5) + self.child.sendline("quit") + self.child.expect("Quit anyway?", timeout=5) + self.child.sendline("y") + + def breakpoint(self, breakpoint): + self.child.expect("(gdb)", timeout=5) + self.child.sendline("break " + breakpoint) + + def run(self, script): + self.child.expect("(gdb)", timeout=5) + self.child.sendline("run " + self.script_path(script)) + + @staticmethod + def script_path(script): + package_path = pathlib.Path(numba_dppy.__file__).parent + return str(package_path / "examples/debug" / script) + + +@pytest.mark.parametrize("api", ["numba", "numba-dppy"]) +def test_breakpoint_row_number(api): + app = gdb() + + app.breakpoint("dppy_numba_basic.py:25") + app.run("dppy_numba_basic.py --api={api}".format(api=api)) + + app.child.expect(r"Thread .* hit Breakpoint .* at dppy_numba_basic.py:25") + app.child.expect(r"25\s+param_c = param_a \+ 10")