mirror of
https://github.com/facebookresearch/faiss.git
synced 2026-10-11 22:50:00 +00:00
Summary: Pull Request resolved: https://github.com/facebookresearch/faiss/pull/5587 **TL;DR:** Adds a batched 20-byte Hamming kernel that measures eight codes per call, the only thing that helps the 160-bit width, worth 1.21x end to end. A 20-byte code has no vector kernel at any x86 SIMD level. `HammingComputer20` measures one distance with three scalar popcounts at every level, including `AVX512_VPOPCNT`, so a scan of 160-bit codes runs the same code everywhere. Vectorizing a single 20-byte distance does not help. A masked 256-bit load plus `vpopcntq` plus a horizontal reduction measures the same as the scalar body, because the reduction costs more than the three popcounts it replaces. Measuring several codes per call does help, because it amortizes that reduction. This adds `hamming_batch()` to `HammingComputer20` at `AVX512_VPOPCNT`, which measures eight codes at once: - Eight codes span 160 bytes. `_mm512_popcnt_epi8` gives a count per byte. - `_mm512_sad_epu8` sums each aligned 8-byte group. - A 20-byte code covers two whole groups plus half of a group it shares with its neighbour, so each code needs one scalar popcount for its half. `IVFBinaryScannerL2::scan_codes` and `IVFBinaryScannerL2::scan_codes_range` call `hamming_batch()` when the computer declares a `batch_size`, then measure the remaining codes one at a time. A computer without a `batch_size` keeps the existing loop, so no other code size changes. The scanner holds the tiled query, and the constructor rejects a code size that does not match the computer. A caller therefore cannot reach the batch kernel with a stride the kernel does not read. The byte-wise popcount needs `AVX512_BITALG`, which is a separate CPUID bit from `AVX512_VPOPCNTDQ`. This adds the flag to the `AVX512_VPOPCNT` level and requires both bits to select it. Every CPU that has VPOPCNTDQ also has BITALG, so no CPU loses the level. An alternative byte-wise popcount built from `vpshufb`, which needs neither bit and would run at the plain `AVX512` level, measures only 1.08x against 1.54x, so it is not worth the wider reach. Reviewed By: alibeklfc Differential Revision: D118971285 fbshipit-source-id: 5fd4637c972e5c55e2695b32b9b15fba8181a242
173 lines
6.4 KiB
CMake
173 lines
6.4 KiB
CMake
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
#
|
|
# This source code is licensed under the MIT license found in the
|
|
# LICENSE file in the root directory of this source tree.
|
|
|
|
cmake_minimum_required(VERSION 3.17 FATAL_ERROR)
|
|
|
|
project(faiss_c_library LANGUAGES C CXX)
|
|
|
|
set(CMAKE_C_STANDARD 11)
|
|
|
|
set(FAISS_C_SRC
|
|
AutoTune_c.cpp
|
|
Clustering_c.cpp
|
|
IndexFlat_c.cpp
|
|
IndexHNSW_c.cpp
|
|
IndexIVFFlat_c.cpp
|
|
IndexIVF_c.cpp
|
|
IndexLSH_c.cpp
|
|
IndexPreTransform_c.cpp
|
|
VectorTransform_c.cpp
|
|
IndexShards_c.cpp
|
|
IndexReplicas_c.cpp
|
|
Index_c.cpp
|
|
IndexBinary_c.cpp
|
|
IndexBinaryIVF_c.cpp
|
|
IndexBinaryFlat_c.cpp
|
|
IndexScalarQuantizer_c.cpp
|
|
MetaIndexes_c.cpp
|
|
clone_index_c.cpp
|
|
error_impl.cpp
|
|
index_factory_c.cpp
|
|
index_io_c.cpp
|
|
impl/AuxIndexStructures_c.cpp
|
|
impl/io_c.cpp
|
|
invlists/DirectMap_c.cpp
|
|
utils/distances_c.cpp
|
|
utils/utils_c.cpp
|
|
)
|
|
|
|
add_library(faiss_c ${FAISS_C_SRC})
|
|
target_link_libraries(faiss_c PRIVATE faiss)
|
|
|
|
add_library(faiss_c_avx2 ${FAISS_C_SRC})
|
|
target_link_libraries(faiss_c_avx2 PRIVATE faiss_avx2)
|
|
if(NOT FAISS_OPT_LEVEL STREQUAL "avx2" AND NOT FAISS_OPT_LEVEL STREQUAL "avx512" AND NOT FAISS_OPT_LEVEL STREQUAL "avx512_spr")
|
|
set_target_properties(faiss_c_avx2 PROPERTIES EXCLUDE_FROM_ALL TRUE)
|
|
endif()
|
|
if(NOT WIN32)
|
|
target_compile_options(faiss_c_avx2 PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-mavx2 -mfma -mf16c -mpopcnt>)
|
|
else()
|
|
# MSVC enables FMA with /arch:AVX2; no separate flags for F16C, POPCNT
|
|
# Ref. FMA (under /arch:AVX2): https://docs.microsoft.com/en-us/cpp/build/reference/arch-x64
|
|
# Ref. F16C (2nd paragraph): https://walbourn.github.io/directxmath-avx2/
|
|
# Ref. POPCNT: https://docs.microsoft.com/en-us/cpp/intrinsics/popcnt16-popcnt-popcnt64
|
|
target_compile_options(faiss_c_avx2 PRIVATE $<$<COMPILE_LANGUAGE:CXX>:/arch:AVX2>)
|
|
endif()
|
|
|
|
add_library(faiss_c_avx512 ${FAISS_C_SRC})
|
|
target_link_libraries(faiss_c_avx512 PRIVATE faiss_avx512)
|
|
if(NOT FAISS_OPT_LEVEL STREQUAL "avx512")
|
|
set_target_properties(faiss_c_avx512 PROPERTIES EXCLUDE_FROM_ALL TRUE)
|
|
endif()
|
|
if(NOT WIN32)
|
|
# All modern CPUs support F, CD, VL, DQ, BW extensions.
|
|
# Ref: https://en.wikipedia.org/wiki/AVX512
|
|
target_compile_options(faiss_c_avx512 PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-mavx2 -mfma -mf16c -mavx512f -mavx512cd -mavx512vl -mavx512dq -mavx512bw -mpopcnt>)
|
|
else()
|
|
target_compile_options(faiss_c_avx512 PRIVATE $<$<COMPILE_LANGUAGE:CXX>:/arch:AVX512>)
|
|
endif()
|
|
|
|
add_library(faiss_c_avx512_spr ${FAISS_C_SRC})
|
|
target_link_libraries(faiss_c_avx512_spr PRIVATE faiss_avx512_spr)
|
|
if(NOT FAISS_OPT_LEVEL STREQUAL "avx512_spr")
|
|
set_target_properties(faiss_c_avx512_spr PROPERTIES EXCLUDE_FROM_ALL TRUE)
|
|
endif()
|
|
if(NOT WIN32)
|
|
# Architecture mode to support AVX512 extensions available since Intel(R) Sapphire Rapids.
|
|
# Ref: https://networkbuilders.intel.com/solutionslibrary/intel-avx-512-fp16-instruction-set-for-intel-xeon-processor-based-products-technology-guide
|
|
target_compile_options(faiss_c_avx512_spr PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-mavx2 -mfma -mf16c -mavx512f -mavx512cd -mavx512vl -mavx512dq -mavx512bw -mavx512vpopcntdq -mavx512bitalg -mpopcnt -mavx512fp16 -mavx512bf16>)
|
|
else()
|
|
target_compile_options(faiss_c_avx512_spr PRIVATE $<$<COMPILE_LANGUAGE:CXX>:/arch:AVX512>)
|
|
endif()
|
|
|
|
add_library(faiss_c_sve ${FAISS_C_SRC})
|
|
target_link_libraries(faiss_c_sve PRIVATE faiss_sve)
|
|
if(NOT FAISS_OPT_LEVEL STREQUAL "sve")
|
|
set_target_properties(faiss_c_sve PROPERTIES EXCLUDE_FROM_ALL TRUE)
|
|
endif()
|
|
if(NOT WIN32)
|
|
if("${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG} " MATCHES "(^| )-march=native")
|
|
# Do nothing, expect SVE to be enabled by -march=native
|
|
elseif("${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG} " MATCHES "(^| )(-march=armv[0-9]+(\\.[1-9]+)?-[^+ ](\\+[^+$ ]+)*)")
|
|
# Add +sve
|
|
target_compile_options(faiss_c_sve PRIVATE $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:DEBUG>>:${CMAKE_MATCH_2}+sve>)
|
|
elseif(NOT "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG} " MATCHES "(^| )-march=armv")
|
|
# No valid -march, so specify -march=armv8-a+sve as the default
|
|
target_compile_options(faiss_c_sve PRIVATE $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:DEBUG>>:-march=armv8-a+sve>)
|
|
endif()
|
|
if("${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE} " MATCHES "(^| )-march=native")
|
|
# Do nothing, expect SVE to be enabled by -march=native
|
|
elseif("${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE} " MATCHES "(^| )(-march=armv[0-9]+(\\.[1-9]+)?-[^+ ](\\+[^+$ ]+)*)")
|
|
# Add +sve
|
|
target_compile_options(faiss_c_sve PRIVATE $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:RELEASE>>:${CMAKE_MATCH_2}+sve>)
|
|
elseif(NOT "${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE} " MATCHES "(^| )-march=armv")
|
|
# No valid -march, so specify -march=armv8-a+sve as the default
|
|
target_compile_options(faiss_c_sve PRIVATE $<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:RELEASE>>:-march=armv8-a+sve>)
|
|
endif()
|
|
endif()
|
|
|
|
function(faiss_install_headers headers p)
|
|
foreach(h ${headers})
|
|
get_filename_component(f ${h} DIRECTORY)
|
|
install(FILES ${h}
|
|
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/faiss/${p}/${f}
|
|
)
|
|
endforeach()
|
|
endfunction()
|
|
|
|
file(GLOB FAISS_C_API_HEADERS
|
|
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
|
|
"*.h"
|
|
"impl/*.h"
|
|
"invlists/*.h"
|
|
"utils/*.h")
|
|
|
|
faiss_install_headers("${FAISS_C_API_HEADERS}" c_api)
|
|
|
|
install(TARGETS faiss_c
|
|
EXPORT faiss-targets
|
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
)
|
|
if(FAISS_OPT_LEVEL STREQUAL "avx2")
|
|
install(TARGETS faiss_c_avx2
|
|
EXPORT faiss-targets
|
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
)
|
|
endif()
|
|
if(FAISS_OPT_LEVEL STREQUAL "avx512")
|
|
install(TARGETS faiss_c_avx2 faiss_c_avx512
|
|
EXPORT faiss-targets
|
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
)
|
|
endif()
|
|
if(FAISS_OPT_LEVEL STREQUAL "avx512_spr")
|
|
install(TARGETS faiss_c_avx2 faiss_c_avx512_spr
|
|
EXPORT faiss-targets
|
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
)
|
|
endif()
|
|
if(FAISS_OPT_LEVEL STREQUAL "sve")
|
|
install(TARGETS faiss_c_sve
|
|
EXPORT faiss-targets
|
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
)
|
|
endif()
|
|
|
|
add_executable(example_c EXCLUDE_FROM_ALL example_c.c)
|
|
target_link_libraries(example_c PRIVATE faiss_c)
|
|
|
|
add_executable(example_search_params_ivf_c EXCLUDE_FROM_ALL
|
|
example_search_params_ivf_c.c)
|
|
target_link_libraries(example_search_params_ivf_c PRIVATE faiss_c)
|
|
|
|
if(FAISS_ENABLE_GPU)
|
|
add_subdirectory(gpu)
|
|
endif()
|