Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python module mutli-platform setup #519

Merged
merged 7 commits into from
Jan 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ Development version (next version)
* Convert float scalar values to cl_half for fp16 routines
* Amax/amin, max/min routines accept unsigned integer buffers for index
- Generator script now always use LF endings, independent of the platform
- Switch to pyproject.toml file for installing python bindings
- Build python binding using Cmake, adding Windows support

Version 1.6.1
- Fix pointer error in pyclblast on Arm
Expand Down
67 changes: 67 additions & 0 deletions src/pyclblast/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
cmake_minimum_required(VERSION 3.20)
project(${SKBUILD_PROJECT_NAME} LANGUAGES CXX)

# Find python and numpy
find_package(
Python3
REQUIRED
COMPONENTS Interpreter Development.Module NumPy
)

# Run the cython compiler
cmake_path(APPEND CMAKE_CURRENT_SOURCE_DIR "./src"
OUTPUT_VARIABLE Cython_SOURCE_DIR)
find_program(CYTHON "cython")
add_custom_command(
OUTPUT "${Cython_SOURCE_DIR}/pyclblast.cpp"
DEPENDS "${Cython_SOURCE_DIR}/pyclblast.pyx"
VERBATIM
COMMAND "${CYTHON}" -3 "${Cython_SOURCE_DIR}/pyclblast.pyx"
--output-file "${Cython_SOURCE_DIR}/pyclblast.cpp")


# Add module target
Python3_add_library(pyclblast MODULE WITH_SOABI
"${Cython_SOURCE_DIR}/pyclblast.cpp")

# Numpy libraries - NOTE: clean NPY_LIBRARIES cache (may fail for venv)
cmake_path(GET Python3_NumPy_INCLUDE_DIRS PARENT_PATH Python3_NumPy_CORE_DIR)
unset(NPY_LIBRARIES CACHE)
find_library(NPY_LIBRARIES
NAMES npymath
PATHS ${Python3_NumPy_CORE_DIR}
PATH_SUFFIXES lib
DOC "Numpy math library"
REQUIRED
NO_DEFAULT_PATH)
target_link_libraries(pyclblast PRIVATE ${NPY_LIBRARIES})
target_include_directories(pyclblast PRIVATE ${Python3_NumPy_INCLUDE_DIRS})

# CLBlast library
set(CLBLAST_HINTS
${CLBLAST_ROOT}
$ENV{CLBLAST_ROOT}
)
find_package(CLBlast CONFIG REQUIRED HINTS ${CLBLAST_HINTS})
target_link_libraries(pyclblast PRIVATE clblast)

install(TARGETS pyclblast DESTINATION .)

# In windows pyclblast cannot find the dll, even on path.
# Probably related to change in 3.8, that loads dll only for trusted location
# see https://stackoverflow.com/questions/41365446/how-to-resolve-importerror-dll-load-failed-on-python
# One workaround is to copy the dll to the same dir as the module.
# TODO: add python version check
if (WIN32)
cmake_path(APPEND CLBlast_DIR "../../../bin" OUTPUT_VARIABLE CLBlast_BINDIR)
cmake_path(SET CLBlast_BINDIR NORMALIZE "${CLBlast_BINDIR}")
unset(CLBlast_SHARED_LIBPATH CACHE)
find_file(CLBlast_SHARED_LIBPATH
NAMES clblast.dll
PATHS ${CLBlast_BINDIR}
DOC "CLBlast shared library"
REQUIRED)

