126 lines
3.6 KiB
Python
126 lines
3.6 KiB
Python
from numba import cuda
|
|
from numba.core.errors import TypingError
|
|
from numba.cuda.testing import CUDATestCase, skip_on_cudasim
|
|
import numpy as np
|
|
import unittest
|
|
|
|
|
|
class TestSelfRecursion(CUDATestCase):
|
|
|
|
def setUp(self):
|
|
# Avoid importing this module at the top level, as it triggers
|
|
# compilation and can therefore fail
|
|
from numba.cuda.tests.cudapy import recursion_usecases
|
|
self.mod = recursion_usecases
|
|
super().setUp()
|
|
|
|
def check_fib(self, cfunc):
|
|
@cuda.jit
|
|
def kernel(r, x):
|
|
r[0] = cfunc(x[0])
|
|
|
|
x = np.asarray([10], dtype=np.int64)
|
|
r = np.zeros_like(x)
|
|
kernel[1, 1](r, x)
|
|
|
|
actual = r[0]
|
|
expected = 55
|
|
self.assertPreciseEqual(actual, expected)
|
|
|
|
def test_global_explicit_sig(self):
|
|
self.check_fib(self.mod.fib1)
|
|
|
|
def test_inner_explicit_sig(self):
|
|
self.check_fib(self.mod.fib2)
|
|
|
|
def test_global_implicit_sig(self):
|
|
self.check_fib(self.mod.fib3)
|
|
|
|
@skip_on_cudasim('Simulator does not compile')
|
|
def test_runaway(self):
|
|
with self.assertRaises(TypingError) as raises:
|
|
cfunc = self.mod.runaway_self
|
|
|
|
@cuda.jit('void()')
|
|
def kernel():
|
|
cfunc(1)
|
|
|
|
self.assertIn("cannot type infer runaway recursion",
|
|
str(raises.exception))
|
|
|
|
@unittest.skip('Needs insert_unresolved_ref support in target')
|
|
def test_type_change(self):
|
|
pfunc = self.mod.type_change_self.py_func
|
|
cfunc = self.mod.type_change_self
|
|
|
|
@cuda.jit
|
|
def kernel(r, x, y):
|
|
r[0] = cfunc(x[0], y[0])
|
|
|
|
args = 13, 0.125
|
|
x = np.asarray([args[0]], dtype=np.int64)
|
|
y = np.asarray([args[1]], dtype=np.float64)
|
|
r = np.zeros_like(x)
|
|
|
|
kernel[1, 1](r, x, y)
|
|
|
|
expected = pfunc(*args)
|
|
actual = r[0]
|
|
|
|
self.assertPreciseEqual(actual, expected)
|
|
|
|
@unittest.expectedFailure
|
|
def test_raise(self):
|
|
# This is an expected failure because reporting of exceptions raised in
|
|
# device functions does not work correctly - see Issue #8036:
|
|
# https://github.com/numba/numba/issues/8036
|
|
with self.assertRaises(ValueError) as raises:
|
|
self.mod.raise_self_kernel[1, 1](3)
|
|
|
|
self.assertEqual(str(raises.exception), "raise_self")
|
|
|
|
@unittest.skip('Needs insert_unresolved_ref support in target')
|
|
def test_optional_return(self):
|
|
pfunc = self.mod.make_optional_return_case()
|
|
cfunc = self.mod.make_optional_return_case(cuda.jit)
|
|
|
|
@cuda.jit
|
|
def kernel(r, x):
|
|
res = cfunc(x[0])
|
|
if res is None:
|
|
res = 999
|
|
r[0] = res
|
|
|
|
def cpu_kernel(x):
|
|
res = pfunc(x)
|
|
if res is None:
|
|
res = 999
|
|
return res
|
|
|
|
for arg in (0, 5, 10, 15):
|
|
expected = cpu_kernel(arg)
|
|
x = np.asarray([arg], dtype=np.int64)
|
|
r = np.zeros_like(x)
|
|
kernel[1, 1](r, x)
|
|
actual = r[0]
|
|
|
|
self.assertEqual(expected, actual)
|
|
|
|
@skip_on_cudasim('Recursion handled because simulator does not compile')
|
|
def test_growing_return_tuple(self):
|
|
cfunc = self.mod.make_growing_tuple_case(cuda.jit)
|
|
|
|
with self.assertRaises(TypingError) as raises:
|
|
@cuda.jit('void()')
|
|
def kernel():
|
|
cfunc(100)
|
|
|
|
self.assertIn(
|
|
"Return type of recursive function does not converge",
|
|
str(raises.exception),
|
|
)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|