Skip to content

Commit 8a2b43e

Browse files
Merge pull request #550 from IntelPython/feature/cython-public-api
Feature/cython public api
2 parents 260573c + 5560978 commit 8a2b43e

File tree

16 files changed

+232
-21
lines changed

16 files changed

+232
-21
lines changed

MANIFEST.in

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,15 @@ include versioneer.py
22
recursive-include dpctl/include *.h
33
recursive-include dpctl *.pxd
44
include dpctl/_sycl_context.h
5+
include dpctl/_sycl_context_api.h
56
include dpctl/_sycl_device.h
7+
include dpctl/_sycl_device_api.h
68
include dpctl/_sycl_queue.h
7-
include dpctl/_sycl_queue_manager.h
9+
include dpctl/_sycl_queue_api.h
810
include dpctl/_sycl_event.h
11+
include dpctl/_sycl_event_api.h
912
include dpctl/memory/_memory.h
13+
include dpctl/memory/_memory_api.h
14+
include dpctl/tensor/_usmarray.h
15+
include dpctl/tensor/_usmarray_api.h
1016
include dpctl/tests/input_files/*

dpctl/_sycl_context.pxd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ from ._backend cimport DPCTLSyclContextRef
2626
from ._sycl_device cimport SyclDevice
2727

2828

29-
cdef public class _SyclContext [
29+
cdef public api class _SyclContext [
3030
object Py_SyclContextObject,
3131
type Py_SyclContextType
3232
]:
@@ -35,7 +35,7 @@ cdef public class _SyclContext [
3535
cdef DPCTLSyclContextRef _ctxt_ref
3636

3737

38-
cdef public class SyclContext(_SyclContext) [
38+
cdef public api class SyclContext(_SyclContext) [
3939
object PySyclContextObject,
4040
type PySyclContextType
4141
]:

dpctl/_sycl_context.pyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ cdef class SyclContext(_SyclContext):
474474
&_context_capsule_deleter
475475
)
476476

477-
cdef public DPCTLSyclContextRef get_context_ref(SyclContext ctx):
477+
cdef api DPCTLSyclContextRef get_context_ref(SyclContext ctx):
478478
"""
479479
C-API function to get opaque context reference from
480480
:class:`dpctl.SyclContext` instance.

dpctl/_sycl_device.pxd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ from ._backend cimport (
2929
)
3030

3131

32-
cdef public class _SyclDevice [
32+
cdef public api class _SyclDevice [
3333
object Py_SyclDeviceObject,
3434
type Py_SyclDeviceType
3535
]:
@@ -42,7 +42,7 @@ cdef public class _SyclDevice [
4242
cdef size_t *_max_work_item_sizes
4343

4444

45-
cdef public class SyclDevice(_SyclDevice) [
45+
cdef public api class SyclDevice(_SyclDevice) [
4646
object PySyclDeviceObject,
4747
type PySyclDeviceType
4848
]:

dpctl/_sycl_device.pyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1118,7 +1118,7 @@ cdef class SyclDevice(_SyclDevice):
11181118
else:
11191119
return str(relId)
11201120

1121-
cdef public DPCTLSyclDeviceRef get_device_ref(SyclDevice dev):
1121+
cdef api DPCTLSyclDeviceRef get_device_ref(SyclDevice dev):
11221122
"""
11231123
C-API function to get opaque device reference from
11241124
:class:`dpctl.SyclDevice` instance.

dpctl/_sycl_event.pxd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from ._backend cimport DPCTLSyclEventRef
2424

2525

26-
cdef public class SyclEvent [object PySyclEventObject, type PySyclEventType]:
26+
cdef public api class SyclEvent [object PySyclEventObject, type PySyclEventType]:
2727
''' Wrapper class for a Sycl Event
2828
'''
2929
cdef DPCTLSyclEventRef _event_ref

dpctl/_sycl_event.pyx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@ __all__ = [
3232
_logger = logging.getLogger(__name__)
3333

3434

35+
cdef api DPCTLSyclEventRef get_event_ref(SyclEvent ev):
36+
""" C-API function to access opaque event reference from
37+
Python object of type :class:`dpctl.SyclEvent`.
38+
"""
39+
return ev.get_event_ref()
40+
41+
3542
cdef class SyclEvent:
3643
""" Python wrapper class for cl::sycl::event.
3744
"""

dpctl/_sycl_queue.pxd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ from .program._program cimport SyclKernel
3131

3232
cdef void default_async_error_handler(int) nogil except *
3333

34-
cdef public class _SyclQueue [
34+
cdef public api class _SyclQueue [
3535
object Py_SyclQueueObject, type Py_SyclQueueType
3636
]:
3737
""" Python data owner class for a sycl::queue.
@@ -41,7 +41,7 @@ cdef public class _SyclQueue [
4141
cdef SyclDevice _device
4242

4343

44-
cdef public class SyclQueue (_SyclQueue) [
44+
cdef public api class SyclQueue (_SyclQueue) [
4545
object PySyclQueueObject, type PySyclQueueType
4646
]:
4747
""" Python wrapper class for a sycl::queue.

dpctl/_sycl_queue.pyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,7 @@ cdef class SyclQueue(_SyclQueue):
969969
self.sycl_device.print_device_info()
970970

971971

972-
cdef public DPCTLSyclQueueRef get_queue_ref(SyclQueue q):
972+
cdef api DPCTLSyclQueueRef get_queue_ref(SyclQueue q):
973973
"""
974974
C-API function to get opaque queue reference from
975975
:class:`dpctl.SyclQueue` instance.

dpctl/memory/_memory.pxd

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ cdef DPCTLSyclQueueRef get_queue_ref_from_ptr_and_syclobj(
3232
DPCTLSyclUSMRef ptr, object syclobj)
3333

3434

35-
cdef public class _Memory [object Py_MemoryObject, type Py_MemoryType]:
35+
cdef public api class _Memory [object Py_MemoryObject, type Py_MemoryType]:
3636
cdef DPCTLSyclUSMRef memory_ptr
3737
cdef Py_ssize_t nbytes
3838
cdef SyclQueue queue
@@ -51,25 +51,25 @@ cdef public class _Memory [object Py_MemoryObject, type Py_MemoryType]:
5151
cpdef bytes tobytes(self)
5252

5353
@staticmethod
54-
cdef public SyclDevice get_pointer_device(
54+
cdef SyclDevice get_pointer_device(
5555
DPCTLSyclUSMRef p, SyclContext ctx)
5656
@staticmethod
57-
cdef public bytes get_pointer_type(DPCTLSyclUSMRef p, SyclContext ctx)
57+
cdef bytes get_pointer_type(DPCTLSyclUSMRef p, SyclContext ctx)
5858
@staticmethod
59-
cdef public object create_from_usm_pointer_size_qref(
59+
cdef object create_from_usm_pointer_size_qref(
6060
DPCTLSyclUSMRef USMRef,
6161
Py_ssize_t nbytes,
6262
DPCTLSyclQueueRef QRef,
6363
object memory_owner=*
6464
)
6565

6666

67-
cdef public class MemoryUSMShared(_Memory) [object PyMemoryUSMSharedObject,
67+
cdef public api class MemoryUSMShared(_Memory) [object PyMemoryUSMSharedObject,
6868
type PyMemoryUSMSharedType]:
6969
pass
7070

7171

72-
cdef public class MemoryUSMHost(_Memory) [object PyMemoryUSMHostObject,
72+
cdef public api class MemoryUSMHost(_Memory) [object PyMemoryUSMHostObject,
7373
type PyMemoryUSMHostType]:
7474
pass
7575

dpctl/memory/_memory.pyx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -708,11 +708,11 @@ def as_usm_memory(obj):
708708
)
709709

710710

711-
cdef public DPCTLSyclUSMRef get_usm_pointer(_Memory obj):
711+
cdef api DPCTLSyclUSMRef get_usm_pointer(_Memory obj):
712712
return obj.memory_ptr
713713

714-
cdef public DPCTLSyclContextRef get_context(_Memory obj):
714+
cdef api DPCTLSyclContextRef get_context(_Memory obj):
715715
return obj.queue._context.get_context_ref()
716716

717-
cdef public size_t get_nbytes(_Memory obj):
717+
cdef api size_t get_nbytes(_Memory obj):
718718
return <size_t>obj.nbytes

dpctl/tensor/_usmarray.pxd

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ cdef public int USM_ARRAY_F_CONTIGUOUS
99
cdef public int USM_ARRAY_WRITEABLE
1010

1111

12-
cdef public class usm_ndarray [object PyUSMArrayObject, type PyUSMArrayType]:
12+
cdef public api class usm_ndarray [object PyUSMArrayObject, type PyUSMArrayType]:
1313
# data fields
1414
cdef char* data_
1515
cdef readonly int nd_
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Usage of dpctl entities in Pybind11
2+
3+
This extension demonstrates how dpctl Python types,
4+
such as dpctl.SyclQueue could be used in Pybind11
5+
extensions.
6+
7+
8+
# Building extension
9+
10+
```
11+
source /opt/intel/oneapi/compiler/latest/env/vars.sh
12+
CXX=dpcpp CC=dpcpp python setup.py build_ext --inplace
13+
python example.py
14+
```
15+
16+
# Sample output
17+
18+
```
19+
(idp) [17:25:27 ansatnuc04 use_dpctl_syclqueue]$ python example.py
20+
EU count returned by Pybind11 extension 24
21+
EU count computed by dpctl 24
22+
23+
Computing modular reduction using SYCL on a NumPy array
24+
Offloaded result agrees with reference one computed by NumPy
25+
```
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Data Parallel Control (dpctl)
2+
#
3+
# Copyright 2020-2021 Intel Corporation
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
# coding: utf-8
18+
19+
import numpy as np
20+
import pybind11_example as eg
21+
22+
import dpctl
23+
24+
q = dpctl.SyclQueue()
25+
26+
# Pass dpctl.SyclQueue to Pybind11 extension
27+
eu_count = eg.get_max_compute_units(q)
28+
29+
print(f"EU count returned by Pybind11 extension {eu_count}")
30+
print("EU count computed by dpctl {}".format(q.sycl_device.max_compute_units))
31+
32+
print("")
33+
print("Computing modular reduction using SYCL on a NumPy array")
34+
35+
X = np.random.randint(low=1, high=2 ** 16 - 1, size=10 ** 6, dtype=np.longlong)
36+
modulus_p = 347
37+
38+
Y = eg.offloaded_array_mod(
39+
q, X, modulus_p
40+
) # Y is a regular array with host memory underneath it
41+
Ynp = X % modulus_p
42+
43+
check = np.array_equal(Y, Ynp)
44+
45+
if check:
46+
print("Offloaded result agrees with reference one computed by NumPy")
47+
else:
48+
print("Offloaded array differs from reference result computed by NumPy")
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#include <CL/sycl.hpp>
2+
#include <cstdint>
3+
#include <pybind11/numpy.h>
4+
#include <pybind11/pybind11.h>
5+
6+
#include "../_sycl_queue.h"
7+
#include "../_sycl_queue_api.h"
8+
#include "dpctl_sycl_types.h"
9+
10+
namespace py = pybind11;
11+
12+
size_t get_max_compute_units(py::object queue)
13+
{
14+
PyObject *queue_ptr = queue.ptr();
15+
if (PyObject_TypeCheck(queue_ptr, &PySyclQueueType)) {
16+
DPCTLSyclQueueRef QRef =
17+
get_queue_ref(reinterpret_cast<PySyclQueueObject *>(queue_ptr));
18+
sycl::queue *q = reinterpret_cast<sycl::queue *>(QRef);
19+
20+
return q->get_device()
21+
.get_info<sycl::info::device::max_compute_units>();
22+
}
23+
else {
24+
throw std::runtime_error("expected dpctl.SyclQueue as argument");
25+
}
26+
}
27+
28+
py::array_t<int64_t>
29+
offloaded_array_mod(py::object queue,
30+
py::array_t<int64_t, py::array::c_style> array,
31+
int64_t mod)
32+
{
33+
sycl::queue *q_ptr;
34+
35+
PyObject *queue_pycapi = queue.ptr();
36+
if (PyObject_TypeCheck(queue_pycapi, &PySyclQueueType)) {
37+
DPCTLSyclQueueRef QRef =
38+
get_queue_ref(reinterpret_cast<PySyclQueueObject *>(queue_pycapi));
39+
q_ptr = reinterpret_cast<sycl::queue *>(QRef);
40+
}
41+
else {
42+
throw std::runtime_error("expected dpctl.SyclQueue as argument");
43+
}
44+
45+
py::buffer_info arg_pybuf = array.request();
46+
if (arg_pybuf.ndim != 1) {
47+
throw std::runtime_error("Expecting a vector");
48+
}
49+
if (mod <= 0) {
50+
throw std::runtime_error("Modulus must be non-negative");
51+
}
52+
53+
size_t n = arg_pybuf.size;
54+
55+
auto res = py::array_t<int64_t>(n);
56+
py::buffer_info res_pybuf = res.request();
57+
58+
int64_t *a = static_cast<int64_t *>(arg_pybuf.ptr);
59+
int64_t *r = static_cast<int64_t *>(res_pybuf.ptr);
60+
61+
{
62+
const sycl::property_list props = {
63+
sycl::property::buffer::use_host_ptr()};
64+
sycl::buffer<int64_t, 1> a_buf(a, sycl::range<1>(n), props);
65+
sycl::buffer<int64_t, 1> r_buf(r, sycl::range<1>(n), props);
66+
67+
q_ptr
68+
->submit([&](sycl::handler &cgh) {
69+
sycl::accessor a_acc(a_buf, cgh, sycl::read_only);
70+
sycl::accessor r_acc(r_buf, cgh, sycl::write_only,
71+
sycl::noinit);
72+
73+
cgh.parallel_for(sycl::range<1>(n), [=](sycl::id<1> idx) {
74+
r_acc[idx] = a_acc[idx] % mod;
75+
});
76+
})
77+
.wait_and_throw();
78+
}
79+
80+
return res;
81+
}
82+
83+
PYBIND11_MODULE(pybind11_example, m)
84+
{
85+
// Import the dpctl._sycl_queue extension
86+
import_dpctl___sycl_queue();
87+
m.def("get_max_compute_units", &get_max_compute_units,
88+
"Computes max_compute_units property of the device underlying given "
89+
"dpctl.SyclQueue");
90+
m.def("offloaded_array_mod", &offloaded_array_mod,
91+
"Compute offloaded modular reduction of integer-valued NumPy array");
92+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Data Parallel Control (dpctl)
2+
#
3+
# Copyright 2020-2021 Intel Corporation
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
from pybind11.setup_helpers import Pybind11Extension
18+
from setuptools import setup
19+
20+
import dpctl
21+
22+
exts = [
23+
Pybind11Extension(
24+
"pybind11_example",
25+
["./pybind11_example.cpp"],
26+
include_dirs=[dpctl.get_include()],
27+
extra_compile_args=["-fPIC"],
28+
extra_link_args=["-fPIC"],
29+
language="c++",
30+
),
31+
]
32+
33+
setup(name="pybind11_example", ext_modules=exts)

0 commit comments

Comments
 (0)