Skip to content

Commit

Permalink
Merge branch 'regression' into spack
Browse files Browse the repository at this point in the history
  • Loading branch information
vancraar committed Feb 4, 2025
2 parents 56ebbff + 4080ef4 commit 4b90f3e
Show file tree
Hide file tree
Showing 27 changed files with 1,278 additions and 1,122 deletions.
52 changes: 23 additions & 29 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -283,35 +283,29 @@ elseif (DEFINED ENV{PLSSVM_TARGET_PLATFORMS})
set(PLSSVM_TARGET_PLATFORMS $ENV{PLSSVM_TARGET_PLATFORMS} CACHE STRING "The target platforms to compile for." FORCE)
else ()
# check for Python3 and all necessary libraries
# find_package(Python3 COMPONENTS Interpreter Development)
# if (NOT Python3_FOUND)
# message(FATAL_ERROR "Can't find Python3. Please manually specify PLSSVM_TARGET_PLATFORMS (e.g. -DPLSSVM_TARGET_PLATFORMS=\"cpu;nvidia:sm_70,sm_86;amd:gfx906;intel:skl\"!")
# endif ()

# include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/check_python_libs.cmake)
# set(PLSSVM_TARGET_PLATFORMS_PYTHON_SCRIPT_REQUIRED_LIBS cpuinfo GPUtil pyamdgpuinfo pylspci)
# message(STATUS "Checking required Python3 libraries (${PLSSVM_TARGET_PLATFORMS_PYTHON_SCRIPT_REQUIRED_LIBS}) to automatically determine the PLSSVM_TARGET_PLATFORMS.")
# set(PLSSVM_TARGET_PLATFORMS_PYTHON_SCRIPT_REQUIRED_LIBS_ERROR_MESSAGE "or manually define PLSSVM_TARGET_PLATFORMS (e.g. -DPLSSVM_TARGET_PLATFORMS=\"cpu;nvidia:sm_70,sm_86;amd:gfx906;intel:skl\"!")
# check_python_libs(${PLSSVM_TARGET_PLATFORMS_PYTHON_SCRIPT_REQUIRED_LIBS} ${PLSSVM_TARGET_PLATFORMS_PYTHON_SCRIPT_REQUIRED_LIBS_ERROR_MESSAGE})

# # run our `plssvm_target_platforms.py` script to determine the PLSSVM_TARGET_PLATFORMS string
# execute_process(
# COMMAND ${Python3_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/utility_scripts/plssvm_target_platforms.py" "--quiet"
# RESULT_VARIABLE PLSSVM_PYTHON_TARGET_PLATFORMS_EXIT_CODE
# OUTPUT_VARIABLE PLSSVM_PYTHON_TARGET_PLATFORMS_OUTPUT
# )
find_package(Python3 COMPONENTS Interpreter Development)
if (NOT Python3_FOUND)
message(FATAL_ERROR "Can't find Python3. Please manually specify PLSSVM_TARGET_PLATFORMS (e.g. -DPLSSVM_TARGET_PLATFORMS=\"cpu;nvidia:sm_70,sm_86;amd:gfx906;intel:skl\"!")
endif ()

