Skip to content

Commit d1e5c3a

Browse files
committed
first version of agents instructions
1 parent ce41a87 commit d1e5c3a

9 files changed

+2635
-0
lines changed
Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
---
2+
applyTo:
3+
- "dpctl/**/*.pyx"
4+
- "dpctl/**/*.pxd"
5+
- "dpctl/**/*.pxi"
6+
---
7+
8+
# Cython Bindings Instructions
9+
10+
## Context
11+
12+
Cython files in dpctl provide the bridge between Python and the C/C++ SYCL interface. They wrap SYCL runtime objects as Python extension types.
13+
14+
## File Types
15+
16+
| Extension | Purpose |
17+
|-----------|---------|
18+
| `.pyx` | Implementation files (compiled to C++) |
19+
| `.pxd` | Declaration files (like C headers) |
20+
| `.pxi` | Include files (textually included) |
21+
22+
## Required Directives
23+
24+
Every `.pyx` file must start with (after license header):
25+
26+
```cython
27+
# distutils: language = c++
28+
# cython: language_level=3
29+
# cython: linetrace=True
30+
```
31+
32+
## Import Conventions
33+
34+
### cimport vs import
35+
36+
```cython
37+
# cimport - for C-level declarations (compile-time)
38+
from cpython cimport pycapsule
39+
from cpython.mem cimport PyMem_Free, PyMem_Malloc
40+
from ._backend cimport DPCTLSyclDeviceRef, DPCTLDevice_Create
41+
42+
# import - for Python-level usage (runtime)
43+
import numpy as np
44+
from . import _device_selection
45+
```
46+
47+
### Import Order
48+
1. Standard library cimports
49+
2. Third-party cimports
50+
3. Local cimports (with `# noqa: E211` if needed)
51+
4. Blank line
52+
5. Standard library imports
53+
6. Third-party imports
54+
7. Local imports
55+
56+
## Extension Type Pattern
57+
58+
```cython
59+
cdef class SyclDevice:
60+
"""
61+
Python wrapper for sycl::device.
62+
63+
Docstring describing the class.
64+
"""
65+
# C-level attribute (not accessible from Python)
66+
cdef DPCTLSyclDeviceRef _device_ref
67+
68+
def __cinit__(self, filter_string=None):
69+
"""
70+
Called before __init__, handles C memory allocation.
71+
Must not raise Python exceptions that leave C state invalid.
72+
"""
73+
if filter_string is not None:
74+
self._device_ref = DPCTLDevice_CreateFromSelector(...)
75+
else:
76+
self._device_ref = NULL
77+
78+
def __dealloc__(self):
79+
"""
80+
Called during garbage collection. Clean up C resources.
81+
"""
82+
if self._device_ref is not NULL:
83+
DPCTLDevice_Delete(self._device_ref)
84+
85+
cdef DPCTLSyclDeviceRef get_device_ref(self):
86+
"""
87+
Internal method for C-level access.
88+
Not visible from Python.
89+
"""
90+
return self._device_ref
91+
92+
@property
93+
def name(self):
94+
"""Python property wrapping C getter."""
95+
cdef const char *name_ptr = DPCTLDevice_GetName(self._device_ref)
96+
if name_ptr is NULL:
97+
raise RuntimeError("Failed to get device name")
98+
try:
99+
return name_ptr.decode("utf-8")
100+
finally:
101+
DPCTLCString_Delete(name_ptr)
102+
```
103+
104+
## Memory Management
105+
106+
### Rule: Always Clean Up in __dealloc__
107+
108+
```cython
109+
def __dealloc__(self):
110+
# Check for NULL before deleting
111+
if self._queue_ref is not NULL:
112+
DPCTLQueue_Delete(self._queue_ref)
113+
```
114+
115+
### Ownership Annotations
116+
117+
Match C API annotations:
118+
- `__dpctl_give` - Caller receives ownership, must delete
119+
- `__dpctl_take` - Function takes ownership, don't use after
120+
- `__dpctl_keep` - Function only observes, doesn't take ownership
121+
122+
```cython
123+
cdef void example():
124+
# Receives ownership (__dpctl_give) - must delete
125+
cdef DPCTLSyclEventRef event = DPCTLQueue_Submit(...)
126+
127+
# ... use event ...
128+
129+
# Clean up owned resource
130+
DPCTLEvent_Delete(event)
131+
```
132+
133+
### GIL Management
134+
135+
Release GIL for blocking C operations:
136+
137+
```cython
138+
cdef void copy_with_wait(DPCTLSyclEventRef event):
139+
with nogil:
140+
DPCTLEvent_Wait(event)
141+
142+
# Or for longer sections
143+
cdef void long_operation() nogil:
144+
# Entire function runs without GIL
145+
# Cannot call Python objects here
146+
pass
147+
```
148+
149+
## Error Handling
150+
151+
### NULL Checks
152+
153+
```cython
154+
cdef DPCTLSyclDeviceRef dref = DPCTLDevice_Create(...)
155+
if dref is NULL:
156+
raise SyclDeviceCreationError("Failed to create device")
157+
```
158+
159+
### Exception Safety
160+
161+
```cython
162+
def create_something(self):
163+
cdef SomeRef ref = SomeFunction()
164+
if ref is NULL:
165+
raise SomeError("Creation failed")
166+
try:
167+
# Operations that might raise
168+
result = self._process(ref)
169+
except:
170+
# Clean up on exception
171+
SomeDelete(ref)
172+
raise
173+
return result
174+
```
175+
176+
## Backend Declarations (.pxd)
177+
178+
```cython
179+
# _backend.pxd
180+
cdef extern from "syclinterface/dpctl_sycl_device_interface.h":
181+
ctypedef void* DPCTLSyclDeviceRef
182+
183+
DPCTLSyclDeviceRef DPCTLDevice_Create(
184+
DPCTLDeviceSelectorRef DSRef
185+
) nogil
186+
187+
void DPCTLDevice_Delete(
188+
DPCTLSyclDeviceRef DRef
189+
) nogil
190+
191+
const char* DPCTLDevice_GetName(
192+
DPCTLSyclDeviceRef DRef
193+
) nogil
194+
```
195+
196+
## Include Files (.pxi)
197+
198+
Used for shared code snippets:
199+
200+
```cython
201+
# In main .pyx file
202+
include "_sycl_usm_array_interface_utils.pxi"
203+
```
204+
205+
## Common Patterns
206+
207+
### Property with C String Return
208+
209+
```cython
210+
@property
211+
def driver_version(self):
212+
cdef const char* ver = DPCTLDevice_GetDriverVersion(self._device_ref)
213+
if ver is NULL:
214+
return ""
215+
try:
216+
return ver.decode("utf-8")
217+
finally:
218+
DPCTLCString_Delete(ver)
219+
```
220+
221+
### Capsule for Opaque Pointers
222+
223+
```cython
224+
def get_capsule(self):
225+
"""Return PyCapsule containing C pointer."""
226+
if self._device_ref is NULL:
227+
return None
228+
return pycapsule.PyCapsule_New(
229+
<void*>self._device_ref,
230+
"SyclDeviceRef",
231+
NULL # No destructor - we manage lifetime
232+
)
233+
```
234+
235+
### Type Checking
236+
237+
```cython
238+
def some_method(self, other):
239+
if not isinstance(other, SyclDevice):
240+
raise TypeError(
241+
f"Expected SyclDevice, got {type(other).__name__}"
242+
)
243+
cdef SyclDevice other_dev = <SyclDevice>other
244+
# Now can access other_dev._device_ref
245+
```
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
---
2+
applyTo:
3+
- "**/*.py"
4+
- "**/*.pyx"
5+
- "**/*.pxd"
6+
- "**/*.pxi"
7+
- "**/*.cpp"
8+
- "**/*.hpp"
9+
- "**/*.h"
10+
- "**/*.c"
11+
---
12+
13+
# DPCTL General Instructions
14+
15+
## Project Context
16+
17+
DPCTL (Data Parallel Control) is a Python SYCL binding library for heterogeneous computing. It provides:
18+
- Python wrappers for SYCL runtime objects (devices, queues, contexts)
19+
- Array API-compliant tensor operations (`dpctl.tensor`)
20+
- USM memory management (`dpctl.memory`)
21+
- Kernel compilation (`dpctl.program`)
22+
23+
## License Header Requirement
24+
25+
**All source files must include the Apache 2.0 license header.**
26+
27+
### Python/Cython Files
28+
```python
29+
# Data Parallel Control (dpctl)
30+
#
31+
# Copyright 2020-2025 Intel Corporation
32+
#
33+
# Licensed under the Apache License, Version 2.0 (the "License");
34+
# you may not use this file except in compliance with the License.
35+
# You may obtain a copy of the License at
36+
#
37+
# http://www.apache.org/licenses/LICENSE-2.0
38+
#
39+
# Unless required by applicable law or agreed to in writing, software
40+
# distributed under the License is distributed on an "AS IS" BASIS,
41+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
42+
# See the License for the specific language governing permissions and
43+
# limitations under the License.
44+
```
45+
46+
### C/C++ Files
47+
```cpp
48+
//===-- filename.hpp - Brief description -*-C++-*-===//
49+
//
50+
// Data Parallel Control (dpctl)
51+
//
52+
// Copyright 2020-2025 Intel Corporation
53+
//
54+
// Licensed under the Apache License, Version 2.0 (the "License");
55+
// ...
56+
//===----------------------------------------------------------------------===//
57+
```
58+
59+
## Code Style
60+
61+
### Python
62+
- **Formatter:** Black (line length 80)
63+
- **Import sorting:** isort
64+
- **Linting:** flake8
65+
- **Max line length:** 80 characters
66+
67+
### C/C++
68+
- **Formatter:** clang-format (LLVM-based)
69+
- **Indent:** 4 spaces
70+
- **Brace style:** Break before functions, classes, namespaces
71+
72+
## Naming Conventions
73+
74+
### Python/Cython
75+
- Classes: `PascalCase` (e.g., `SyclDevice`, `SyclQueue`)
76+
- Functions/methods: `snake_case` (e.g., `get_device_info`)
77+
- Private: prefix with `_` (e.g., `_validate_queue`)
78+
- Constants: `UPPER_SNAKE_CASE`
79+
80+
### C API (libsyclinterface)
81+
- Functions: `DPCTL<Class>_<Method>` (e.g., `DPCTLDevice_Create`)
82+
- Types: `DPCTL<Class>Ref` (e.g., `DPCTLSyclDeviceRef`)
83+
- Macros: `DPCTL_` prefix
84+
85+
### C++ Kernels
86+
- Functors: `<Operation>Functor` (e.g., `AddFunctor`)
87+
- Kernel classes: `<operation>_krn` suffix
88+
- Namespaces: `dpctl::tensor::kernels`
89+
90+
## Error Handling
91+
92+
### Python Exceptions
93+
- `SyclDeviceCreationError` - Device creation failed
94+
- `SyclQueueCreationError` - Queue creation failed
95+
- `ExecutionPlacementError` - Queue mismatch between arrays
96+
- `TypeError`, `ValueError` - Standard Python errors for invalid input
97+
98+
### C API Error Handling
99+
- Return `NULL` for failed object creation
100+
- Use `error_handler_callback` for async errors
101+
- Check return values before using
102+
103+
## Device Compatibility
104+
105+
**Warning:** Not all SYCL devices support all data types.
106+
107+
- **fp64 (double):** Check `device.has_aspect_fp64`
108+
- **fp16 (half):** Check `device.has_aspect_fp16`
109+
110+
Always use `skip_if_dtype_not_supported()` in tests.
111+
112+
## Common Patterns
113+
114+
### Queue Validation
115+
```python
116+
def some_operation(x, y):
117+
exec_q = dpctl.utils.get_execution_queue([x.sycl_queue, y.sycl_queue])
118+
if exec_q is None:
119+
raise ExecutionPlacementError("...")
120+
```
121+
122+
### Resource Cleanup
123+
```python
124+
cdef class SyclDevice:
125+
cdef DPCTLSyclDeviceRef _device_ref
126+
127+
def __dealloc__(self):
128+
DPCTLDevice_Delete(self._device_ref)
129+
```
130+
131+
### GIL Release for Blocking Operations
132+
```cython
133+
with nogil:
134+
DPCTLEvent_Wait(event_ref)
135+
```

0 commit comments

Comments
 (0)