2023-01-19 06:30:17 +08:00
|
|
|
# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other
|
2020-10-16 15:47:22 +08:00
|
|
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
|
|
|
#
|
|
|
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
|
|
|
|
|
|
|
import os
|
2021-07-09 06:12:30 +08:00
|
|
|
|
2022-05-29 00:55:44 +08:00
|
|
|
from spack.package import *
|
2020-10-16 15:47:22 +08:00
|
|
|
|
|
|
|
|
2022-11-19 04:43:41 +08:00
|
|
|
class Faiss(AutotoolsPackage, CMakePackage, CudaPackage):
|
2020-10-16 15:47:22 +08:00
|
|
|
"""Faiss is a library for efficient similarity search and clustering of
|
2022-07-31 06:19:18 +08:00
|
|
|
dense vectors.
|
2020-10-16 15:47:22 +08:00
|
|
|
|
2022-07-31 06:19:18 +08:00
|
|
|
Faiss contains algorithms that search in sets of vectors of any size, up
|
|
|
|
to ones that possibly do not fit in RAM. It also contains supporting code
|
|
|
|
for evaluation and parameter tuning. Faiss is written in C++ with
|
|
|
|
complete wrappers for Python/numpy. Some of the most useful algorithms
|
|
|
|
are implemented on the GPU. It is developed by Facebook AI Research.
|
2020-10-16 15:47:22 +08:00
|
|
|
"""
|
|
|
|
|
|
|
|
homepage = "https://github.com/facebookresearch/faiss"
|
2022-07-31 06:19:18 +08:00
|
|
|
url = "https://github.com/facebookresearch/faiss/archive/v1.6.3.tar.gz"
|
2020-10-16 15:47:22 +08:00
|
|
|
|
2023-02-02 13:07:25 +08:00
|
|
|
maintainers("bhatiaharsh", "rblake-llnl", "lpottier")
|
2020-10-16 15:47:22 +08:00
|
|
|
|
2022-11-19 04:43:41 +08:00
|
|
|
build_system(
|
|
|
|
conditional("cmake", when="@1.7:"), conditional("autotools", when="@:1.6"), default="cmake"
|
|
|
|
)
|
|
|
|
|
2023-04-27 00:15:52 +08:00
|
|
|
version("1.7.4", sha256="d9a7b31bf7fd6eb32c10b7ea7ff918160eed5be04fe63bb7b4b4b5f2bbde01ad")
|
2022-11-19 04:43:41 +08:00
|
|
|
version("1.7.2", sha256="d49b4afd6a7a5b64f260a236ee9b2efb760edb08c33d5ea5610c2f078a5995ec")
|
2022-07-31 06:19:18 +08:00
|
|
|
version("1.6.3", sha256="e1a41c159f0b896975fbb133e0240a233af5c9286c09a28fde6aefff5336e542")
|
|
|
|
version("1.5.3", sha256="b24d347b0285d01c2ed663ccc7596cd0ea95071f3dd5ebb573ccfc28f15f043b")
|
2020-10-16 15:47:22 +08:00
|
|
|
|
2022-07-31 06:19:18 +08:00
|
|
|
variant("python", default=False, description="Build Python bindings")
|
2022-11-19 04:43:41 +08:00
|
|
|
variant("shared", default=False, description="Build shared library")
|
2022-07-31 06:19:18 +08:00
|
|
|
variant("tests", default=False, description="Build Tests")
|
2020-10-16 15:47:22 +08:00
|
|
|
|
2022-07-31 06:19:18 +08:00
|
|
|
conflicts("+tests", when="~python", msg="+tests must be accompanied by +python")
|
2020-10-16 15:47:22 +08:00
|
|
|
|
2022-11-19 04:43:41 +08:00
|
|
|
depends_on("cmake@3.17:", when="build_system=cmake", type="build")
|
|
|
|
|
|
|
|
extends("python", when="+python")
|
2022-07-31 06:19:18 +08:00
|
|
|
depends_on("python@3.7:", when="+python", type=("build", "run"))
|
|
|
|
depends_on("py-pip", when="+python", type="build")
|
|
|
|
depends_on("py-wheel", when="+python", type="build")
|
2022-11-19 04:43:41 +08:00
|
|
|
depends_on("py-setuptools", when="+python", type="build")
|
2022-07-31 06:19:18 +08:00
|
|
|
depends_on("py-numpy", when="+python", type=("build", "run"))
|
2022-11-19 04:43:41 +08:00
|
|
|
depends_on("swig@4", when="+python", type="build")
|
|
|
|
depends_on("py-scipy", when="+python+tests", type=("build", "run"))
|
2020-10-16 15:47:22 +08:00
|
|
|
|
2022-07-31 06:19:18 +08:00
|
|
|
depends_on("blas")
|
2020-10-16 15:47:22 +08:00
|
|
|
|
|
|
|
# patch for v1.5.3
|
|
|
|
# faiss assumes that the "source directory" will always
|
|
|
|
# be called "faiss" (not spack-src or faiss-1.5.3)
|
|
|
|
# so, we will have to create a symlink to self (faiss did that in 1.6.3)
|
|
|
|
# and add an include path
|
2022-07-31 06:19:18 +08:00
|
|
|
patch("fixes-in-v1.5.3.patch", when="@1.5.3")
|
2020-10-16 15:47:22 +08:00
|
|
|
|
|
|
|
# patch for v1.6.3
|
|
|
|
# for v1.6.3, GPU build has a bug (two files need to be deleted)
|
|
|
|
# https://github.com/facebookresearch/faiss/issues/1159
|
|
|
|
# also, some include paths in gpu/tests/Makefile are missing
|
2022-07-31 06:19:18 +08:00
|
|
|
patch("fixes-in-v1.6.3.patch", when="@1.6.3")
|
2020-10-16 15:47:22 +08:00
|
|
|
|
2022-11-19 04:43:41 +08:00
|
|
|
# patch for v1.7.2
|
|
|
|
# a shared object is missing in the python/setup.py
|
|
|
|
# https://github.com/facebookresearch/faiss/issues/2063
|
|
|
|
# https://github.com/facebookresearch/faiss/pull/2062
|
|
|
|
# a header is missing in a test file
|
|
|
|
# https://github.com/facebookresearch/faiss/issues/2300
|
|
|
|
patch("fixes-in-v1.7.2.patch", when="@1.7.2")
|
|
|
|
|
|
|
|
def setup_run_environment(self, env):
|
|
|
|
if "+python" in self.spec:
|
|
|
|
env.prepend_path("PYTHONPATH", python_platlib)
|
2023-01-17 20:43:35 +08:00
|
|
|
if self.spec.satisfies("platform=darwin"):
|
|
|
|
env.append_path(
|
|
|
|
"DYLD_FALLBACK_LIBRARY_PATH", os.path.join(python_platlib, "faiss")
|
|
|
|
)
|
|
|
|
else:
|
|
|
|
env.append_path("LD_LIBRARY_PATH", os.path.join(python_platlib, "faiss"))
|
2022-11-19 04:43:41 +08:00
|
|
|
|
|
|
|
|
|
|
|
class CMakeBuilder(spack.build_systems.cmake.CMakeBuilder):
|
|
|
|
def cmake_args(self):
|
|
|
|
spec = self.spec
|
|
|
|
args = [
|
|
|
|
self.define_from_variant("BUILD_SHARED_LIBS", "shared"),
|
|
|
|
self.define_from_variant("FAISS_ENABLE_PYTHON", "python"),
|
|
|
|
self.define_from_variant("FAISS_ENABLE_GPU", "cuda"),
|
|
|
|
self.define_from_variant("BUILD_TESTING", "tests"),
|
|
|
|
self.define("FAISS_OPT_LEVEL", "generic"),
|
|
|
|
]
|
|
|
|
if "+python" in spec:
|
|
|
|
pyexe = spec["python"].command.path
|
|
|
|
args.append(self.define("Python_EXECUTABLE", pyexe))
|
|
|
|
|
|
|
|
if "+cuda" in spec:
|
|
|
|
key = "CMAKE_CUDA_ARCHITECTURES"
|
|
|
|
args.append(self.define_from_variant(key, "cuda_arch"))
|
|
|
|
# args.append(self.define_from_variant(
|
|
|
|
# 'CMAKE_CUDA_STANDARD', 'cudastd'))
|
|
|
|
return args
|
|
|
|
|
|
|
|
def install(self, pkg, spec, prefix):
|
|
|
|
super().install(pkg, spec, prefix)
|
|
|
|
if "+python" in spec:
|
|
|
|
|
|
|
|
class CustomPythonPipBuilder(spack.build_systems.python.PythonPipBuilder):
|
|
|
|
def __init__(self, pkg, build_dirname):
|
|
|
|
spack.build_systems.python.PythonPipBuilder.__init__(self, pkg)
|
|
|
|
self.build_dirname = build_dirname
|
|
|
|
|
|
|
|
@property
|
|
|
|
def build_directory(self):
|
|
|
|
return os.path.join(self.pkg.stage.path, self.build_dirname, "faiss", "python")
|
|
|
|
|
|
|
|
customPip = CustomPythonPipBuilder(pkg, self.build_dirname)
|
|
|
|
customPip.install(pkg, spec, prefix)
|
|
|
|
|
|
|
|
|
|
|
|
class AutotoolsBuilder(spack.build_systems.autotools.AutotoolsBuilder):
|
2020-10-16 15:47:22 +08:00
|
|
|
def configure_args(self):
|
|
|
|
args = []
|
2022-07-31 06:19:18 +08:00
|
|
|
args.extend(self.with_or_without("cuda", activation_value="prefix"))
|
2020-10-16 15:47:22 +08:00
|
|
|
return args
|
|
|
|
|
2022-11-19 04:43:41 +08:00
|
|
|
def build(self, pkg, spec, prefix):
|
2020-10-16 15:47:22 +08:00
|
|
|
make()
|
|
|
|
|
2022-07-31 06:19:18 +08:00
|
|
|
if "+python" in self.spec:
|
|
|
|
make("-C", "python")
|
2020-10-16 15:47:22 +08:00
|
|
|
|
|
|
|
# CPU tests
|
2022-07-31 06:19:18 +08:00
|
|
|
if "+tests" in self.spec:
|
|
|
|
with working_dir("tests"):
|
|
|
|
make("gtest")
|
|
|
|
make("tests")
|
2020-10-16 15:47:22 +08:00
|
|
|
|
|
|
|
# GPU tests
|
2022-07-31 06:19:18 +08:00
|
|
|
if "+tests+cuda" in self.spec:
|
|
|
|
with working_dir(os.path.join("gpu", "test")):
|
|
|
|
make("gtest")
|
|
|
|
make("build") # target added by the patch
|
|
|
|
make("demo_ivfpq_indexing_gpu")
|
2020-10-16 15:47:22 +08:00
|
|
|
|
2022-11-19 04:43:41 +08:00
|
|
|
def install(self, pkg, spec, prefix):
|
2022-07-31 06:19:18 +08:00
|
|
|
make("install")
|
2020-10-16 15:47:22 +08:00
|
|
|
|
2022-07-31 06:19:18 +08:00
|
|
|
if "+python" in self.spec:
|
|
|
|
with working_dir("python"):
|
|
|
|
args = std_pip_args + ["--prefix=" + prefix, "."]
|
2022-01-15 02:37:57 +08:00
|
|
|
pip(*args)
|
2020-10-16 15:47:22 +08:00
|
|
|
|
2022-07-31 06:19:18 +08:00
|
|
|
if "+tests" not in self.spec:
|
2020-10-16 15:47:22 +08:00
|
|
|
return
|
|
|
|
|
|
|
|
if not os.path.isdir(self.prefix.bin):
|
|
|
|
os.makedirs(self.prefix.bin)
|
|
|
|
|
|
|
|
def _prefix_and_install(file):
|
2022-07-31 06:19:18 +08:00
|
|
|
os.rename(file, "faiss_" + file)
|
|
|
|
install("faiss_" + file, self.prefix.bin)
|
2020-10-16 15:47:22 +08:00
|
|
|
|
|
|
|
# CPU tests
|
2022-07-31 06:19:18 +08:00
|
|
|
with working_dir("tests"):
|
2020-10-16 15:47:22 +08:00
|
|
|
# rename the exec to keep consistent with gpu tests
|
2022-07-31 06:19:18 +08:00
|
|
|
os.rename("tests", "TestCpu")
|
|
|
|
_prefix_and_install("TestCpu")
|
2020-10-16 15:47:22 +08:00
|
|
|
|
|
|
|
# GPU tests
|
2022-07-31 06:19:18 +08:00
|
|
|
if "+cuda" in self.spec:
|
|
|
|
with working_dir(os.path.join("gpu", "test")):
|
|
|
|
_prefix_and_install("TestGpuIndexFlat")
|
|
|
|
_prefix_and_install("TestGpuIndexBinaryFlat")
|
|
|
|
_prefix_and_install("TestGpuIndexIVFFlat")
|
|
|
|
_prefix_and_install("TestGpuIndexIVFPQ")
|
|
|
|
_prefix_and_install("TestGpuMemoryException")
|
|
|
|
_prefix_and_install("TestGpuSelect")
|
|
|
|
_prefix_and_install("demo_ivfpq_indexing_gpu")
|
|
|
|
|
|
|
|
@run_after("configure")
|
2020-10-16 15:47:22 +08:00
|
|
|
def _fix_makefile(self):
|
|
|
|
# spack injects its own optimization flags
|
2022-07-31 06:19:18 +08:00
|
|
|
makefile = FileFilter("makefile.inc")
|
|
|
|
makefile.filter("CPUFLAGS = -mavx2 -mf16c", "#CPUFLAGS = -mavx2 -mf16c")
|