Installation¶
Binary wheels (Linux x86_64)¶
Each release carries self-contained wheels for CPython 3.10 to 3.13 on Linux x86_64 (glibc 2.28 or newer, i.e. any mainstream distribution from 2019 on). They bundle SDPB and every library it needs, so nothing has to be compiled. Let pip choose the wheel for your Python from the release page:
pip install sdpb-python --find-links https://github.com/YPWang0818/sdpb-python/releases/expanded_assets/v0.4.0
or install one file directly:
pip install https://github.com/YPWang0818/sdpb-python/releases/download/v0.4.0/sdpb_python-0.4.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Then check:
python -c "import sdpb_python; print(sdpb_python.sdpb_version())"
Two things to know about the wheels:
They contain their own MPI library (MPICH), used only to initialise SDPB’s single-process solver. Do not load another MPI in the same process, for example
mpi4pybuilt against OpenMPI.They open no network sockets. The bundled MPICH is built without a network module, so a solve cannot be reached, or disturbed, from the network. (Up to v0.2.1 the bundled MPICH listened on a random TCP port on all interfaces, and any foreign connection to it, such as a port scan on a shared server, aborted the running process with
Assertion failed in file .../netmod/tcp/socksm.c. If you must keep such a version, run it in a private network namespace:unshare --user --map-root-user --net bash -c 'ip link set lo up; python script.py'.)They are built with a portable OpenBLAS and generic x86_64 code; a native build tuned for your CPU can be somewhat faster.
For other platforms, or to work on the C++ side, build from source as below.
Building from source¶
sdpb-python compiles SDPB and links it into a Python extension, so it needs SDPB’s full C++ tool chain.
Requirements¶
Python 3.10 or newer, with
mpmath.A C++17 compiler and an MPI implementation (
mpicxx), Boost (headers and the compiledprogram_optionsandserializationlibraries), GMP with C++ bindings, MPFR, FLINT (2.8 or newer), RapidJSON, and a CBLAS such as OpenBLAS.The bootstrap-collaboration fork of Elemental, normally built from source.
SDPB itself also lists MPSolve, libxml2 and libarchive. Only its command-line
tools use them; the build script configures SDPB with --libs-only, which
builds just the four static libraries the extension links and does not look
for those packages.
Building the dependencies (Ubuntu 24.04) is a tested, step-by-step recipe for Ubuntu 24.04; SDPB’s own
Install.md in the submodule covers other systems and HPC sites.
Steps¶
Clone with the SDPB submodule (it follows the fork’s
python-apibranch):git clone --recurse-submodules git@github.com:YPWang0818/sdpb-python.git cd sdpb-python
Create an environment with the build tools:
python3 -m venv .venv && source .venv/bin/activate pip install setuptools wheel Cython mpmath pytest
Build SDPB and install the package in editable mode:
scripts/build_sdpb.sh
The script configures SDPB’s waf build with
-fPIC, builds it, and runspip install --no-build-isolation -e .. It expects Elemental under$DEPS_PREFIX(default~/install); extra arguments are passed towaf configure,JOBSsets the parallelism.Check:
python -c "import sdpb_python; print(sdpb_python.sdpb_version())" pytest
Optional extras¶
numpy: matrices forLMIcan be arrays.sympy:Polynomial.from_sympy.Documentation:
pip install sphinx myst-parser furo sphinx-copybutton, thensphinx-build -b html docs docs/_build/html.
Notes¶
If MPI programs print
Authorization required, but no authorization protocol specified, that is X11 noise caused by a setDISPLAY;unset DISPLAYsilences it.The build links SDPB statically into the extension; the Elemental shared libraries are found through an rpath, so they must stay where they were at build time.
The package runs on one MPI rank. Launching several processes with an
mpirunorsrunfrom a different MPI than the package links (the wheels bundle MPICH) does not create a multi-rank job: each process initialises MPI alone, and they would silently duplicate the work and overwrite each other’s output. That is refused with an error naming the launcher; setSDPB_PYTHON_ALLOW_MULTI_PROCESS=1when the processes really are meant to be independent, for example a sweep in which each writes to its own directory.A source build links the system’s MPI, which may listen on the network even for one process. Open MPI opens a TCP port on all interfaces; setting
OMPI_MCA_btl=^tcpin the environment avoids it (the package never communicates between hosts). An MPICH built with its defaulttcpnetwork module additionally aborts the process when something that is not MPICH connects to that port; configure MPICH with--with-device=ch3:nemesis:none, as the wheels do, or run in a private network namespace.OpenBLAS selects its kernels at run time from the CPU family, and for an AMD family-15/17 CPU it takes Opteron kernels that use the 3DNow! instruction
femms. QEMU/KVM guests with the default CPU model report such a family without 3DNow!, so the firstsolve()died withIllegal instructioninsidelibopenblas(wheel builds before this fix and source builds against a system OpenBLAS alike). The package now setsOPENBLAS_CORETYPEitself on such CPUs before OpenBLAS loads (modulesdpb_python._cpu; an existing setting is kept), and the wheels’ OpenBLAS is built without the Opteron targets. On a source build,OPENBLAS_CORETYPE=NEHALEMin the environment is the manual equivalent.
How the wheels are made¶
.github/workflows/deps-image.yml builds a manylinux_2_28 Docker image with
MPICH, GMP, MPFR, FLINT, Boost, OpenBLAS and the Elemental fork
installed under /opt/deps (docker/deps.Dockerfile, one build stage per
library, cached in the registry so a change rebuilds only what depends on it) and pushes it to
ghcr.io/ypwang0818/sdpb-python-deps. .github/workflows/wheels.yml then runs
cibuildwheel in that image on every v* tag: it builds SDPB’s static
libraries once, builds the extension for each Python version, repairs the
wheels so they bundle every shared library, runs the test-suite inside each,
checks with scripts/check_wheel_isa.sh that no bundled library has AVX code
baked in (the manylinux tag fixes glibc, not the CPU), and attaches them to
the GitHub release. The same image can be pulled locally to reproduce a build.