Skip to content

Commit

Permalink
Switch from pybind11 to nanobind
Browse files Browse the repository at this point in the history
  • Loading branch information
inducer committed May 3, 2024
1 parent a44befb commit 8c421ee
Show file tree
Hide file tree
Showing 17 changed files with 504 additions and 456 deletions.
7 changes: 6 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ jobs:
curl -L -O https://tiker.net/ci-support-v0
. ci-support-v0
build_py_project_in_conda_env
# Avoid linting local directory, where native module
# cannot be imported.
rm -Rf "$(get_proj_name)"
run_pylint "$(get_proj_name)" test/*.py
mypy:
Expand Down Expand Up @@ -122,7 +127,7 @@ jobs:
curl -L -O https://tiker.net/ci-support-v0
. ci-support-v0
./configure.py --cxxflags= --ldflags= --cl-libname=OpenCL
./configure.py --cl-libname=OpenCL
build_py_project_in_conda_env
test_py_project
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
_skbuild

.pydevproject
.project
.settings
Expand Down
25 changes: 0 additions & 25 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -165,31 +165,6 @@ Python 3 POCL (+GL and special functions):
reports:
junit: test/pytest.xml

PyPy3 POCL:
script: |
export PY_EXE=pypy3
export PYOPENCL_TEST=portable:pthread
export NO_DOCTESTS=1
# On pypy, this seems to install old versions from the package index
# independently of whether newer ones are already present.
rm -f pyproject.toml
export EXTRA_INSTALL="pybind11 numpy mako"
curl -L -O https://tiker.net/ci-support-v0
. ci-support-v0
build_py_project_in_venv
test_py_project
tags:
- pypy
- pocl
except:
- tags
artifacts:
reports:
junit: test/pytest.xml

Flake8:
script: |
curl -L -O https://tiker.net/ci-support-v0
Expand Down
79 changes: 79 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
cmake_minimum_required(VERSION 3.17...3.22)

project(pyopencl)

if (NOT SKBUILD)
message(FATAL_ERROR "This CMake file should be executed via scikit-build. "
"Please run\n$ pip install .")
endif()

# {{{ Constrain FindPython to find the Python version used by scikit-build

if (SKBUILD)
message(STATUS "Python_VERSION ${PYTHON_VERSION_STRING}")
message(STATUS "Python_EXECUTABLE ${PYTHON_EXECUTABLE}")
message(STATUS "Python_INCLUDE_DIR ${PYTHON_INCLUDE_DIR}")
message(STATUS "Python_LIBRARIES ${PYTHON_LIBRARY}")
set(Python_VERSION "${PYTHON_VERSION_STRING}")
set(Python_EXECUTABLE "${PYTHON_EXECUTABLE}")
set(Python_INCLUDE_DIR "${PYTHON_INCLUDE_DIR}")
set(Python_LIBRARIES "${PYTHON_LIBRARY}")
endif()
find_package(Python COMPONENTS Interpreter Development.Module REQUIRED)

# }}}

# {{{ Detect nanobind and import it

execute_process(
COMMAND
"${PYTHON_EXECUTABLE}" -c "import nanobind; print(nanobind.cmake_dir())"
OUTPUT_VARIABLE _tmp_dir
OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ECHO STDOUT)
list(APPEND CMAKE_PREFIX_PATH "${_tmp_dir}")

# }}}

link_directories(${PYOPENCL_CL_LIB_DIRS})

find_package(nanobind CONFIG REQUIRED)
find_package(NumPy REQUIRED)
find_package(OpenCL REQUIRED)

include_directories(${OpenCL_INCLUDE_DIR} ${NumPy_INCLUDE_DIRS})

nanobind_add_module(
_cl
NB_STATIC # Build static libnanobind (the extension module itself remains a shared library)
src/wrap_constants.cpp
src/wrap_cl.cpp
src/wrap_cl_part_1.cpp
src/wrap_cl_part_2.cpp
src/wrap_mempool.cpp
src/bitlog.cpp
)

target_link_libraries(_cl PRIVATE ${OpenCL_LIBRARY})

target_compile_definitions(_cl
PRIVATE
PYGPU_PACKAGE=pyopencl
PYGPU_PYOPENCL
)

if (PYOPENCL_PRETEND_CL_VERSION)
target_compile_definitions(
_cl PRIVATE PYOPENCL_PRETEND_CL_VERSION=${PYOPENCL_PRETEND_CL_VERSION})
endif()

if (PYOPENCL_ENABLE_GL)
target_compile_definitions(_cl PRIVATE HAVE_GL=1)
endif()

if (PYOPENCL_USE_SHIPPED_EXT)
target_compile_definitions(_cl PRIVATE PYOPENCL_USE_SHIPPED_EXT=1)
endif()

install(TARGETS _cl LIBRARY DESTINATION .)

# vim: foldmethod=marker:sw=2
20 changes: 3 additions & 17 deletions pyopencl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ def build(self, options=None, devices=None, cache_dir=None):
def _build_and_catch_errors(self, build_func, options_bytes, source=None):
try:
return build_func()
except _cl.RuntimeError as e:
except RuntimeError as e:
msg = str(e)
if options_bytes:
msg = msg + "\n(options: %s)" % options_bytes.decode("utf-8")
Expand All @@ -553,7 +553,7 @@ def _build_and_catch_errors(self, build_func, options_bytes, source=None):
code = e.code
routine = e.routine

err = _cl.RuntimeError(
err = RuntimeError(
_cl._ErrorRecord(
msg=msg,
code=code,
Expand Down Expand Up @@ -835,7 +835,7 @@ def kernel_set_arg_types(self, arg_types):
# }}}

from pyopencl.invoker import generate_enqueue_and_set_args
enqueue, my_set_args = \
self._enqueue, self.set_args = \
generate_enqueue_and_set_args(
self.function_name,
len(arg_types), self.num_args,
Expand All @@ -844,20 +844,6 @@ def kernel_set_arg_types(self, arg_types):
work_around_arg_count_bug=work_around_arg_count_bug,
devs=self.context.devices)

# Make ourselves a kernel-specific class, so that we're able to override
# __call__. Inspired by https://stackoverflow.com/a/38541437
class KernelWithCustomEnqueue(type(self)):
__call__ = enqueue
set_args = my_set_args

try:
self.__class__ = KernelWithCustomEnqueue
except TypeError:
# __class__ assignment may not work in all cases, due to differing
# object layouts. Fall back to bouncing through kernel_call below.
self._enqueue = enqueue
self.set_args = my_set_args

def kernel_get_work_group_info(self, param, device):
cache_key = (param, device.int_ptr)
try:
Expand Down
2 changes: 1 addition & 1 deletion pyopencl/invoker.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ def _check_arg_size(function_name, num_cl_args, arg_types, devs):
from pytools.py_codegen import PicklableModule
invoker_cache: WriteOncePersistentDict[Any, Tuple[PicklableModule, str]] \
= WriteOncePersistentDict(
"pyopencl-invoker-cache-v41",
"pyopencl-invoker-cache-v42-nano",
key_builder=_NumpyTypesKeyBuilder(),
in_mem_cache_size=0)

Expand Down
12 changes: 9 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,19 @@ requires = [
"wheel>=0.34.2",
"numpy;python_version >= '3.9' and platform_python_implementation == 'PyPy'",
"oldest-supported-numpy;python_version < '3.9' or platform_python_implementation != 'PyPy'",
"pybind11>=2.5.0"
"scikit-build",
"cmake>=3.17",
"nanobind>=1.9.2",
"ninja; platform_system!='Windows'",
]
build-backend = "setuptools.build_meta"


[tool.cibuildwheel]
test-command = "pytest {project}/test"
test-extras = ["test"]

[tool.cibuildwheel.linux]
skip = ["pp37*", "cp36-*", "cp37-*", "*_i686"]
skip = ["pp*", "cp36-*", "cp37-*", "*_i686"]
test-command = ""
before-all = [
"yum install -y git openssl-devel ruby",
Expand All @@ -42,6 +44,10 @@ archs = "x86_64 arm64"

# https://github.com/conda-forge/pyopencl-feedstock/blob/6f3c5de59b18c9518abba3cb94f6ae92964553f8/recipe/meta.yaml#L62-L63

[tool.cibuildwheel.macos.environment]
# Needed for full C++17 support
MACOSX_DEPLOYMENT_TARGET = "10.14"

[tool.cibuildwheel.windows]
skip = ["*-win32", "pp*", "cp36-*", "cp37-*"]
test-command = ""
Expand Down
1 change: 1 addition & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ multiline-quotes = """
# enable-flake8-bugbear
# enable-isort
# disable-editable-pip-install
[isort]
line_length = 85
Expand Down
Loading

0 comments on commit 8c421ee

Please sign in to comment.