# copy dll to build
install(FILES ${CLBlast_SHARED_LIBPATH} DESTINATION .)
endif()
3 changes: 2 additions & 1 deletion src/pyclblast/MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
include README.md setup.py src/*.pyx
include README.md src/*.pyx
include samples/*.py
include CMakeLists.txt
36 changes: 23 additions & 13 deletions src/pyclblast/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,39 @@ Non-Python requirements:
* OpenCL
* [CLBlast](https://github.com/CNugteren/CLBlast)

Python requirements:

* Cython
* [PyOpenCL](https://github.com/pyopencl/pyopencl/)


Getting started
-------------

After installation OpenCL and CLBlast, simply use pip to install PyCLBlast, e.g.:
After installing OpenCL and CLBlast, simply use pip to install PyCLBlast, e.g.:

pip install --user pyclblast

To start using the library, browse the [CLBlast](https://github.com/CNugteren/CLBlast) documentation or check out the PyCLBlast samples provides in the `samples` subfolder.
To start using the library, browse the [CLBlast](https://github.com/CNugteren/CLBlast) documentation or check out the PyCLBlast samples provided in the `samples` subfolder.

For developers, install CLBlast and [cython](https://cython.org/) (e.g. in a Python3 virtualenv):

pip install Cython

And then compile the bindings from this location using pip:

pip install .


Detecting CLBlast
-------------

The CLBlast library should be present and detectable to your system, to successfully install the PyCLBlast bindings. In some systems, this is done automatically. But if the CLBlast library cannot be detected, the PyCLBlast installation will fail. To ensure detection, one can apply either of the following:

For developers, first install CLBlast, followed by the Python requirements (e.g. in a Python3 virtualenv):
* Add the CLBLast root directory to the environment path.
* Create the environment variable `CLBLAST_ROOT` that holds the path to the CLBLast root directory.
* Define the `cmake` variables `CMAKE_PREFIX_PATH` or the `CLBLAST_ROOT` variable that point to the CLBlast root directory, as:

pip install Cython numpy pybind11
pip install pyopencl
pip install . -C skbuild.cmake.args="-DCMAKE_PREFIX_PATH=/root/path/to/clblast"

And then compile the library from this location using the `setup.py` file:
* Create the environment variable `CLBlast_DIR` that holds the path to the directory where either of the `CLBlastConfig.cmake` or `clblast-config.cmake` files reside.

python setup.py install
Note that the aforementioned environment variables should be set only during the installation of PyCLBlast and can be unset during normal use.


Testing PyCLBlast
Expand All @@ -53,6 +63,6 @@ How to release a new version on PyPi

Following [the guide](https://packaging.python.org/tutorials/packaging-projects/), in essence doing (after changing the version number in `setup.py`):

python3 setup.py sdist bdist_wheel
python3 -m build
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This did not work for me, while the old command does still work:

:~/CLBlast/src/pyclblast$ python3 -m build
python3: No module named build.__main__; 'build' is a package and cannot be directly executed

And if I remove that folder then I get No module named build. This is with the relatively old Python 3.7.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi,

No worries for the time taken, it is a festive period after all.
I have updated the changelog file.

Regarding the error, it seems to me that you have not installed the build python package. Running python3 -m pip install --upgrade build (or install it through your linux distro package manager) should make it work.
Keep in mind that the python -m build method for packaging, is the one currently described in the guide in the README.md link.
Let me know if the error persists after you install the build package.

One more unrelated thing, it would be good to add 'hints' (if you have any suggestion) for cmake to find the CLBlast library.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes of course, thanks that fixes it. I got confused because I also had a local build folder, and didn't think of build as a Python package. It does build now and the tests pass.

One more unrelated thing, it would be good to add 'hints' (if you have any suggestion) for cmake to find the CLBlast library.

Hmm yes indeed. Not sure what those locations would be though. Perhaps something similar to what I did for the clBLAS library here: https://github.com/CNugteren/CLBlast/blob/master/cmake/Modules/FindclBLAS.cmake#L25?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added some hints for CLBlast in the CMakeLists.txt file and updated the README.md to inform the user about them.

python3 -m twine upload --repository pypi dist/pyclblast-1.4.0.tar.gz
# use '__token__' as username and supply the token from your PyPi account
32 changes: 32 additions & 0 deletions src/pyclblast/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[build-system]
requires = ["scikit-build-core", "cython", "numpy"]
build-backend = "scikit_build_core.build"

[project]
name = "pyclblast"
version = "1.4.0"
description = "Python bindings for CLBlast, the tuned OpenCL BLAS library"
authors = [
{name = "Cedric Nugteren", email = "[email protected]"}
]
license = {text = "Apache Software License"}
readme = "README.md"
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Topic :: Software Development :: Libraries",
"License :: OSI Approved :: Apache Software License",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 3",
]
keywords = ["OpenCL", "BLAS", "CLBlast", "GEMM", "matrix-multiplication"]
dependencies = [
"numpy",
"pyopencl"
]

[project.urls]
Homepage = "https://github.com/CNugteren/CLBlast/blob/master/src/pyclblast"

[tool.setuptools.packages.find]
where = ["src"]
61 changes: 0 additions & 61 deletions src/pyclblast/setup.py

This file was deleted.