Skip to content

Commit

Permalink
Make: Link to pre-compiled SimSIMD wheel
Browse files Browse the repository at this point in the history
In older version of USearch we compile it directly
with SimSIMD sources. It heavily complicates the
dynamic dispatch logic and is problematic with
Python's `cibuildwheel`.

Now we expect the user to pull SimSIMD from
PyPi and the symbols will be automatically linked.
  • Loading branch information
ashvardanian committed Oct 9, 2024
1 parent 191d9bb commit bd5e579
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 60 deletions.
7 changes: 6 additions & 1 deletion python/lib.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -871,8 +871,13 @@ PYBIND11_MODULE(compiled, m) {
m.attr("DEFAULT_EXPANSION_SEARCH") = py::int_(default_expansion_search());

m.attr("USES_OPENMP") = py::int_(USEARCH_USE_OPENMP);
m.attr("USES_SIMSIMD") = py::int_(USEARCH_USE_SIMSIMD);
m.attr("USES_FP16LIB") = py::int_(USEARCH_USE_FP16LIB);
m.attr("USES_SIMSIMD") = py::int_(USEARCH_USE_SIMSIMD);
#if USEARCH_USE_SIMSIMD
m.attr("USES_SIMSIMD_DYNAMIC_DISPATCH") = py::int_(simsimd_uses_dynamic_dispatch());
#else
m.attr("USES_SIMSIMD_DYNAMIC_DISPATCH") = py::int_(0);
#endif

m.attr("VERSION_MAJOR") = py::int_(USEARCH_VERSION_MAJOR);
m.attr("VERSION_MINOR") = py::int_(USEARCH_VERSION_MINOR);
Expand Down
16 changes: 15 additions & 1 deletion python/usearch/__init__.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,30 @@
import os
import platform
import tempfile
import warnings
import urllib.request
from typing import Optional, Tuple
from urllib.error import HTTPError


#! SimSIMD must come before USearch import
try:
import simsimd
except ImportError:
pass

from usearch.compiled import (
VERSION_MAJOR,
VERSION_MINOR,
VERSION_PATCH,
# Default values:
DEFAULT_CONNECTIVITY,
DEFAULT_EXPANSION_ADD,
DEFAULT_EXPANSION_SEARCH,
# Dependencies:
USES_OPENMP,
USES_FP16LIB,
USES_SIMSIMD,
USES_SIMSIMD_DYNAMIC_DISPATCH,
)

__version__ = f"{VERSION_MAJOR}.{VERSION_MINOR}.{VERSION_PATCH}"
Expand Down
6 changes: 6 additions & 0 deletions python/usearch/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@
import numpy as np
from tqdm import tqdm

#! SimSIMD must come before USearch import
try:
import simsimd
except ImportError:
pass

# Precompiled symbols that won't be exposed directly:
from usearch.compiled import (
Index as _CompiledIndex,
Expand Down
91 changes: 34 additions & 57 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

from pybind11.setup_helpers import Pybind11Extension

sources = ["python/lib.cpp"]
compile_args = []
link_args = []
macros_args = []
Expand Down Expand Up @@ -46,17 +45,39 @@ def get_bool_env_w_name(name: str, preference: bool) -> tuple:
prefer_fp16lib: bool = True
prefer_openmp: bool = is_linux and is_gcc

use_simsimd: bool = get_bool_env("USEARCH_USE_SIMSIMD", prefer_simsimd)
use_simsimd: bool = True # get_bool_env("USEARCH_USE_SIMSIMD", prefer_simsimd)
use_fp16lib: bool = get_bool_env("USEARCH_USE_FP16LIB", prefer_fp16lib)
use_openmp: bool = get_bool_env("USEARCH_USE_OPENMP", prefer_openmp)

if use_simsimd:
sources.append("simsimd/c/lib.c")

# Common arguments for all platforms
macros_args.append(("USEARCH_USE_OPENMP", "1" if use_openmp else "0"))
macros_args.append(("USEARCH_USE_SIMSIMD", "1" if use_simsimd else "0"))
macros_args.append(("USEARCH_USE_FP16LIB", "1" if use_fp16lib else "0"))
macros_args.append(("USEARCH_USE_SIMSIMD", "1" if use_simsimd else "0"))


#! Unlike OpenMP and FP16LIB, the SimSIMD is integrated differently.
#! It will anyways use dynamic dispatch, and will not build the library as part of `usearch` package.
#! It relies on the fact that SimSIMD ships it's own bindings for most platforms, and the user should
#! install it separately!
macros_args.extend(
[
("SIMSIMD_DYNAMIC_DISPATCH", "1" if use_simsimd else "0"),
("SIMSIMD_TARGET_NEON", "0"), # ? Hide-out all complex intrinsics
("SIMSIMD_TARGET_NEON_BF16", "0"), # ? Hide-out all complex intrinsics
("SIMSIMD_TARGET_NEON_F16", "0"), # ? Hide-out all complex intrinsics
("SIMSIMD_TARGET_NEON_I8", "0"), # ? Hide-out all complex intrinsics
("SIMSIMD_TARGET_SVE", "0"), # ? Hide-out all complex intrinsics
("SIMSIMD_TARGET_SVE_BF16", "0"), # ? Hide-out all complex intrinsics
("SIMSIMD_TARGET_SVE_F16", "0"), # ? Hide-out all complex intrinsics
("SIMSIMD_TARGET_SVE_I8", "0"), # ? Hide-out all complex intrinsics
("SIMSIMD_TARGET_SVE2", "0"), # ? Hide-out all complex intrinsics
("SIMSIMD_TARGET_HASWELL", "0"), # ? Hide-out all complex intrinsics
("SIMSIMD_TARGET_SKYLAKE", "0"), # ? Hide-out all complex intrinsics
("SIMSIMD_TARGET_ICE", "0"), # ? Hide-out all complex intrinsics
("SIMSIMD_TARGET_SAPPHIRE", "0"), # ? Hide-out all complex intrinsics
("SIMSIMD_TARGET_GENOA", "0"), # ? Hide-out all complex intrinsics
]
)

if is_linux:
compile_args.append("-std=c++17")
Expand All @@ -72,21 +93,6 @@ def get_bool_env_w_name(name: str, preference: bool) -> tuple:
compile_args.append("-fopenmp")
link_args.append("-lgomp")

if use_simsimd:
macros_args.extend(
[
get_bool_env_w_name("SIMSIMD_TARGET_NEON", True),
get_bool_env_w_name("SIMSIMD_TARGET_NEON_BF16", False),
get_bool_env_w_name("SIMSIMD_TARGET_SVE", True),
get_bool_env_w_name("SIMSIMD_TARGET_SVE_BF16", False),
get_bool_env_w_name("SIMSIMD_TARGET_HASWELL", True),
get_bool_env_w_name("SIMSIMD_TARGET_SKYLAKE", True),
get_bool_env_w_name("SIMSIMD_TARGET_ICE", True),
get_bool_env_w_name("SIMSIMD_TARGET_GENOA", True),
get_bool_env_w_name("SIMSIMD_TARGET_SAPPHIRE", True),
]
)

if is_macos:
# MacOS 10.15 or higher is needed for `aligned_alloc` support.
# https://github.com/unum-cloud/usearch/actions/runs/4975434891/jobs/8902603392
Expand All @@ -111,47 +117,16 @@ def get_bool_env_w_name(name: str, preference: bool) -> tuple:
# link_args.append("-lomp")
# macros_args.append(("USEARCH_USE_OPENMP", "1"))

if use_simsimd:
macros_args.extend(
[
get_bool_env_w_name("SIMSIMD_TARGET_NEON", True),
get_bool_env_w_name("SIMSIMD_TARGET_NEON_BF16", False),
get_bool_env_w_name("SIMSIMD_TARGET_SVE", False),
get_bool_env_w_name("SIMSIMD_TARGET_SVE_BF16", False),
get_bool_env_w_name("SIMSIMD_TARGET_HASWELL", True),
get_bool_env_w_name("SIMSIMD_TARGET_SKYLAKE", False),
get_bool_env_w_name("SIMSIMD_TARGET_ICE", False),
get_bool_env_w_name("SIMSIMD_TARGET_GENOA", False),
get_bool_env_w_name("SIMSIMD_TARGET_SAPPHIRE", False),
]
)


if is_windows:
compile_args.append("/std:c++17")
compile_args.append("/O2")
compile_args.append("/fp:fast") # Enable fast math for MSVC
compile_args.append("/W1") # Reduce warnings verbosity

if use_simsimd:
macros_args.extend(
[
get_bool_env_w_name("SIMSIMD_TARGET_NEON", True),
get_bool_env_w_name("SIMSIMD_TARGET_NEON_BF16", False),
get_bool_env_w_name("SIMSIMD_TARGET_SVE", False),
get_bool_env_w_name("SIMSIMD_TARGET_SVE_BF16", False),
get_bool_env_w_name("SIMSIMD_TARGET_HASWELL", True),
get_bool_env_w_name("SIMSIMD_TARGET_SKYLAKE", True),
get_bool_env_w_name("SIMSIMD_TARGET_ICE", True),
get_bool_env_w_name("SIMSIMD_TARGET_GENOA", False),
get_bool_env_w_name("SIMSIMD_TARGET_SAPPHIRE", False),
]
)

ext_modules = [
Pybind11Extension(
"usearch.compiled",
sources,
["python/lib.cpp"],
extra_compile_args=compile_args,
extra_link_args=link_args,
define_macros=macros_args,
Expand All @@ -172,8 +147,13 @@ def get_bool_env_w_name(name: str, preference: bool) -> tuple:
"python",
"stringzilla/include",
]
install_requires = [
"numpy",
"tqdm",
]
if use_simsimd:
include_dirs.append("simsimd/include")
install_requires.append("simsimd>=5.6.3")
if use_fp16lib:
include_dirs.append("fp16/include")

Expand Down Expand Up @@ -222,10 +202,7 @@ def get_bool_env_w_name(name: str, preference: bool) -> tuple:
],
include_dirs=include_dirs,
ext_modules=ext_modules,
install_requires=[
"numpy",
"tqdm",
],
install_requires=install_requires,
)

# Reset the CC environment variable, that we overrode earlier.
Expand Down

0 comments on commit bd5e579

Please sign in to comment.