Skip to content

Commit ffaa535

Browse files
committed
improved version of documentation
1 parent d1e5c3a commit ffaa535

File tree

14 files changed

+375
-2505
lines changed

14 files changed

+375
-2505
lines changed

.github/instructions/cython.instructions.md

Lines changed: 9 additions & 229 deletions
Original file line numberDiff line numberDiff line change
@@ -5,241 +5,21 @@ applyTo:
55
- "dpctl/**/*.pxi"
66
---
77

8-
# Cython Bindings Instructions
8+
# Cython Instructions
99

10-
## Context
10+
See [dpctl/AGENTS.md](/dpctl/AGENTS.md) for conventions and patterns.
1111

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):
12+
## Quick Reference
2513

14+
### Required Directives (after license header)
2615
```cython
2716
# distutils: language = c++
2817
# cython: language_level=3
2918
# cython: linetrace=True
3019
```
3120

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-
```
21+
### Key Rules
22+
- `cimport` for C-level declarations, `import` for Python
23+
- Store C refs as `_*_ref`, clean up in `__dealloc__`
24+
- Use `with nogil:` for blocking C operations
25+
- Check NULL before using C API returns

.github/instructions/dpctl.instructions.md

Lines changed: 10 additions & 119 deletions
Original file line numberDiff line numberDiff line change
@@ -3,133 +3,24 @@ applyTo:
33
- "**/*.py"
44
- "**/*.pyx"
55
- "**/*.pxd"
6-
- "**/*.pxi"
76
- "**/*.cpp"
87
- "**/*.hpp"
98
- "**/*.h"
10-
- "**/*.c"
119
---
1210

1311
# DPCTL General Instructions
1412

15-
## Project Context
13+
See [/AGENTS.md](/AGENTS.md) for project overview and architecture.
1614

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`)
15+
## Key References
2216

23-
## License Header Requirement
17+
- **Code style:** See `.pre-commit-config.yaml` for tool versions, `.clang-format` for C++ style
18+
- **License:** Apache 2.0 with Intel copyright - see existing files for header format
19+
- **Directory guides:** Each major directory has its own `AGENTS.md`
2420

25-
**All source files must include the Apache 2.0 license header.**
21+
## Critical Rules
2622

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-
```
23+
1. **Device compatibility:** Not all devices support fp64/fp16 - check capabilities
24+
2. **Queue consistency:** All arrays in an operation must share compatible queues
25+
3. **Resource cleanup:** Always clean up C resources in `__dealloc__`
26+
4. **NULL checks:** Always check C API returns before use

0 commit comments

Comments
 (0)