Skip to content

Commit 743de4b

Browse files
committed
Remove atomic emulation
1 parent 67f06ee commit 743de4b

File tree

5 files changed

+42
-194
lines changed

5 files changed

+42
-194
lines changed

numba_dpex/config.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,6 @@ def __getattr__(name):
5353
# Dump offload diagnostics
5454
OFFLOAD_DIAGNOSTICS = _readenv("NUMBA_DPEX_OFFLOAD_DIAGNOSTICS", int, 0)
5555

56-
# Activate Native floating point atomcis support for supported devices.
57-
# Requires llvm-spirv supporting the FP atomics extension
58-
NATIVE_FP_ATOMICS = _readenv("NUMBA_DPEX_ACTIVATE_ATOMICS_FP_NATIVE", int, 0)
5956
# Emit debug info
6057
DEBUG = _readenv("NUMBA_DPEX_DEBUG", int, config.DEBUG)
6158
DEBUGINFO_DEFAULT = _readenv(

numba_dpex/examples/kernel/atomic_op.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@
1010
@ndpx.kernel
1111
def atomic_reduction(a):
1212
idx = ndpx.get_global_id(0)
13+
# a[0]+=a[idx]
1314
ndpx.atomic.add(a, 0, a[idx])
1415

1516

1617
def main():
1718
N = 10
18-
a = np.arange(N)
19+
a = np.ones(N)
1920

2021
print("Using device ...")
2122
print(a.device)

numba_dpex/ocl/oclimpl.py

Lines changed: 25 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -143,63 +143,6 @@ def sub_group_barrier_impl(context, builder, sig, args):
143143
return _void_value
144144

145145

146-
def insert_and_call_atomic_fn(
147-
context, builder, sig, fn_type, dtype, ptr, val, addrspace
148-
):
149-
ll_p = None
150-
name = ""
151-
if dtype.name == "float32":
152-
ll_val = llvmir.FloatType()
153-
ll_p = ll_val.as_pointer()
154-
if fn_type == "add":
155-
name = "numba_dpex_atomic_add_f32"
156-
elif fn_type == "sub":
157-
name = "numba_dpex_atomic_sub_f32"
158-
else:
159-
raise TypeError("Operation type is not supported %s" % (fn_type))
160-
elif dtype.name == "float64":
161-
if True:
162-
ll_val = llvmir.DoubleType()
163-
ll_p = ll_val.as_pointer()
164-
if fn_type == "add":
165-
name = "numba_dpex_atomic_add_f64"
166-
elif fn_type == "sub":
167-
name = "numba_dpex_atomic_sub_f64"
168-
else:
169-
raise TypeError(
170-
"Operation type is not supported %s" % (fn_type)
171-
)
172-
else:
173-
raise TypeError(
174-
"Atomic operation is not supported for type %s" % (dtype.name)
175-
)
176-
177-
if addrspace == address_space.LOCAL:
178-
name = name + "_local"
179-
else:
180-
name = name + "_global"
181-
182-
assert ll_p is not None
183-
assert name != ""
184-
ll_p.addrspace = address_space.GENERIC
185-
186-
mod = builder.module
187-
if sig.return_type == types.void:
188-
llretty = llvmir.VoidType()
189-
else:
190-
llretty = context.get_value_type(sig.return_type)
191-
192-
llargs = [ll_p, context.get_value_type(sig.args[2])]
193-
fnty = llvmir.FunctionType(llretty, llargs)
194-
195-
fn = cgutils.get_or_insert_function(mod, fnty, name)
196-
fn.calling_convention = kernel_target.CC_SPIR_FUNC
197-
198-
generic_ptr = context.addrspacecast(builder, ptr, address_space.GENERIC)
199-
200-
return builder.call(fn, [generic_ptr, val])
201-
202-
203146
def native_atomic_add(context, builder, sig, args):
204147
aryty, indty, valty = sig.args
205148
ary, inds, val = args
@@ -282,27 +225,33 @@ def native_atomic_add(context, builder, sig, args):
282225
return builder.call(fn, fn_args)
283226

284227

228+
def support_atomic(dtype: types.Type, device: str) -> bool:
229+
# This check should be the same as described in sycl documentation:
230+
# https://registry.khronos.org/SYCL/specs/sycl-2020/html/sycl-2020.html#sec:atomic-references
231+
return (
232+
dtype == types.int32
233+
or dtype == types.uint32
234+
or dtype == types.float32
235+
or (
236+
dtype == types.int64
237+
or dtype == types.uint64
238+
or dtype == types.float64
239+
)
240+
and dpctl.SyclDevice(device).has_aspect_atomic64
241+
)
242+
243+
285244
@lower(stubs.atomic.add, types.Array, types.intp, types.Any)
286245
@lower(stubs.atomic.add, types.Array, types.UniTuple, types.Any)
287246
@lower(stubs.atomic.add, types.Array, types.Tuple, types.Any)
288247
def atomic_add_tuple(context, builder, sig, args):
289-
device_type = dpctl.get_current_queue().sycl_device.device_type
290-
dtype = sig.args[0].dtype
291-
292-
if dtype == types.float32 or dtype == types.float64:
293-
if (
294-
device_type == dpctl.device_type.gpu
295-
and config.NATIVE_FP_ATOMICS == 1
296-
):
297-
return native_atomic_add(context, builder, sig, args)
298-
else:
299-
# Currently, DPCPP only supports native floating point
300-
# atomics for GPUs.
301-
return atomic_add(context, builder, sig, args, "add")
302-
elif dtype == types.int32 or dtype == types.int64:
248+
dtype, device = sig.args[0].dtype, sig.args[0].device
249+
if support_atomic(dtype, device):
303250
return native_atomic_add(context, builder, sig, args)
304251
else:
305-
raise TypeError("Atomic operation on unsupported type %s" % dtype)
252+
raise TypeError(
253+
f"Atomic operation on unsupported type {dtype} or device {device}"
254+
)
306255

307256

308257
def atomic_sub_wrapper(context, builder, sig, args):
@@ -337,80 +286,12 @@ def atomic_sub_wrapper(context, builder, sig, args):
337286
@lower(stubs.atomic.sub, types.Array, types.UniTuple, types.Any)
338287
@lower(stubs.atomic.sub, types.Array, types.Tuple, types.Any)
339288
def atomic_sub_tuple(context, builder, sig, args):
340-
device_type = dpctl.get_current_queue().sycl_device.device_type
341-
dtype = sig.args[0].dtype
342-
343-
if dtype == types.float32 or dtype == types.float64:
344-
if (
345-
device_type == dpctl.device_type.gpu
346-
and config.NATIVE_FP_ATOMICS == 1
347-
):
348-
return atomic_sub_wrapper(context, builder, sig, args)
349-
else:
350-
# Currently, DPCPP only supports native floating point
351-
# atomics for GPUs.
352-
return atomic_add(context, builder, sig, args, "sub")
353-
elif dtype == types.int32 or dtype == types.int64:
289+
dtype, device = sig.args[0].dtype, sig.args[0].device
290+
if support_atomic(dtype, device):
354291
return atomic_sub_wrapper(context, builder, sig, args)
355292
else:
356-
raise TypeError("Atomic operation on unsupported type %s" % dtype)
357-
358-
359-
def atomic_add(context, builder, sig, args, name):
360-
from .atomics import atomic_support_present
361-
362-
if atomic_support_present():
363-
context.extra_compile_options[kernel_target.LINK_ATOMIC] = True
364-
aryty, indty, valty = sig.args
365-
ary, inds, val = args
366-
dtype = aryty.dtype
367-
368-
if indty == types.intp:
369-
indices = [inds] # just a single integer
370-
indty = [indty]
371-
else:
372-
indices = cgutils.unpack_tuple(builder, inds, count=len(indty))
373-
indices = [
374-
context.cast(builder, i, t, types.intp)
375-
for t, i in zip(indty, indices)
376-
]
377-
378-
if dtype != valty:
379-
raise TypeError("expecting %s but got %s" % (dtype, valty))
380-
381-
if aryty.ndim != len(indty):
382-
raise TypeError(
383-
"indexing %d-D array with %d-D index" % (aryty.ndim, len(indty))
384-
)
385-
386-
lary = context.make_array(aryty)(context, builder, ary)
387-
ptr = cgutils.get_item_pointer(context, builder, aryty, lary, indices)
388-
389-
if isinstance(aryty, Array) and aryty.addrspace == address_space.LOCAL:
390-
return insert_and_call_atomic_fn(
391-
context,
392-
builder,
393-
sig,
394-
name,
395-
dtype,
396-
ptr,
397-
val,
398-
address_space.LOCAL,
399-
)
400-
else:
401-
return insert_and_call_atomic_fn(
402-
context,
403-
builder,
404-
sig,
405-
name,
406-
dtype,
407-
ptr,
408-
val,
409-
address_space.GLOBAL,
410-
)
411-
else:
412-
raise ImportError(
413-
"Atomic support is not present, can not perform atomic_add"
293+
raise TypeError(
294+
f"Atomic operation on unsupported type {dtype} or device {device}"
414295
)
415296

416297

numba_dpex/spirv_generator.py

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
"""A wrapper to connect to the SPIR-V binaries (Tools, Translator)."""
66

77
import os
8-
import shutil
98
import tempfile
109
from subprocess import CalledProcessError, check_call
1110

@@ -75,14 +74,6 @@ def generate(self, llvm_spirv_args, ipath, opath):
7574
if config.DEBUG:
7675
llvm_spirv_flags.append("--spirv-debug-info-version=ocl-100")
7776

78-
if not config.NATIVE_FP_ATOMICS:
79-
# Do NOT upgrade version unless you are 100% confident. Not all
80-
# kernel outputs can be converted to higher version of spirv.
81-
# That results in different spirv file versions. As next step
82-
# requires linking of the result file and
83-
# numba_dpex/ocl/atomics/atomic_ops.spir it will raise an error
84-
# that two spirv files have different version and can't be linked
85-
llvm_spirv_args = ["--spirv-max-version", "1.0"] + llvm_spirv_args
8677
llvm_spirv_tool = self._llvm_spirv()
8778

8879
if config.DEBUG:
@@ -162,15 +153,9 @@ def finalize(self):
162153
# Generate SPIR-V from "friendly" LLVM-based SPIR 2.0
163154
spirv_path = self._track_temp_file("generated-spirv")
164155

165-
binary_paths = [spirv_path]
166-
167156
llvm_spirv_args = []
168157
for key in list(self.context.extra_compile_options.keys()):
169-
if key == LINK_ATOMIC:
170-
from .ocl.atomics import get_atomic_spirv_path
171-
172-
binary_paths.append(get_atomic_spirv_path())
173-
elif key == LLVM_SPIRV_ARGS:
158+
if key == LLVM_SPIRV_ARGS:
174159
llvm_spirv_args = self.context.extra_compile_options[key]
175160
del self.context.extra_compile_options[key]
176161

@@ -194,10 +179,6 @@ def finalize(self):
194179
opath=spirv_path,
195180
)
196181

197-
if len(binary_paths) > 1:
198-
spirv_path = self._track_temp_file("linked-spirv")
199-
self._cmd.link(spirv_path, binary_paths)
200-
201182
if config.SAVE_IR_FILES != 0:
202183
# Dump the llvmir and llvmbc in file
203184
with open("generated_spirv.spir", "wb") as f1:

numba_dpex/tests/kernel_tests/test_atomic_op.py

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -160,21 +160,11 @@ def test_kernel_atomic_multi_dim(
160160
assert a[0] == expected
161161

162162

163-
skip_NATIVE_FP_ATOMICS_0 = pytest.mark.skipif(
164-
not config.NATIVE_FP_ATOMICS, reason="Native FP atomics disabled"
165-
)
166-
167-
168-
def skip_if_disabled(*args):
169-
return pytest.param(*args, marks=skip_NATIVE_FP_ATOMICS_0)
170-
171-
172163
@skip_no_atomic_support
173164
@pytest.mark.parametrize(
174-
"NATIVE_FP_ATOMICS, expected_native_atomic_for_device",
165+
"expected_native_atomic_for_device",
175166
[
176-
skip_if_disabled(1, lambda device: device != "opencl:cpu:0"),
177-
(0, lambda device: False),
167+
lambda device: True,
178168
],
179169
)
180170
@pytest.mark.parametrize(
@@ -189,7 +179,6 @@ def skip_if_disabled(*args):
189179
)
190180
@pytest.mark.parametrize("dtype", list_of_f_dtypes)
191181
def test_atomic_fp_native(
192-
NATIVE_FP_ATOMICS,
193182
expected_native_atomic_for_device,
194183
function_generator,
195184
operator_name,
@@ -206,16 +195,15 @@ def test_atomic_fp_native(
206195
for arg in args
207196
]
208197

209-
with override_config("NATIVE_FP_ATOMICS", NATIVE_FP_ATOMICS):
210-
kernel.compile(
211-
args=argtypes,
212-
debug=False,
213-
compile_flags=None,
214-
target_ctx=dpex_kernel_target.target_context,
215-
typing_ctx=dpex_kernel_target.typing_context,
216-
)
217-
218-
is_native_atomic = expected_spirv_function in kernel._llvm_module
219-
assert is_native_atomic == expected_native_atomic_for_device(
220-
dpctl.select_default_device().filter_string
221-
)
198+
kernel.compile(
199+
args=argtypes,
200+
debug=False,
201+
compile_flags=None,
202+
target_ctx=dpex_kernel_target.target_context,
203+
typing_ctx=dpex_kernel_target.typing_context,
204+
)
205+
206+
is_native_atomic = expected_spirv_function in kernel._llvm_module
207+
assert is_native_atomic == expected_native_atomic_for_device(
208+
dpctl.select_default_device().filter_string
209+
)

0 commit comments

Comments
 (0)