1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
|
# Copyright 2013-2023 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
from spack.package import *
class Faiss(AutotoolsPackage, CMakePackage, CudaPackage):
"""Faiss is a library for efficient similarity search and clustering of
dense vectors.
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.
"""
homepage = "https://github.com/facebookresearch/faiss"
url = "https://github.com/facebookresearch/faiss/archive/v1.6.3.tar.gz"
maintainers("bhatiaharsh", "rblake-llnl", "lpottier")
build_system(
conditional("cmake", when="@1.7:"), conditional("autotools", when="@:1.6"), default="cmake"
)
license("MIT")
version("1.7.4", sha256="d9a7b31bf7fd6eb32c10b7ea7ff918160eed5be04fe63bb7b4b4b5f2bbde01ad")
version("1.7.2", sha256="d49b4afd6a7a5b64f260a236ee9b2efb760edb08c33d5ea5610c2f078a5995ec")
version("1.6.3", sha256="e1a41c159f0b896975fbb133e0240a233af5c9286c09a28fde6aefff5336e542")
version("1.5.3", sha256="b24d347b0285d01c2ed663ccc7596cd0ea95071f3dd5ebb573ccfc28f15f043b")
variant("python", default=False, description="Build Python bindings")
variant("shared", default=False, description="Build shared library")
variant("tests", default=False, description="Build Tests")
conflicts("+tests", when="~python", msg="+tests must be accompanied by +python")
depends_on("cmake@3.17:", when="build_system=cmake", type="build")
extends("python", when="+python")
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")
depends_on("py-setuptools", when="+python", type="build")
depends_on("py-numpy", when="+python", type=("build", "run"))
depends_on("swig@4", when="+python", type="build")
depends_on("py-scipy", when="+python+tests", type=("build", "run"))
depends_on("blas")
# 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
patch("fixes-in-v1.5.3.patch", when="@1.5.3")
# 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
patch("fixes-in-v1.6.3.patch", when="@1.6.3")
# 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)
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"))
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):
def configure_args(self):
args = []
args.extend(self.with_or_without("cuda", activation_value="prefix"))
return args
def build(self, pkg, spec, prefix):
make()
if "+python" in self.spec:
make("-C", "python")
# CPU tests
if "+tests" in self.spec:
with working_dir("tests"):
make("gtest")
make("tests")
# GPU tests
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")
def install(self, pkg, spec, prefix):
make("install")
if "+python" in self.spec:
with working_dir("python"):
args = std_pip_args + ["--prefix=" + prefix, "."]
pip(*args)
if "+tests" not in self.spec:
return
if not os.path.isdir(self.prefix.bin):
os.makedirs(self.prefix.bin)
def _prefix_and_install(file):
os.rename(file, "faiss_" + file)
install("faiss_" + file, self.prefix.bin)
# CPU tests
with working_dir("tests"):
# rename the exec to keep consistent with gpu tests
os.rename("tests", "TestCpu")
_prefix_and_install("TestCpu")
# GPU tests
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")
def _fix_makefile(self):
# spack injects its own optimization flags
makefile = FileFilter("makefile.inc")
makefile.filter("CPUFLAGS = -mavx2 -mf16c", "#CPUFLAGS = -mavx2 -mf16c")
|