# run our `plssvm_target_platforms.py` script to determine the PLSSVM_TARGET_PLATFORMS string
execute_process(
COMMAND ${Python3_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/utility_scripts/plssvm_target_platforms.py" "--quiet"
RESULT_VARIABLE PLSSVM_PYTHON_TARGET_PLATFORMS_EXIT_CODE
OUTPUT_VARIABLE PLSSVM_PYTHON_TARGET_PLATFORMS_OUTPUT
)

# # an error occurred when running our python script
# if (NOT ${PLSSVM_PYTHON_TARGET_PLATFORMS_EXIT_CODE} EQUAL 0)
# message(FATAL_ERROR
# "Error running '${CMAKE_CURRENT_SOURCE_DIR}/utility_scripts/plssvm_target_platforms.py'."
# "Please manually specify PLSSVM_TARGET_PLATFORMS (e.g. -DPLSSVM_TARGET_PLATFORMS=\"cpu;nvidia:sm_70,sm_86;amd:gfx906;intel:skl\"!"
# )
# endif ()
# an error occurred when running our python script
if (NOT ${PLSSVM_PYTHON_TARGET_PLATFORMS_EXIT_CODE} EQUAL 0)
message(FATAL_ERROR
"Error running '${CMAKE_CURRENT_SOURCE_DIR}/utility_scripts/plssvm_target_platforms.py'."
"Please manually specify PLSSVM_TARGET_PLATFORMS (e.g. -DPLSSVM_TARGET_PLATFORMS=\"cpu;nvidia:sm_70,sm_86;amd:gfx906;intel:skl\"!"
)
endif ()

# # set PLSSVM_TARGET_PLATFORMS
# string(STRIP "${PLSSVM_PYTHON_TARGET_PLATFORMS_OUTPUT}" PLSSVM_TARGET_PLATFORMS)
# message(STATUS "Automatically derived PLSSVM_TARGET_PLATFORMS=\"${PLSSVM_TARGET_PLATFORMS}\".")
# set PLSSVM_TARGET_PLATFORMS
string(STRIP "${PLSSVM_PYTHON_TARGET_PLATFORMS_OUTPUT}" PLSSVM_TARGET_PLATFORMS)
message(STATUS "Automatically derived PLSSVM_TARGET_PLATFORMS=\"${PLSSVM_TARGET_PLATFORMS}\".")
endif ()


Expand Down Expand Up @@ -606,7 +600,7 @@ list(POP_BACK CMAKE_MESSAGE_INDENT)
option(PLSSVM_ENABLE_FORMATTING "Enable a formatting targets using clang-format." OFF)
if (PLSSVM_ENABLE_FORMATTING)
list(APPEND CMAKE_MESSAGE_INDENT "Formatting: ")

## install library to add a clang-format target
set(PLSSVM_format_VERSION d22c36043bea6ef85f3eb68b823f50703bd1cc21)
find_package(format QUIET)
Expand All @@ -625,7 +619,7 @@ if (PLSSVM_ENABLE_FORMATTING)
)
FetchContent_MakeAvailable(format)
endif ()

list(POP_BACK CMAKE_MESSAGE_INDENT)
endif ()

