|
| 1 | +# Data Parallel Control (dpctl) |
| 2 | +# |
| 3 | +# Copyright 2020-2025 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 | +""" |
| 18 | +Demonstrates SYCL USM memory usage in Python using dpctl.memory. |
| 19 | +Includes allocation, host access, and host-device copying. |
| 20 | +""" |
| 21 | + |
| 22 | +import numpy as np |
| 23 | + |
| 24 | +import dpctl.memory as dpmem |
| 25 | + |
| 26 | + |
| 27 | +def usm_allocation(): |
| 28 | + """ |
| 29 | + Example demonstrating ways to allocate USM using dpctl.memory. |
| 30 | + """ |
| 31 | + # allocate USM-shared byte-buffer |
| 32 | + ms = dpmem.MemoryUSMShared(16) |
| 33 | + print(f"USM-shared buffer allocated with size: {len(ms)}") |
| 34 | + |
| 35 | + # allocate USM-device byte-buffer |
| 36 | + md = dpmem.MemoryUSMDevice(16) |
| 37 | + print(f"USM-device buffer allocated with size: {len(md)}") |
| 38 | + |
| 39 | + # allocate USM-host byte-buffer |
| 40 | + mh = dpmem.MemoryUSMHost(16) |
| 41 | + print(f"USM-host buffer allocated with size: {len(mh)}") |
| 42 | + |
| 43 | + # specify alignment |
| 44 | + # TODO: add alignment check |
| 45 | + mda = dpmem.MemoryUSMDevice(128, alignment=16) |
| 46 | + print(f"16-byte aligned USM-device buffer allocated with size: {len(mda)}") |
| 47 | + |
| 48 | + # allocate using given queue, |
| 49 | + # i.e. on the device and bound to the context stored in the queue |
| 50 | + mdq = dpmem.MemoryUSMDevice(256, queue=mda.sycl_queue) |
| 51 | + print( |
| 52 | + "USM-device buffers share the same queue: " |
| 53 | + f"{mdq.sycl_queue == mda.sycl_queue}" |
| 54 | + ) |
| 55 | + |
| 56 | + # information about device associate with USM buffer |
| 57 | + print("Allocation performed on device:") |
| 58 | + mda.sycl_queue.print_device_info() |
| 59 | + |
| 60 | + |
| 61 | +def usm_host_access(): |
| 62 | + """ |
| 63 | + Example demonstrating that shared and host USM allocations are |
| 64 | + host-accessible and thus accessible from Python via buffer protocol. |
| 65 | + """ |
| 66 | + # USM-shared and USM-host pointers are host-accessible, |
| 67 | + # meaning they are accessible from Python, therefore |
| 68 | + # they implement Python buffer protocol |
| 69 | + |
| 70 | + # allocate 1K of USM-shared buffer |
| 71 | + ms = dpmem.MemoryUSMShared(1024) |
| 72 | + |
| 73 | + # create memoryview into USM-shared buffer |
| 74 | + msv = memoryview(ms) |
| 75 | + |
| 76 | + # populate buffer from host one byte at a time |
| 77 | + for i in range(len(ms)): |
| 78 | + ir = i % 256 |
| 79 | + msv[i] = ir**2 % 256 |
| 80 | + |
| 81 | + mh = dpmem.MemoryUSMHost(64) |
| 82 | + mhv = memoryview(mh) |
| 83 | + |
| 84 | + # copy content of block of USM-shared buffer to |
| 85 | + # USM-host buffer |
| 86 | + mhv[:] = msv[78 : 78 + len(mh)] |
| 87 | + |
| 88 | + print("Byte-values of the USM-host buffer") |
| 89 | + print(list(mhv)) |
| 90 | + |
| 91 | + # USM-device buffer is not host accessible |
| 92 | + md = dpmem.MemoryUSMDevice(16) |
| 93 | + try: |
| 94 | + memoryview(md) |
| 95 | + except TypeError as e: |
| 96 | + print("") |
| 97 | + print( |
| 98 | + "An expected exception was raised during attempted construction of " |
| 99 | + "memoryview from USM-device memory object." |
| 100 | + ) |
| 101 | + print(f"\t{e}") |
| 102 | + |
| 103 | + |
| 104 | +def usm_host_device_copy(): |
| 105 | + """ |
| 106 | + Example demonstrating copying operations using dpctl.memory. |
| 107 | + """ |
| 108 | + ms = dpmem.MemoryUSMShared(32) |
| 109 | + md = dpmem.MemoryUSMDevice(32) |
| 110 | + |
| 111 | + host_buf = np.random.randint(0, 42, dtype=np.uint8, size=32) |
| 112 | + |
| 113 | + # copy host byte-like object to USM-device buffer |
| 114 | + md.copy_from_host(host_buf) |
| 115 | + |
| 116 | + # copy USM-device buffer to USM-shared buffer in parallel using |
| 117 | + # sycl::queue::memcpy. |
| 118 | + ms.copy_from_device(md) |
| 119 | + |
| 120 | + # build numpy array reusing host-accessible USM-shared memory |
| 121 | + X = np.ndarray((len(ms),), buffer=ms, dtype=np.uint8) |
| 122 | + |
| 123 | + # Display Python object NumPy ndarray is viewing into |
| 124 | + print("numpy.ndarray.base: ", X.base) |
| 125 | + print("") |
| 126 | + |
| 127 | + # Print content of the view |
| 128 | + print("View..........: ", X) |
| 129 | + |
| 130 | + # Print content of the original host buffer |
| 131 | + print("host_buf......: ", host_buf) |
| 132 | + |
| 133 | + # use copy_to_host to retrieve memory of USM-device memory |
| 134 | + print("copy_to_host(): ", md.copy_to_host()) |
| 135 | + |
| 136 | + |
| 137 | +if __name__ == "__main__": |
| 138 | + import _runner as runner |
| 139 | + |
| 140 | + runner.run_examples("Memory examples for dpctl.", globals()) |
0 commit comments