diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000000..c3e24cdef6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,47 @@ +name: Bug report +description: Report incorrect behavior, a crash, or a build failure +labels: ["bug"] +body: + - type: textarea + id: description + attributes: + label: Description + description: What happened, and what did you expect? + validations: + required: true + - type: textarea + id: reproducer + attributes: + label: Reproducer + description: Minimal code or commands that trigger the problem. + render: python + validations: + required: true + - type: textarea + id: output + attributes: + label: Output + description: Full traceback or error output. Run with `DPCTL_VERBOSITY=warning` for C API diagnostics. + render: shell + - type: input + id: version + attributes: + label: dpctl version + description: Output of `python -c "import dpctl; print(dpctl.__version__)"`, or N/A if dpctl fails to build or import + validations: + required: true + - type: textarea + id: devices + attributes: + label: Devices + description: Output of `python -m dpctl -f` (or `sycl-ls` if dpctl fails to import) + render: shell + validations: + required: true + - type: textarea + id: environment + attributes: + label: Environment + description: OS, Python version (and whether free-threaded), how dpctl was installed (conda/pip/source), DPC++ runtime version (`intel-sycl-rt` in `conda list`/`pip list`), DPC++ compiler version if built from source. + validations: + required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..55236ef43e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,8 @@ +blank_issues_enabled: true +contact_links: + - name: Questions and discussions + url: https://github.com/IntelPython/dpctl/discussions/categories/q-a + about: Ask usage questions here. + - name: Security vulnerabilities + url: https://github.com/IntelPython/dpctl/blob/master/SECURITY.md + about: Report security issues privately, not as public issues. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000000..7199c41532 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,23 @@ +name: Feature request +description: Propose new SYCL functionality or an API change +labels: ["enhancement"] +body: + - type: textarea + id: motivation + attributes: + label: Motivation + description: What do you need to do that dpctl does not support today? + validations: + required: true + - type: textarea + id: proposal + attributes: + label: Proposed API + description: Python, Cython, or C API you would like, and the SYCL feature it maps to. + validations: + required: true + - type: textarea + id: alternatives + attributes: + label: Alternatives considered + description: Optional. Workarounds you use today, or other designs you considered. diff --git a/.gitignore b/.gitignore index f8d185c7a9..0783592b9b 100644 --- a/.gitignore +++ b/.gitignore @@ -104,3 +104,14 @@ dpctl/resources/cmake # asv artifacts *.asv* + +# agent-related +.claude/settings.local.json +.claude/worktrees/ + +# virtual environments, test caches, local env files +.venv/ +venv/ +.pytest_cache/ +.env +.env.* diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000..10a9af5f11 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,146 @@ +# AGENTS.md + +dpctl is a Python/Cython wrapper over a subset of SYCL, built on a C API +library (`libsyclinterface`). It is compiled with Intel oneAPI DPC++ (`icx`/`icpx`). + +## Environment + +- Activate the compiler before building or testing: `source /opt/intel/oneapi/setvars.sh` + (or use a conda env with `dpcpp_linux-64`). The environment does not persist + between shell invocations; source it in the same command: + `source /opt/intel/oneapi/setvars.sh && python -m pytest dpctl/tests/...`. +- Check visible devices: `sycl-ls`. Tests skip on missing devices/aspects; a CPU + OpenCL device is enough for most of the suite. +- Python build deps: `pip install numpy cython scikit-build cmake ninja setuptools pybind11 pytest "versioneer[toml]==0.29"`. + +## Commands + +- Build in place + editable install: `python scripts/build_locally.py --verbose` + - defaults to `icx`/`icpx` on `PATH`; for other compilers pass absolute + `--c-compiler`/`--cxx-compiler` paths, or names plus `--compiler-root=` + - `--debug`, `--clean`, `--target-cuda[=sm_XX]`, `--target-hip=`, + `--cmake-opts="-D..."` + - the first configure clones the Level Zero headers and downloads pybind11; + offline, pass `--no-level-zero` (or + `--cmake-opts="-DDPCTL_LEVEL_ZERO_INCLUDE_DIR="`) and install `pybind11` +- Python tests: `python -m pytest dpctl/tests` + - one file: `python -m pytest dpctl/tests/test_sycl_queue.py` + - one test: `python -m pytest dpctl/tests/test_sycl_queue_memset.py::test_memset_partial_count` + - without a C compiler/Cython: add `-k "not test_cython_api and not test_c_headers"` +- C API tests (Linux; GoogleTest must be findable by CMake, e.g. via `GTEST_ROOT`): + `(cd libsyclinterface && bash dbg_build.sh)` +- Coverage (Linux; C + Python, rebuilds in place with `-DDPCTL_BUILD_CAPI_TESTS=ON`, + then runs the full pytest suite unless `--skip-pytest`): `python scripts/gen_coverage.py`, + then `python scripts/build_locally.py --clean` for a normal build +- Docs (Linux only; needs Doxygen and the `docs` extras from `pyproject.toml`): + `python scripts/gen_docs.py`, plus `--doxyrest-root=` for the C API reference +- Lint/format one file (no build needed): `pre-commit run --files ` +- Lint/format everything: `pre-commit run --all-files` + (black, isort, flake8, cython-lint, clang-format, codespell, bandit, shellcheck, + gitleaks, actionlint). Config: `pyproject.toml`, `.flake8`, `.clang-format`. + +## Structure + +- `libsyclinterface/` — C API over SYCL (C++ implementation) + - `include/syclinterface/*.h` — public C headers, `DPCTL_` functions + - `source/*.cpp` — implementations + - `helper/` — error handlers and enum/string conversion utils + - `tests/*.cpp` — GoogleTest suite; `*.spv` are prebuilt kernel fixtures +- `dpctl/` — Python package + - `_backend.pxd` — Cython `extern` declarations of the C API + - `_sycl_*.pyx/.pxd` — `SyclDevice`, `SyclQueue`, `SyclContext`, `SyclEvent`, ... + - `memory/` — USM memory objects (`MemoryUSMDevice`, ...), IPC memory + - `compiler/` — `SyclKernelBundle` creation (SPIR-V, SYCL source) + - `program/` — deprecated alias of `dpctl.compiler` + - `utils/` — order manager, device queries, Intel device info + - `apis/include/` — Python C-API headers for extensions (`dpctl_capi.h`, `dpctl4pybind11.hpp`) + - `tests/` — pytest suite; `tests/helper/` has `get_queue_or_skip` and friends +- `examples/` — python, cython, pybind11, c extension examples (each with README) +- `docs/doc_sources/` — Sphinx sources +- `conda-recipe/`, `conda-recipe-cf/` — conda packaging used by CI +- `scripts/` — build, coverage, docs drivers +- `benchmarks/` — asv benchmarks +- `cmake/` — CMake config for downstream projects (`dpctl-config.cmake`) + +## Adding a SYCL feature (typical PR shape) + +1. Declare in `libsyclinterface/include/syclinterface/dpctl_sycl__interface.h` + with a Doxygen comment and ownership attributes. For an existing SYCL type, + extend its files in steps 1-4 rather than creating new ones. +2. Implement in `libsyclinterface/source/dpctl_sycl__interface.cpp`. +3. Add GoogleTest cases in `libsyclinterface/tests/test_sycl__interface.cpp`. +4. Declare in `dpctl/_backend.pxd`; wrap in `dpctl/_sycl_.pyx` (and `.pxd` if + the method is `cdef` or `cpdef`). +5. Add pytest coverage in `dpctl/tests/`. +6. Export new public names (e.g. enums) in `dpctl/__init__.py` and list them in + `docs/doc_sources/api_reference/dpctl/*.rst`. +7. For user-visible changes, add a `CHANGELOG.md` entry (see Git). + +Reference PRs to copy from: +- New queue operation: gh-2361 (`DPCTLQueue_MemsetWithEvents` → + `SyclQueue.memset`/`memset_async`, `dpctl/tests/test_sycl_queue_memset.py`). +- New device info query: gh-2324 (`dpctl_sycl_device_interface.h` → + `dpctl/_sycl_device.pyx`; add a `check_(device)` to `list_of_checks` in + `dpctl/tests/_device_attributes_checks.py`). New enums go through + `dpctl_sycl_enum_types.h`, `libsyclinterface/helper/`, and `dpctl/enum_types.py`. + +## Conventions + +### C API +- Opaque refs (`DPCTLSyclQueueRef`, ...) via `wrap`/`unwrap` + (`dpctl_sycl_type_casters.hpp`). +- Annotate ownership: `__dpctl_give` (caller must delete), `__dpctl_take` + (callee consumes), `__dpctl_keep` (borrowed). See `Support/MemOwnershipAttrs.h`. +- Never let a C++ exception cross the C boundary: catch, call + `error_handler(e, __FILE__, __func__, __LINE__)`, return `nullptr`/error value. +- Null-check every incoming ref and report via `error_handler`. +- Errors are silent unless `DPCTL_VERBOSITY` is set; use `warning` when debugging + a `nullptr` return (`error` hides the null-ref messages). + +### Cython / Python +- Release the GIL (`with nogil:`) around calls that may block on the device. +- Python-visible errors: raise specific exceptions (`TypeError`, `ValueError`, + `SyclQueueCreationError`, ...) when the C API returns `NULL`. +- Free-threaded CPython (3.14t) is supported; do not rely on the GIL for + thread safety of shared state. New `.pyx` files need + `# cython: freethreading_compatible = True`, like the existing ones. +- Line length 80 (black, isort, cython-lint, clang-format). + +### Tests +- Create queues with `get_queue_or_skip()` (`dpctl/tests/helper`) or + `try: dpctl.SyclQueue()` / `except dpctl.SyclQueueCreationError: pytest.skip(...)`; + skip on missing aspects, never assume a GPU or fp64 support. +- Test both sync and `*_async` variants when adding queue operations. + +### Files +- New files need the Apache-2.0 license header from `CONTRIBUTING.md` with the + current year; all C/C++ files (not only headers) also need the `\file` Doxygen block. +- Comments and docstrings: short, describe what the code does. + +## Git + +- Branch off `master`; pre-commit blocks commits directly to `master` and + `maintenance/*`. +- One concern per PR; fill in `.github/pull_request_template.md`. +- Update `CHANGELOG.md` under `## [dev]` (Keep a Changelog sections: Added, Changed, + Deprecated, Removed, Fixed, Maintenance) for user-visible changes, e.g. + `* Added ... [gh-NNNN](https://github.com/IntelPython/dpctl/pull/NNNN)`; the + number is only known once the PR is opened. + +## Boundaries + +- Generated, do not edit: `dpctl/*.cxx`, `dpctl/**/*.cxx`, `dpctl/include/` + (headers copied/generated at build time), `_skbuild/`, `build/`. +- `dpctl/_version.py` is a committed, vendored versioneer file; do not edit it by hand. +- Edit C headers in `libsyclinterface/include/` and Python C-API headers in + `dpctl/apis/include/`, not their copies under `dpctl/include/`. + `Config/dpctl_config.h` is generated from `dpctl_config.h.in`; edit the `.in`. +- In-place `.so` files survive branch switches; rebuild (`--clean`) before + trusting test results after checking out another branch. +- Changing an existing C API signature or enum value is a breaking change: + call it out in the PR and in a `**NOTE**: This release contains breaking changes:` + list at the top of the `[dev]` section (as under 0.23.0). +- `.github/workflows/` actions are pinned to commit SHAs (checked by zizmor); + keep that when adding steps. +- Don't change `conda-recipe*/`, release versions, or `docs/doc_versions.txt` + unless asked; call such changes out in the PR.