GPUに対応したFAISSをソースコードからビルドする
概要
近似近傍探索のライブラリFAISS[1]のGPUに対応したバージョンをソースからインストールする手順について備忘録として記す。
環境
- OS: Ubuntu 22.04.3 LTS (Docker)
- GPU: GeForce RTX 4090
- CUDA: 12.1
- base docker image:
nvidia/cuda:11.8.0-devel-ubuntu22.04
公式インストール手順の躓きどころ
基本的には公式ドキュメント[2]の通りなのだが、いくつかすんなりといかないところがあったのでそれらを中心に記す。
MKLのインストール
MKLというのは数値計算のライブラリらしいが、いくつかの実装がある。
ここでは公式ドキュメントが推奨するIntelのoneMKL[3]をインストールした。
なお、インストール方法がいくつか提供されているが、自分の場合はAPTでインストールした。
ビルドオプション
自分の環境では以下のようにした。MKL_LIBRARIES
にはMKLのライブラリのパスを指定するらしいが、具体的にどの*.so
を指定するのかについて、検索した限り解決策が見つからなかった。ChatGPT-4の回答を元にlibmkl_rt.so.2
のパスを指定したら動作したためこの設定を採用した(理にかなっているのかは不明)。
CUDA_ARCHITECTURES
はNVIDIAが製造するGPU製品ごとにcapabilityという番号が付与されているので、CUDAの公式ドキュメントの表[4]をもとにその番号を指定する。自分の使用しているGeForce RTX 4090のcapabilityは8.9なので89
を指定した。
MKL_ROOT=/opt/intel/oneapi/mkl/latest/lib/intel64
cmake -B build . \
-DFAISS_ENABLE_GPU=ON \
-DFAISS_ENABLE_PYTHON=ON \
-DFAISS_ENABLE_RAFT=OFF \
-DBUILD_TESTING=ON \
-DBUILD_SHARED_LIBS=ON \
-DFAISS_ENABLE_C_API=ON \
-DCMAKE_BUILD_TYPE=Release \
-DFAISS_OPT_LEVEL=avx2 \
-DBLA_VENDOR=Intel10_64_dyn \
-DMKL_LIBRARIES=$MKL_ROOT/libmkl_rt.so.2 \
-DCUDAToolkit_ROOT=/usr/local/cuda-11.8 \
-DCMAKE_CUDA_ARCHITECTURES="89" \
-DPython_EXECUTABLE=/usr/bin/python3.10
最終的なインストール手順
執筆時点(2023.10.3)における自分の環境でのインストール手順は最終的に以下のようになった。
#!/bin/bash
#===================================================================================================
# 1. Install MKL
# ref: https://www.intel.com/content/www/us/en/developer/tools/oneapi/onemkl-download.html?operatingsystem=linux&distributions=aptpackagemanager
wget -O- https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB |
gpg --dearmor | tee /usr/share/keyrings/oneapi-archive-keyring.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/oneapi-archive-keyring.gpg] https://apt.repos.intel.com/oneapi all main" |
tee /etc/apt/sources.list.d/oneAPI.list
apt update && apt install -y intel-oneapi-mkl
# set environment variables
source /opt/intel/oneapi/setvars.sh intel64
# add init script to bashrc
printf "\n# initialize oneapi\nsource /opt/intel/oneapi/setvars.sh intel64\n" >>~/.bashrc
#===================================================================================================
# 2. Build FAISS from source
# ref: https://github.com/facebookresearch/faiss/blob/main/INSTALL.md#building-from-source
# install requirements to build python bindings
apt -y install swig
if [ ! -d faiss ]; then
git clone https://github.com/facebookresearch/faiss
fi
cd faiss
# ref:
# - cuda capability: https://developer.nvidia.com/cuda-gpus#compute
# GeForce RTX 4090 -> 8.9
if [ ! -d build ]; then
MKL_ROOT=/opt/intel/oneapi/mkl/latest/lib/intel64
cmake -B build . \
-DFAISS_ENABLE_GPU=ON \
-DFAISS_ENABLE_PYTHON=ON \
-DFAISS_ENABLE_RAFT=OFF \
-DBUILD_TESTING=ON \
-DBUILD_SHARED_LIBS=ON \
-DFAISS_ENABLE_C_API=ON \
-DCMAKE_BUILD_TYPE=Release \
-DFAISS_OPT_LEVEL=avx2 \
-DBLA_VENDOR=Intel10_64_dyn \
-DMKL_LIBRARIES=$MKL_ROOT/libmkl_rt.so.2 \
-DCUDAToolkit_ROOT=/usr/local/cuda-11.8 \
-DCMAKE_CUDA_ARCHITECTURES="89" \
-DPython_EXECUTABLE=/usr/bin/python3.10
# build faiss C++ library
make -C build -j faiss
# build the python bindings
make -C build -j swigfaiss
fi
(cd build/faiss/python && python setup.py install)
# check if successfully installed
pip freeze | grep faiss
# build & run basic CPU example
make -C build demo_ivfpq_indexing
./build/demos/demo_ivfpq_indexing
# build & run basic GPU example
make -C build demo_ivfpq_indexing_gpu
./build/faiss/gpu/test/demo_ivfpq_indexing_gpu
# run realtime benchmark (CPU)
# wget ftp://ftp.irisa.fr/local/texmex/corpus/sift.tar.gz
# tar -xzvf sift.tar.gz
# mv sift sift1M
# make -C build demo_sift1M
# build/demos/demo_sift1M
参考資料
- [1] facebookresearch/faiss
- [2] Building from source - FAISS
- [3] Get Intel® oneAPI Math Kernel Library (oneMKL)
- [4] Your GPU Compute Capability
Appendix
python bindingをシステムにインストールする
上記手順ではfaissディレクトリを削除するとfaissライブラリを参照できなくなる。
ビルドした資材のみシステムにインストールし、他の中間生成物に依存しないようにするには以下のようにする。
# build wheel
(cd build/faiss/python && pip wheel . --no-deps)
# install *.so files to system
cp build/faiss/libfaiss.so /usr/local/lib/.
cp build/faiss/python/lib/faiss_python_callbacks.so /usr/local/lib/.
# install python bindings
(cd build/faiss/python && pip install faiss*.whl)
NVIDIAが提供しているRAFTというライブラリが早いらしい。
python bindingのテスト
python上から利用できるかの確認は以下のようにする(コードはここから転載した)。
import faiss
import numpy as np
d = 64 # dimension
nb = 1000000 # database size
nq = 10000 # nb of queries
np.random.seed(1234) # make reproducible
xb = np.random.random((nb, d)).astype('float32')
xb[:, 0] += np.arange(nb) / 1000.
xq = np.random.random((nq, d)).astype('float32')
xq[:, 0] += np.arange(nq) / 1000.
gpu_resource = faiss.StandardGpuResources()
cpu_index = faiss.IndexFlatL2(d)
gpu_index = faiss.index_cpu_to_gpu(gpu_resource, 0, cpu_index)
gpu_index.add(xb)
k = 4 # we want to see 4 nearest neighbors
D, I = gpu_index.search(xb, k) # actual search
print(I)
[[ 0 393 363 78]
[ 1 555 277 364]
[ 2 304 101 13]
...
[999997 999636 999411 999877]
[999998 999575 999987 999933]
[999999 999916 999470 999911]]