diff --git a/numba_dppy/config.py b/numba_dppy/config.py index 880d18d7b5..76849ba00c 100644 --- a/numba_dppy/config.py +++ b/numba_dppy/config.py @@ -34,3 +34,5 @@ def _readenv(): ... # Turn SPIRV-VALIDATION ON/OFF switch SPIRV_VAL = _readenv("NUMBA_DPPY_SPIRV_VAL", int, 0) + +FALLBACK_ON_CPU = _readenv("NUMBA_DPPY_FALLBACK_ON_CPU", int, 1) diff --git a/numba_dppy/dppy_lowerer.py b/numba_dppy/dppy_lowerer.py index 1561a6d85e..b7f591d296 100644 --- a/numba_dppy/dppy_lowerer.py +++ b/numba_dppy/dppy_lowerer.py @@ -1171,7 +1171,8 @@ def lower(self): if numba_dppy.compiler.DEBUG: print("Failed to lower parfor on DPPY-device. Due to:\n", e) lowering.lower_extensions[parfor.Parfor].pop() - if (lowering.lower_extensions[parfor.Parfor][-1] == numba.parfors.parfor_lowering._lower_parfor_parallel): + if ((lowering.lower_extensions[parfor.Parfor][-1] == numba.parfors.parfor_lowering._lower_parfor_parallel) and + numba_dppy.config.FALLBACK_ON_CPU == 1): self.cpu_lower.lower() self.base_lower = self.cpu_lower else: diff --git a/numba_dppy/tests/test_controllable_fallback.py b/numba_dppy/tests/test_controllable_fallback.py new file mode 100644 index 0000000000..45405b9958 --- /dev/null +++ b/numba_dppy/tests/test_controllable_fallback.py @@ -0,0 +1,72 @@ +import numpy as np + +import numba +import numba_dppy +from numba_dppy.testing import unittest +from numba_dppy.testing import DPPYTestCase +from numba.tests.support import captured_stderr +import dpctl + + +@unittest.skipUnless(dpctl.has_gpu_queues(), 'test only on GPU system') +class TestDPPYFallback(DPPYTestCase): + def test_dppy_fallback_true(self): + @numba.jit + def fill_value(i): + return i + + def inner_call_fallback(): + x = 10 + a = np.empty(shape=x, dtype=np.float32) + + for i in numba.prange(x): + a[i] = fill_value(i) + + return a + + numba_dppy.compiler.DEBUG = 1 + with captured_stderr() as msg_fallback_true: + with dpctl.device_context("opencl:gpu") as gpu_queue: + dppy = numba.njit(parallel=True)(inner_call_fallback) + dppy_fallback_true = dppy() + + ref_result = inner_call_fallback() + numba_dppy.compiler.DEBUG = 0 + + np.testing.assert_array_equal(dppy_fallback_true, ref_result) + self.assertTrue('Failed to lower parfor on DPPY-device' in msg_fallback_true.getvalue()) + + @unittest.expectedFailure + def test_dppy_fallback_false(self): + @numba.jit + def fill_value(i): + return i + + def inner_call_fallback(): + x = 10 + a = np.empty(shape=x, dtype=np.float32) + + for i in numba.prange(x): + a[i] = fill_value(i) + + return a + + try: + numba_dppy.compiler.DEBUG = 1 + numba_dppy.config.FALLBACK_ON_CPU = 0 + with captured_stderr() as msg_fallback_true: + with dpctl.device_context("opencl:gpu") as gpu_queue: + dppy = numba.njit(parallel=True)(inner_call_fallback) + dppy_fallback_false = dppy() + + finally: + ref_result = inner_call_fallback() + numba_dppy.config.FALLBACK_ON_CPU = 1 + numba_dppy.compiler.DEBUG = 0 + + not np.testing.assert_array_equal(dppy_fallback_false, ref_result) + not self.assertTrue('Failed to lower parfor on DPPY-device' in msg_fallback_true.getvalue()) + + +if __name__ == '__main__': + unittest.main()