You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 6ef42b4
Browse filesBrowse the repository at this point in the historyBrowse files
* ✅ **Studio Quality:** 32-bit floating-point precision (float32) to prevent color banding.
40
40
* ✅ **Advanced Memory Control:** Reuse GPU buffers across operations and resize without reallocation—critical for video processing and batch workflows.
41
41
* ✅ **OpenGL Integration:** Direct GPU-to-GPU display for real-time preview widgets.
42
+
* ✅ **CUDA Interop (Zero-Copy):** Native `__cuda_array_interface__` v3 support. Share GPU buffers with CuPy, PyTorch, Numba and the rest of the CUDA Python ecosystem without copies.
42
43
* ✅ **API Simplicity:** Intuitive, Pythonic API designed for ease of use.
PyImageCUDA images implement the [`__cuda_array_interface__`](https://numba.readthedocs.io/en/stable/cuda/cuda_array_interface.html) v3 protocol. This allows any library in the CUDA Python ecosystem (CuPy, PyTorch, Numba, RAPIDS, JAX with the CUDA backend, etc.) to read **and write** the image's GPU memory **without any copies**.
160
+
161
+
The memory layout exposed is `(height, width, 4)` interleaved RGBA, row-major contiguous:
162
+
163
+
-`Image` → `float32` (typestr `<f4`)
164
+
-`ImageU8` → `uint8` (typestr `|u1`)
165
+
166
+
!!! warning "Memory ownership"
167
+
The CUDA buffer is owned by the `Image` / `ImageU8` instance. The image **must stay alive** while any external array views it, otherwise the view becomes a dangling pointer. Do **not** call `image.free()` while a CuPy / Torch tensor still references it.
168
+
169
+
---
170
+
171
+
### Raw device pointer
172
+
173
+
Use the `cuda_ptr` property to retrieve the raw CUDA device pointer as a Python `int`. Useful for custom kernels or low-level interop.
174
+
```python
175
+
from pyimagecuda import Image
176
+
177
+
img = Image(1920, 1080)
178
+
print(hex(img.cuda_ptr)) # e.g. 0x7f1234500000
179
+
```
180
+
181
+
---
182
+
183
+
### CuPy
184
+
185
+
The `to_cupy()` helper wraps a pyimagecuda image as a zero-copy `cupy.ndarray`. CuPy is **not** a dependency of pyimagecuda; install it separately:
186
+
```bash
187
+
pip install cupy-cuda12x # or cupy-cuda11x for CUDA 11
188
+
```
189
+
```python
190
+
from pyimagecuda import Image, Fill, to_cupy, download
191
+
import cupy as cp
192
+
193
+
img = Image(512, 512)
194
+
Fill.color(img, (1, 0, 0, 1))
195
+
196
+
# Zero-copy view — shares the same GPU memory
197
+
arr = to_cupy(img)
198
+
assert arr.data.ptr == img.cuda_ptr
199
+
assert arr.shape == (512, 512, 4)
200
+
assert arr.dtype == cp.float32
201
+
202
+
# Modify via CuPy → changes are visible in the pyimagecuda image
203
+
arr[:, :, 1] =1.0# add green channel
204
+
205
+
# Download to verify
206
+
pixels = download(img)
207
+
```
208
+
209
+
Because `__cuda_array_interface__` is honored, `cp.asarray(img)` works too:
210
+
```python
211
+
arr = cp.asarray(img) # zero-copy
212
+
```
213
+
214
+
---
215
+
216
+
### Custom CUDA kernels (CuPy RawKernel)
217
+
218
+
You can run your own CUDA kernels directly on pyimagecuda buffers:
0 commit comments