Expand Down
80 changes: 56 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
![![PLSSVM](../resources/logo_245x150.png)](docs/resources/logo_245x150.png)
![PLSSVM](https://github.com/SC-SGS/PLSSVM/raw/main/docs/resources/logo_245x150.png)

# PLSSVM - Parallel Least Squares Support Vector Machine

Expand Down Expand Up @@ -35,7 +35,7 @@ To predict to which class a new, unseen data point belongs, the SVM simply has t
This is very efficient since it only involves a single scalar product of the size corresponding to the numer of features of the data set.

<p align="center">
<img alt="Basic idea of an Support Vector Machine as classification model." src=".figures/support_vector_machine.png" width="50%">
<img alt="Basic idea of an Support Vector Machine as classification model." src="https://github.com/SC-SGS/PLSSVM/raw/main/.figures/support_vector_machine.png" width="50%">
</p>

However, normal SVMs suffer in their potential parallelizability.
Expand Down Expand Up @@ -188,13 +188,9 @@ Valid targets are:
- `intel`: compile for Intel GPUs; **at least one** architectural specification is necessary, e.g., `intel:skl`

At least one of the above targets must be present. If the option `PLSSVM_TARGET_PLATFORMS` is not present, the targets
are automatically determined using the Python3 `utility_scripts/plssvm_target_platforms.py` script (required Python3 dependencies:
[`argparse`](https://docs.python.org/3/library/argparse.html), [`py-cpuinfo`](https://pypi.org/project/py-cpuinfo/),
[`GPUtil`](https://pypi.org/project/GPUtil/), [`pyamdgpuinfo`](https://pypi.org/project/pyamdgpuinfo/), and
[`pylspci`](https://pypi.org/project/pylspci/)).
are automatically determined using the Python3 `utility_scripts/plssvm_target_platforms.py` script.

Note that when using DPC++/icpx only a single architectural specification for `cpu`, `nvidia` or `amd` is allowed and that
automatically retrieving AMD GPU information on Windows is currently not supported due to `pyamdgpuinfo` limitations.
Note that when using DPC++/icpx only a single architectural specification for `cpu`, `nvidia` or `amd` is allowed.


```bash
Expand All @@ -204,8 +200,9 @@ python3 utility_scripts/plssvm_target_platforms.py --help
usage: plssvm_target_platforms.py [-h] [--quiet]
optional arguments:
-h, --help show this help message and exit
--quiet only output the final PLSSVM_TARGET_PLATFORMS string
-h, --help show this help message and exit
--quiet only output the final PLSSVM_TARGET_PLATFORMS string
--gpus_only only output gpu architectures to the final PLSSVM_TARGET_PLATFORMS string
```

Example invocation:
Expand All @@ -214,10 +211,9 @@ Example invocation:
python3 utility_scripts/plssvm_target_platforms.py
```
```
Intel(R) Core(TM) i9-10980XE CPU @ 3.00GHz: {'avx512': True, 'avx2': True, 'avx': True, 'sse4_2': True}
supported CPU SIMD flags: {'avx512': True, 'avx2': True, 'avx': True, 'sse4_2': True}
Found 1 NVIDIA GPU(s):
1x NVIDIA GeForce RTX 3080: sm_86
Found 1 NVIDIA GPU(s): [sm_86]
Possible -DPLSSVM_TARGET_PLATFORMS entries:
cpu:avx512;nvidia:sm_86
Expand All @@ -231,13 +227,11 @@ or with the `--quiet` flag provided:
python3 utility_scripts/plssvm_target_platforms.py --quiet
```
```
cpu:avx512;intel:dg1
cpu:avx512;nvidia:sm_86
```

If the architectural information for the requested GPU could not be retrieved, one option would be to have a look at:

- for NVIDIA GPUs: [Your GPU Compute Capability](https://developer.nvidia.com/cuda-gpus)
- for AMD GPUs: [clang AMDGPU backend usage](https://llvm.org/docs/AMDGPUUsage.html)
- for Intel GPUs and CPUs: [Ahead of Time Compilation](https://www.intel.com/content/www/us/en/develop/documentation/oneapi-dpcpp-cpp-compiler-dev-guide-and-reference/top/compilation/ahead-of-time-compilation.html) and [Intel graphics processor table](https://dgpu-docs.intel.com/devices/hardware-table.html)


Expand Down Expand Up @@ -498,6 +492,8 @@ The documentation of the current state of the main branch can be found [here](ht

### Installing

#### Install via CMake

The library supports the `install` target:

```bash
Expand All @@ -515,6 +511,48 @@ export LD_LIBRARY_PATH=${CMAKE_INSTALL_PREFIX}/lib:${CMAKE_INSTALL_PREFIX}/lib64
export CPLUS_INCLUDE_PATH=${CMAKE_INSTALL_PREFIX}/include:${CPLUS_INCLUDE_PATH}
```

If our library was built with the Python bindings enabled, the `PYTHONPATH` must additionally be set:

```bash
export PYTHONPATH=${CMAKE_INSTALL_PREFIX}/lib:${CMAKE_INSTALL_PREFIX}/lib64:${PYTHONPATH}
```

#### Install via pip

We also support a pip packages that can be used to install our library:

```bash
pip install plssvm
```

This pip install behaves **as if** the CMake `all_python` preset is used.
This means that the `PLSSVM_TARGET_PLATFORMS` are automatically determined and PLSSVM is build with all supported
backends that available on the target machine at the point of the `pip install plssvm` invocation.
To check the installation, including, e.g., the installed backends, we provide the `plssvm-install-check` command after
PLSSVM has been installed via pip.
An example output of this command can look like:

```text
PLSSVM - Parallel Least Squares Support Vector Machine (3.0.0)
Copyright(C) 2018-today The PLSSVM project - All Rights Reserved
This is free software distributed under the MIT license.
Available target platforms: TargetPlatform.AUTOMATIC, TargetPlatform.GPU_NVIDIA, TargetPlatform.CPU
Default target platform: TargetPlatform.GPU_NVIDIA
Available backends: BackendType.AUTOMATIC, BackendType.OPENMP, BackendType.CUDA, BackendType.OPENCL, BackendType.SYCL
Default backend for target platform TargetPlatform.GPU_NVIDIA: BackendType.CUDA
Default backend for target platform TargetPlatform.CPU: BackendType.SYCL
Available SYCL implementations: ImplementationType.AUTOMATIC, ImplementationType.ADAPTIVECPP
Repository: https://github.com/SC-SGS/PLSSVM.git
Documentation: https://sc-sgs.github.io/PLSSVM
Issues: https://github.com/SC-SGS/PLSSVM/issues
```

## Usage

PLSSVM provides three executables: `plssvm-train`, `plssvm-predict`, and `plssvm-scale`.
Expand Down Expand Up @@ -963,7 +1001,7 @@ weighted avg 0.91 0.91 0.91 569
Score: 91.39%
```
<p align="center">
<img alt="Example classification task breast cancer decision boundary output." src=".figures/classification_example.png" width="80%">
<img alt="Example classification task breast cancer decision boundary output." src="https://github.com/SC-SGS/PLSSVM/raw/regression/.figures/classification_example.png" width="80%">
</p>

A regression example comparing PLSSVM's `SVR` Python binding and `sklearn.SVR` using a sine curve:
Expand Down Expand Up @@ -1030,15 +1068,9 @@ plt.show()
```
with an example output:
<p align="center">
<img alt="Example regression output using a sine curve." src=".figures/regression_example.png" width="80%">
<img alt="Example regression output using a sine curve." src="https://github.com/SC-SGS/PLSSVM/raw/regression/.figures/regression_example.png" width="80%">
</p>

**Note:** it may be necessary to set the environment variable `PYTHONPATH` to the `lib` folder in the PLSSVM install path.

```bash
export PYTHONPATH=${CMAKE_INSTALL_PREFIX}/lib:${CMAKE_INSTALL_PREFIX}/lib64:${PYTHONPATH}
```

Note that currently not all sklearn `SVC` and `SVR` functionality has been implemented in PLSSVM.
The respective functions will throw a Python `AttributeError` if called.
For a detailed overview of the functions that are currently implemented, see [our API documentation](bindings/Python/README.md).
Expand Down
10 changes: 10 additions & 0 deletions bindings/Python/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,13 @@ target_compile_options(${PLSSVM_BASE_LIBRARY_NAME} PUBLIC -fPIC)

# append pybind11 bindings library to installed targets
append_local_and_parent(PLSSVM_TARGETS_TO_INSTALL ${PLSSVM_PYTHON_BINDINGS_LIBRARY_NAME})

# install the __init__.py file so Python recognizes the package when installed via pip
# install the __cli__.py file so the PLSSVM executables can be used when installed via pip
# install the __install_check__.py file creating a new executable plssvm-install-check outputting some information when installed via pip
include(GNUInstallDirs)
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/__init__.py"
"${CMAKE_CURRENT_SOURCE_DIR}/__cli__.py"
"${CMAKE_CURRENT_SOURCE_DIR}/__install_check__.py"
DESTINATION "${CMAKE_INSTALL_LIBDIR}"
)
21 changes: 21 additions & 0 deletions bindings/Python/__cli__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import sys
import subprocess
from pathlib import Path


# support for plssvm-train including command line arguments
def train():
exe_path = Path(__file__).parent / "plssvm-train"
subprocess.run([str(exe_path)] + sys.argv[1:])


# support for plssvm-predict including command line arguments
def predict():
exe_path = Path(__file__).parent / "plssvm-predict"
subprocess.run([str(exe_path)] + sys.argv[1:])


# support for plssvm-scale including command line arguments
def scale():
exe_path = Path(__file__).parent / "plssvm-scale"
subprocess.run([str(exe_path)] + sys.argv[1:])
6 changes: 6 additions & 0 deletions bindings/Python/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# import all bindings from the compiled PLSSVM module
from .plssvm import *

# explicitly set the module level attributes
__doc__ = plssvm.__doc__
__version__ = plssvm.__version__
33 changes: 33 additions & 0 deletions bindings/Python/__install_check__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import plssvm

# print information regarding the current installation after an installation via pip
def check():
print("{} ({})".format(plssvm.__doc__, plssvm.__version__))
print()

print("Copyright(C) 2018-today The PLSSVM project - All Rights Reserved")
print("This is free software distributed under the MIT license.")
print()

print("Available target platforms: {}".format(', '.join(str(target) for target in plssvm.list_available_target_platforms())))
print("Default target platform: {}\n".format(str(plssvm.determine_default_target_platform())))

print("Available backends: {}".format(', '.join(str(backend) for backend in plssvm.list_available_backends())))
for target in plssvm.list_available_target_platforms():
if target == plssvm.TargetPlatform.AUTOMATIC:
continue
try:
backend = plssvm.determine_default_backend(available_target_platforms=[target])
print("Default backend for target platform {}: {}".format(str(target), str(backend)))
except:
pass
print()

if plssvm.BackendType.SYCL in plssvm.list_available_backends():
print("Available SYCL implementations: {}".format(', '.join(str(impl) for impl in plssvm.sycl.list_available_sycl_implementations())))
print()

print()
print("Repository: https://github.com/SC-SGS/PLSSVM.git")
print("Documentation: https://sc-sgs.github.io/PLSSVM/")
print("Issues: https://github.com/SC-SGS/PLSSVM/issues")
Loading

0 comments on commit 4b90f3e

Please sign in to comment.