Python wrapper for the DeLIA C++ library (MPI-enabled)
Project description
DeLIApy: Python Wrapper for the DeLIA C++ Library
This document provides a complete technical guide for the use, development, and architectural understanding of DeLIApy, a high-performance wrapper developed in Cython for the DeLIA fault tolerance library.
Table of Contents
- Overview and Documentation
- Prerequisites
- Installation and Quick Start
- Implementation Examples
- Project Structure
- Development and Build Guide
- Test Suite
- Architecture and Design Decisions
- Known Issues and Workarounds
- Final Considerations and Next Steps
Overview and Documentation
DeLIApy is the official Python interface for DeLIA (Dependability Library for Iterative Applications), a C++ library designed to provide checkpointing and fault tolerance mechanisms in High-Performance Computing (HPC) environments.
- Important Links:
Prerequisites
To use or compile the project, the environment must meet the following specifications:
- Python: Version
>= 3.11and< 3.12. - OpenMPI: Version
5.0.8(expected at/opt/openmpi-5.0.8). - Compiler: GCC/G++ with
C++17support. - System Dependencies: Python and MPI development headers.
Installation and Quick Start
Installation via PyPI
For users who only wish to use the library in their Poetry or Pip projects:
# Via Pip
pip install deliapy
# Via Poetry
poetry add deliapy
Installing pre-releases from TestPyPI (Optional)
If you want to install from TestPyPI instead:
# Via Pip
pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ deliapy
# Via Poetry
# 1. Add TestPyPI as a supplemental repository
poetry config repositories.testpypi https://test.pypi.org/legacy/
# 2. Configure the source in the project
poetry source add --priority=supplemental testpypi https://test.pypi.org/simple/
# 3. Install deliapy specifying the source
poetry add --source testpypi deliapy
Implementation Examples
Below is a practical example integrating mpi4py with DeLIApy's checkpointing and monitoring features.
import deliapy
from mpi4py import MPI
import array
# 1. Define data structure with persistence logic
class MyAppStats(deliapy.IDataLocal):
def __init__(self, name, rank):
self.name = name
self.rank = rank
self.data = array.array('d', [rank * 1.5])
super().__init__()
def SerializeLocal(self, ft_path: str):
# Concatenate ft_path and the filename since ft_path is a path/filename prefix
with open(f"{ft_path}{self.name}_{self.rank}.bin", "wb") as f:
f.write(self.data.tobytes())
def DeserializeLocal(self, ft_path: str) -> bool:
# Logic to restore data after a failure
return True
def SerializeTasks(self, ft_path: str):
pass
def DeserializeAllTaks(self, ft_path: str) -> bool:
return True
def getName(self):
return self.name
# 2. MPI Communicator Setup
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()
# 3. DeLIA Initialization
# Arguments: rank, size, path_params, path_config, [data_global], [data_local]
stats = MyAppStats("local_stats", rank)
deliapy.DeLIA_Init(rank, size, "params.json", "config.txt", data_local=[stats])
if deliapy.DeLIA_CanWork():
# 4. Start Heartbeat Monitoring (C++ Thread)
deliapy.DeLIA_HeartbeatMonitoring_Init()
# 5. Save settings and initial state
deliapy.DeLIA_SaveSettings()
deliapy.DeLIA_SaveLocalData()
print(f"Rank {rank} processing...")
# 6. Finalization
deliapy.DeLIA_HeartbeatMonitoring_Finalize()
deliapy.DeLIA_Finalize()
Project Structure
The file organization reflects the separation between Python logic, the Cython bridge, and the C++ core:
deliapy/:core.pyx: Main wrapper implementation and type conversion logic.core.pxd: C++ interface declarations for Cython.core.pyi: Typing stubs for IDE support.
libs/:IDataWrappers.cpp/h: C++ bridge implementation that allows the native core to call Python object methods.
deliacpp/: Git submodule containing the original DeLIA library source code.tests/: Unit and MPI integration test suite.build.py: Custom extension compilation script.
Development and Build Guide
The project uses Poetry in conjunction with PoeThePoet to automate the C++ extension build cycle.
Environment Configuration
The project depends on the correct location of MPI shared libraries. Use the .env file to define execution paths:
cp .env.example .env
# Ensure LD_LIBRARY_PATH points to your OpenMPI installation
Local Compilation Workflow
- Install development dependencies:
poetry install - Compile the extension (Inplace):
poetry run poe build-ext
- This command runs
build.py, which usescythonizeto generate.cppfiles from.pyxand compiles the binary.soobject.
- This command runs
CI/CD Pipeline
The project uses GitLab CI for automated linting, testing, and publishing (via a custom OpenMPI Docker environment). For complete details on the pipeline architecture, trigger matrix, and how to publish new releases, please read the CI/CD Pipeline Documentation.
Test Suite
Project validation is divided into two domains:
Serial Tests (OOP and Bindings)
Validates whether Python classes can be instantiated and if polymorphism between C++ and Python functions correctly.
poetry run poe test-serial
MPI Tests (Distributed)
Tests library behavior in a real parallel environment with 3 processes.
test_mpi_reads.py: Verifies if global/local checkpointing restores in-memory data after intentional corruption.test_mpi_signals.py: Validates the interception of theSIGTSTPsignal (kill -20) for automatic local state saving.test_mpi_hm.py: Tests Heartbeat Monitoring, simulating a "hang" in one of the processes to verify failure detection.
poetry run poe test-mpi
Architecture and Design Decisions
The primary architectural challenge of this wrapper is allowing the C++ core (which is unaware of Python) to execute methods like SerializeGlobal defined in a Python class.
IDataWrappers
To solve this, we created C++ "Wrapper" classes (IDataGlobalWrapper, etc.) that inherit from the original DeLIA abstract classes.
- These classes store a pointer to the Python object (
PyObject *py_obj). - When the C++ core calls
SerializeGlobal, the wrapper uses the Python C API to locate the method on the Python object and execute it. - Memory Management: The wrapper increments the reference count (
Py_XINCREF) of the Python object upon creation, ensuring it is not reclaimed by the Garbage Collector while the C++ library is using it.
Linking and RPATH
Unlike standard installations, build.py uses the runtime_library_dirs directive.
- Why?: This embeds the OpenMPI path (RPATH) directly into the
.sofile. - Benefit: Users do not need to manually configure
LD_LIBRARY_PATHevery time they run a script, provided MPI is in the default build location.
Known Issues and Workarounds
1. Termination with Segmentation Fault (Signal 11) in MPI Tests
- Symptom: Upon finishing the distributed test suite (
test-mpi),mpiexecmay report a segmentation fault, even after Pytest confirms all tests passed. - Technical Cause: This is an Exit-time Crash. It occurs due to a race condition between the Python Garbage Collector and the DeLIA (C++) background monitoring threads. During shutdown, if Heartbeat threads or C++ Signal Handlers attempt to access memory pointers that the MPI or Python runtime has already invalidated, a Signal 11 occurs.
- Impact: None. The error occurs exclusively during the final teardown phase. All checkpoint data and local states are successfully saved and validated before this fault happens.
2. ImportError: libmpi.so.12 not found
- Symptom: Failure to import
deliapy.coreormpi4pystating the MPI dynamic library was not located. - Solution: Use the
.envfile to correctly injectLD_LIBRARY_PATH. The build script also attempts to mitigate this by injecting RPATH flags during compilation.
Final Considerations and Next Steps
DeLIApy bridges the gap between Python's convenience and the robustness required for large-scale MPI systems.
Next Steps:
- Expansion of automated documentation (Sphinx/Doxygen).
- Support for complex multi-dimensional arrays via the buffer interface.
- Improved Python exception handling within C++ calls to prevent abrupt runtime aborts.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file deliapy-0.1.5.tar.gz.
File metadata
- Download URL: deliapy-0.1.5.tar.gz
- Upload date:
- Size: 14.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.4.1 CPython/3.11.15 Linux/5.15.154+
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5cc758b5121926226b73d6b97c9c9ddfd372045f4009f04316affa35ff0692d4
|
|
| MD5 |
2808b010cdbeccc7cb15db90cbc1034f
|
|
| BLAKE2b-256 |
8341a2b0b5d279871491e1869af7cb379eefb7a65a07c4565a55dfe83d971a43
|
File details
Details for the file deliapy-0.1.5-cp311-cp311-manylinux_2_41_x86_64.whl.
File metadata
- Download URL: deliapy-0.1.5-cp311-cp311-manylinux_2_41_x86_64.whl
- Upload date:
- Size: 2.9 MB
- Tags: CPython 3.11, manylinux: glibc 2.41+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/2.4.1 CPython/3.11.15 Linux/5.15.154+
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eb79bb2e2e8f02dc61c40f04b8878b64dc2918d17baae08bf1604937ba9b3153
|
|
| MD5 |
49f7d0c4fb0679cfdfc1ef378b580b7b
|
|
| BLAKE2b-256 |
143cdafa5197c882db6bfef41635df72dccd4471bf89f84a2572e3e704ec1edb
|