Skip to content

Commit 11b70f5

Browse files
authored
Merge pull request #6788 from testhound/testhound/fastmath_fdiv
Add support for fastmath 32-bit floating point divide
2 parents 6302896 + 4c4ac66 commit 11b70f5

2 files changed

Lines changed: 51 additions & 4 deletions

File tree

‎numba/cuda/mathimpl.py‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import math
22
import operator
33
from llvmlite import ir
4-
from numba.core import types, typing, utils
4+
from numba.core import types, typing, utils, cgutils
55
from numba.core.imputils import Registry
66
from numba.types import float32, float64, int64, uint64
77
from numba.cuda import libdevice
@@ -71,6 +71,19 @@ def math_isinf_isnan_int(context, builder, sig, args):
7171
return context.get_constant(types.boolean, 0)
7272

7373

74+
@lower(operator.truediv, types.float32, types.float32)
75+
def maybe_fast_truediv(context, builder, sig, args):
76+
if context.fastmath:
77+
sig = typing.signature(float32, float32, float32)
78+
impl = context.get_function(libdevice.fast_fdividef, sig)
79+
return impl(builder, args)
80+
else:
81+
with cgutils.if_zero(builder, args[1]):
82+
context.error_model.fp_zero_division(builder, ("division by zero",))
83+
res = builder.fdiv(*args)
84+
return res
85+
86+
7487
@lower(math.isfinite, types.Integer)
7588
def math_isfinite_int(context, builder, sig, args):
7689
return context.get_constant(types.boolean, 1)

‎numba/cuda/tests/cudapy/test_fastmath.py‎

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
from numba import cuda, float32
22
from math import cos, sin, tan, exp, log, log10, log2, pow
3+
import numpy as np
34
from numba.cuda.testing import CUDATestCase, skip_on_cudasim
45
import unittest
56

67

78
class TestFastMathOption(CUDATestCase):
9+
@skip_on_cudasim('fast divide not available in CUDASIM')
810
def test_kernel(self):
9-
11+
# Test the cast of an int being used in fastmath divide
1012
def foo(arr, val):
1113
i = cuda.grid(1)
1214
if i < arr.size:
@@ -15,8 +17,8 @@ def foo(arr, val):
1517
fastver = cuda.jit("void(float32[:], float32)", fastmath=True)(foo)
1618
precver = cuda.jit("void(float32[:], float32)")(foo)
1719

18-
self.assertIn('div.full.ftz.f32', fastver.ptx)
19-
self.assertNotIn('div.full.ftz.f32', precver.ptx)
20+
self.assertIn('div.approx.ftz.f32', fastver.ptx)
21+
self.assertNotIn('div.approx.ftz.f32', precver.ptx)
2022

2123
@skip_on_cudasim('fast cos not available in CUDASIM')
2224
def test_cosf(self):
@@ -105,6 +107,38 @@ def f8(r, x, y):
105107
self.assertIn('lg2.approx.ftz.f32 ', fastver.ptx)
106108
self.assertNotIn('lg2.approx.ftz.f32 ', slowver.ptx)
107109

110+
@skip_on_cudasim('fast divide not available in CUDASIM')
111+
def test_divf(self):
112+
def f9(r, x, y):
113+
r[0] = x / y
114+
115+
fastver = cuda.jit("void(float32[::1], float32, float32)",
116+
fastmath=True)(f9)
117+
slowver = cuda.jit("void(float32[::1], float32, float32)")(f9)
118+
self.assertIn('div.approx.ftz.f32 ', fastver.ptx)
119+
self.assertNotIn('div.approx.ftz.f32 ', slowver.ptx)
120+
self.assertIn('div.rn.f32', slowver.ptx)
121+
self.assertNotIn('div.rn.f32', fastver.ptx)
122+
123+
@skip_on_cudasim('fast divide not available in CUDASIM')
124+
def test_divf_exception(self):
125+
def f10(r, x, y):
126+
r[0] = x / y
127+
128+
fastver = cuda.jit("void(float32[::1], float32, float32)",
129+
fastmath=True, debug=True)(f10)
130+
slowver = cuda.jit("void(float32[::1], float32, float32)",
131+
debug=True)(f10)
132+
nelem = 10
133+
ary = np.empty(nelem, dtype=np.float32)
134+
with self.assertRaises(ZeroDivisionError):
135+
slowver[1, nelem](ary, 10.0, 0.0)
136+
137+
try:
138+
fastver[1, nelem](ary, 10.0, 0.0)
139+
except ZeroDivisionError:
140+
self.fail("Divide in fastmath should not throw ZeroDivisionError")
141+
108142
def test_device(self):
109143
# fastmath option is ignored for device function
110144
@cuda.jit("float32(float32, float32)", device=True)

0 commit comments

Comments
 (0)