Skip to content

Commit fc9371f

Browse files
Extend the extenal_usm_allocation pybind11 example
The example now also demonstration zero-copy creation of MemoryUSMDevice Python object from allocation created and populated in C++.
1 parent e4a72a9 commit fc9371f

File tree

5 files changed

+97
-5
lines changed

5 files changed

+97
-5
lines changed

examples/pybind11/external_usm_allocation/README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
# Exposing USM Allocations Made by the Native Code to dpctl
22

3-
This extension demonstrates how a Python object backed by
3+
This extension demonstrates how a Python object representing
44
a native class, which allocates USM memory, can expose it
5-
to the `dpctl.memory` entities using `__sycl_usm_array_interface__`.
5+
to the `dpctl.memory` entities using `__sycl_usm_array_interface__`,
6+
and how to create `dpctl.memory` object from allocation made
7+
in native extension.
68

79

810
## Building
@@ -29,4 +31,10 @@ shared
2931
[1.0, 1.0, 0.0, 2.0, 2.0]
3032
[0.0, 0.0, 0.0, 3.0, -1.0]
3133
[0.0, 0.0, 0.0, -1.0, 5.0]
34+
35+
========================================
36+
device
37+
64
38+
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
39+
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
3240
```

examples/pybind11/external_usm_allocation/example.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,10 @@
5050
list_of_lists = matr.tolist()
5151
for row in list_of_lists:
5252
print(row)
53+
54+
print("====" * 10)
55+
56+
mbuf = eua.make_zeroed_device_memory(4 * 16, q)
57+
print(mbuf.get_usm_type())
58+
print(mbuf.nbytes)
59+
print(mbuf.copy_to_host())

examples/pybind11/external_usm_allocation/external_usm_allocation/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@
1616

1717
# coding: utf-8
1818

19-
from ._external_usm_alloc import DMatrix
19+
from ._external_usm_alloc import DMatrix, make_zeroed_device_memory
2020

21-
__all__ = ["DMatrix"]
21+
__all__ = ["DMatrix", "make_zeroed_device_memory"]
2222

2323
__doc__ = """
2424
Example of implementing C++ class with its own USM memory allocation logic

examples/pybind11/external_usm_allocation/external_usm_allocation/_usm_alloc_example.cpp

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,12 @@
3131
/// content of the object into list of lists of Python floats.
3232
///
3333
//===----------------------------------------------------------------------===//
34-
#include <CL/sycl.hpp>
34+
#include <sycl/sycl.hpp>
3535

3636
#include "dpctl4pybind11.hpp"
3737
#include "pybind11/pybind11.h"
3838
#include "pybind11/stl.h"
39+
#include <memory>
3940

4041
namespace py = pybind11;
4142

@@ -120,6 +121,42 @@ py::list tolist(DMatrix &m)
120121
return rows;
121122
}
122123

124+
class USMDeleter
125+
{
126+
public:
127+
USMDeleter() = delete;
128+
USMDeleter(const USMDeleter &) = default;
129+
USMDeleter(USMDeleter &&) = default;
130+
USMDeleter(const ::sycl::queue &queue) : _context(queue.get_context()) {}
131+
USMDeleter(const ::sycl::context &context) : _context(context) {}
132+
133+
/*! @brief call operator to delete resources */
134+
template <typename T> void operator()(T *ptr) const
135+
{
136+
try {
137+
::sycl::free(ptr, _context);
138+
} catch (const std::exception &e) {
139+
std::cout << "Call to sycl::free caught an exception: " << e.what()
140+
<< std::endl;
141+
}
142+
}
143+
144+
private:
145+
::sycl::context _context;
146+
};
147+
148+
dpctl::memory::usm_memory make_zeroed_device_memory(size_t nbytes,
149+
sycl::queue &q)
150+
{
151+
char *data = sycl::malloc_device<char>(nbytes, q);
152+
q.memset(data, 0, nbytes).wait();
153+
154+
USMDeleter _deleter(q);
155+
auto shptr = std::shared_ptr<void>(data, _deleter);
156+
157+
return dpctl::memory::usm_memory(data, nbytes, q, shptr);
158+
}
159+
123160
PYBIND11_MODULE(_external_usm_alloc, m)
124161
{
125162
py::class_<DMatrix> dm(m, "DMatrix");
@@ -128,4 +165,7 @@ PYBIND11_MODULE(_external_usm_alloc, m)
128165
dm.def_property("__sycl_usm_array_interface__", &construct_sua_iface,
129166
nullptr);
130167
dm.def("tolist", &tolist, "Return matrix a Python list of lists");
168+
169+
m.def("make_zeroed_device_memory", &make_zeroed_device_memory,
170+
"Returns zero-initialized USM-device allocation created C++");
131171
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Data Parallel Control (dpctl)
2+
#
3+
# Copyright 2020-2024 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 external_usm_allocation as eua
20+
21+
import dpctl
22+
import dpctl.memory as dpm
23+
import dpctl.tensor as dpt
24+
25+
26+
def test_direct():
27+
q = dpctl.SyclQueue()
28+
29+
nb = 2 * 30
30+
mbuf = eua.make_zeroed_device_memory(nb, q)
31+
32+
assert isinstance(mbuf, dpm.MemoryUSMDevice)
33+
assert mbuf.nbytes == 2 * 30
34+
assert mbuf.sycl_queue == q
35+
36+
x = dpt.usm_ndarray(30, dtype="i2", buffer=mbuf)
37+
assert dpt.all(x == dpt.zeros(30, dtype="i2", sycl_queue=q))

0 commit comments

Comments
 (0)