向量数据库Faiss C++

news2025/3/1 3:17:38

目录

  • 1. Faiss简介
  • 2. FAISS 的主要特点
    • 2.1 高效性
    • 2.2 支持多种索引类型
    • 2.3 灵活性
    • 2.4 GPU 加速
    • 2.5 易于集成
  • 3. 应用场景
  • 4. 安装
    • 4.1 安装依赖
    • 4.2 编译源码
      • 4.2.1 下载Faiss源码
      • 4.2.2 编译
  • 5. Demo
    • 5.1 代码
    • 5.2 编译
    • 5.3 运行

1. Faiss简介

FAISS(Facebook AI Similarity Search)是由 Facebook AI Research 开发的一个高效的相似性搜索库,主要用于大规模向量数据的相似性搜索和聚类。它特别适合处理高维数据,如图像特征、文本嵌入等。

2. FAISS 的主要特点

2.1 高效性

FAISS 采用了多种高效的算法和数据结构,能够快速进行最近邻搜索(Nearest Neighbor Search),即使在大规模数据集上也能保持较好的性能。

2.2 支持多种索引类型

FAISS 提供了多种索引结构,包括:

  • 平面索引(Flat Index):简单直接,适合小规模数据。
  • 倒排索引(IVF):适合大规模数据,使用聚类来减少搜索空间。
  • HNSW(Hierarchical Navigable Small World):一种基于图的索引,适合高维数据。
  • PQ(Product Quantization):通过量化减少内存占用,适合处理大规模数据。

2.3 灵活性

FAISS 支持多种数据类型,包括浮点数和二进制数据。用户可以根据需求选择合适的索引类型和参数。

2.4 GPU 加速

FAISS 支持 GPU 加速,使得在处理非常大的数据集时能够显著提高性能。

2.5 易于集成

FAISS 提供了 C++ 和 Python 接口,方便用户在不同的应用场景中集成和使用。

3. 应用场景

FAISS 广泛应用于以下领域:

  • 图像检索:通过特征向量快速查找相似图像。
  • 自然语言处理:处理文本嵌入,进行相似句子或文档的检索。
  • 推荐系统:根据用户历史行为推荐相似项目。
  • 聚类分析:对高维数据进行聚类。

4. 安装

4.1 安装依赖

该项目依赖于BLAS 组件 OpenBLAS 和 IntelMKL BLAS 【官方支持】

4.2 编译源码

4.2.1 下载Faiss源码

Faiss源码地址

4.2.2 编译

cmake .. -DFAISS_ENABLE_GPU=OFF -DFAISS_ENABLE_PYTHON=OFF -DBUILD_SHARED_LIBS=ON -DFAISS_ENABLE_C_API=ON -DCMAKE_BUILD_TYPE=Release -DFAISS_ENABLE_CUVS=OFF -DBUILD_TESTING=OFF

基本参数介绍:

-DFAISS_ENABLE_GPU=ON *是否构建GPU支持

-DFAISS_ENABLE_PYTHON=OFF 是否构建Python 支持

-DBUILD_TESTING=ON 是否编译Testing 【依赖于googletest】

-DFAISS_ENABLE_C_API=ON 是否需要提高CAPI支持

-DCMAKE_BUILD_TYPE=Release 编译类型

-DBUILD_SHARED_LIBS=ON 是否生成动态库

GPU版本编译请参考:编译Faiss-gpu【InterMKL】C++

5. Demo

5.1 代码

FaissDB.h

#ifndef FACERECOGNITION_CPP_FAISSDB_H
#define FACERECOGNITION_CPP_FAISSDB_H
//faiss
#include <faiss/IndexHNSW.h>
#include <faiss/IndexIDMap.h>
#include <faiss/index_io.h>
#include <vector>
#include <string>
#include <thread>
#include <mutex>
#include <filesystem>

class FaissDB {
public:
	FaissDB(int dim, const std::string &db_name);
	~FaissDB();
	int insert(int n, const std::vector<float> &vec, const std::vector<faiss::idx_t> &ids);
	int query(int n, const std::vector<float> &vec, int topk, std::vector<float> &distances, std::vector<faiss::idx_t> &indices);
	int remove(const faiss::IDSelector& sel);
private:
	std::unique_ptr<faiss::IndexHNSWFlat> _indexHNSW_ptr;
	std::unique_ptr<faiss::Index> _indexIDMap_ptr;
	std::mutex _rw_lock;
	std::string _db_name;
};

#endif //FAISSDB_H

FaissDB.cpp

#include "FaissDB.h"
#include <iostream>

using namespace std;

FaissDB::FaissDB(int dim, const std::string &db_name)
{
	this->_db_name = db_name;
	if (std::filesystem::exists(db_name))
	{
		_indexIDMap_ptr = unique_ptr<faiss::Index>(faiss::read_index(db_name.c_str()));
		std::cout<<"load faiss data success from file"<<std::endl;
	}
	else
	{
		_indexHNSW_ptr = unique_ptr<faiss::IndexHNSWFlat>(new faiss::IndexHNSWFlat(dim, 200));
		_indexIDMap_ptr= unique_ptr<faiss::IndexIDMap>(new faiss::IndexIDMap(_indexHNSW_ptr.get()));
	}
}

FaissDB::~FaissDB()
{
}

int FaissDB::insert(int n, const std::vector<float>& vec, const std::vector<faiss::idx_t>& ids)
{
	std::lock_guard<std::mutex> lk(_rw_lock);
	_indexIDMap_ptr->add_with_ids(n, vec.data(), ids.data());
	faiss::write_index(_indexIDMap_ptr.get(),  _db_name.c_str());
	return 0;
}

int FaissDB::query(int n, const std::vector<float>& vec, int topk, std::vector<float>& distances,
	std::vector<faiss::idx_t>& indices)
{
	std::lock_guard<std::mutex> lk(_rw_lock);
	if (_indexIDMap_ptr->ntotal == 0)
	{
		std::cerr << "Index is empty. Please add data before searching." << std::endl;
		return -1;
	}
	_indexIDMap_ptr->search(n, vec.data(), topk, distances.data(), indices.data());

	return 0;
}

int FaissDB::remove(const faiss::IDSelector& sel)
{
	return _indexIDMap_ptr->remove_ids(sel);
}

faiss-demo.cpp

#include "FaissDB.h"
using namespace std;

int main(){
	const int d = 128;
    const int n = 5;
    std::vector<float> data(d * n);

    for (int i = 0; i < d * n; ++i) {
        data[i] = static_cast<float>(rand()) / RAND_MAX;
    }

    std::vector<faiss::idx_t> ids = {101, 102, 103, 104, 105};

    int M = 16;
    FaissDB faiss_db(d, "faiss.index");
	faiss_db.insert(n, data.data(), ids.data());

    const int k = 3;
    std::vector<float> query(d);

    for (int i = 0; i < d; ++i) {
        query[i] = static_cast<float>(rand()) / RAND_MAX;
    }

    std::vector<faiss::idx_t> result_ids(k);
    std::vector<float> distances(k);

    faiss_db.query(1, query.data(), k, distances.data(), result_ids.data());

    std::cout << "search result:" << std::endl;
    for (int i = 0; i < k; ++i) {
        std::cout << "vector ID: " << result_ids[i] << ", dis: " << distances[i] << std::endl;
    }
    
	return 0;
}

这里我封装了3个接口,索引类型为HNSW,insert的时候指定id。
注意:如果要使用add_with_ids方法插入index,必须使用faiss::IndexIDMap封装一下,否则会报错

5.2 编译

g++ faiss-demo.cpp FaissDB.cpp -o faiss-demo -I/usr/local/include -L/usr/local/lib -lfaiss -fopenmp -lopenblas

5.3 运行

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2259149.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

群控系统服务端开发模式-应用开发-获取登录者今天操作日志

一、后端api开放路由 在根目录下route文件夹下app.php文件中&#xff0c;在perimission的group中添加如下代码&#xff1a; Route::get(member/personal_log,permission.Member/personalLog);// 获取个人信息操作接口 二、后端api添加方法 在根目录下app文件夹下controller文…

淘宝/天猫获得淘宝商品详情高级版 API 接口获取

要获取淘宝/天猫商品详情高级版API接口&#xff0c;您可以按照以下步骤操作&#xff1a; 注册淘宝开放平台账号&#xff1a; 访问淘宝开放平台官网&#xff0c;点击“开发者中心”&#xff0c;使用淘宝账号登录或注册新账号。这是获取API权限和密钥的第一步。 创建应用并获取AP…

腾讯云系统盘扩容

在腾讯云申请空间后&#xff0c;只要执行三行命令 云硬盘 在线扩展系统盘分区及文件系统-操作指南-文档中心-腾讯云 安装工具 yum install -y cloud-utils-growpart 给/eav/vda1扩分区 LC_ALLen_US.UTF-8 growpart /dev/vda 1 挂载扩容 ext4 文件系统 resize2fs /dev/vda1 …

数据结构 ——二叉树转广义表

数据结构 ——二叉树转广义表 1、树转广义表 如下一棵树&#xff0c;转换为广义表 root(c(a()(b()()))(e(d()())(f()(j(h()())())))) (根&#xff08;左子树&#xff09;&#xff08;右子树&#xff09;) 代码实现 #include<stdio.h> #include<stdlib.h>//保存…

人工智能大语言模型起源篇(二),从通用语言微调到驾驭LLM

上一篇&#xff1a;《人工智能大语言模型起源篇&#xff08;一&#xff09;&#xff0c;从哪里开始》 &#xff08;5&#xff09;Howard 和 Ruder 于2018年发表的《Universal Language Model Fine-tuning for Text Classification》&#xff0c;https://arxiv.org/abs/1801.06…

设置笔记本同时连接内外网

原理&#xff1a;通过笔记本和手机相连&#xff0c;实现双网卡功能能。笔记本连接内网wifi、同时手机端开启usb网络共享&#xff0c;笔记本就有了两个网&#xff0c;然配置那个访问外网&#xff0c;那个访问内网。 1.笔记本wifi连接内网wifi 2.手机端共享网络。 手机打开 -【…

【Hexo】Hexo基本使用

Hexo官网&#xff1a;https://hexo.io/ Hexo Github: https://github.com/hexojs/hexo Hexo Awesome: https://github.com/hexojs/awesome-hexo 1、初始化 需要node 环境&#xff0c;不再赘述node安装过程 推荐使用cnpm进行安装 npm install -g cnpm --registryhttps://regi…

PPO系列4 - Reward模型训练

流程&#xff1a; 训练Reward模型 训练数据&#xff1a; 相比给每条回答进行打分&#xff0c;人类更容易给出两者的比较结果。这样标注出来的数据&#xff0c;准确性更高。 模型&#xff1a; 可以使用和生成模型能力差不多的模型&#xff08;或者更强的模型&#xff09;&#x…

5.11如何用PyTorch实现ResNet34

ResNet34是由16个残差块和一个全局平局池化层和一个全连接层组成&#xff0c;即32个卷积层1个pooling层1和fc层。 训练的数据集是cifar10数据集&#xff0c;训练次数5&#xff0c;损失函数为CrossEntropyLoss()&#xff0c;optimizer torch.optim.SGD。 1.先定义残差块&#…

yolov,coco,voc标记的睡岗检测数据集,可识别在桌子上趴着睡,埋头睡觉,座椅上靠着睡,平躺着睡等多种睡姿的检测,6549张图片

yolov&#xff0c;coco,voc标记的睡岗检测数据集&#xff0c;可识别在桌子上趴着睡&#xff0c;埋头睡觉&#xff0c;座椅上靠着睡&#xff0c;平躺着睡等多种睡姿的检测&#xff0c;6549张图片 数据集分割 6549总图像数 训练组91&#xff05; 5949图片 有效集9&#x…

【C++游记】string的使用和模拟实现

枫の个人主页 你不能改变过去&#xff0c;但你可以改变未来 算法/C/数据结构/C Hello&#xff0c;这里是小枫。C语言与数据结构和算法初阶两个板块都更新完毕&#xff0c;我们继续来学习C的内容呀。C是接近底层有比较经典的语言&#xff0c;因此学习起来注定枯燥无味&#xf…

【深度学习量化交易7】miniQMT快速上手教程案例集——使用xtQuant进行历史数据下载篇

我是Mr.看海&#xff0c;我在尝试用信号处理的知识积累和思考方式做量化交易&#xff0c;应用深度学习和AI实现股票自动交易&#xff0c;目的是实现财务自由~ 目前我正在开发基于miniQMT的量化交易系统。 在前几篇的文章中讲到&#xff0c;我正在开发的看海量化交易系统&#x…

相差不超过k的最多数,最长公共子序列(一),排序子序列,体操队形,青蛙过河

相差不超过k的最多数 链接:相差不超过k的最多数 来源&#xff1a;牛客网 题目描述&#xff1a; 给定一个数组&#xff0c;选择一些数&#xff0c;要求选择的数中任意两数差的绝对值不超过 &#x1d458; 。问最多能选择多少个数&#xff1f; 输入描述: 第一行输入两个正整…

解决navicat 导出excel数字为科学计数法问题

一、原因分析 用程序导出的csv文件&#xff0c;当字段中有比较长的数字字段存在时&#xff0c;在用excel软件查看csv文件时就会变成科学技术法的表现形式。 其实这个问题跟用什么语言导出csv文件没有关系。Excel显示数字时&#xff0c;如果数字大于12位&#xff0c;它会自动转化…

C++3--内联函数、auto

1.内联函数 1.1概念 以inline修饰的函数叫做内联函数&#xff0c;编译时C编译器会在调用内联函数的地方展开&#xff0c;没有函数调用建立栈帧的开销&#xff0c;内联函数提升程序的效率 如果在上述函数前增加inline关键字将其改成内联函数&#xff0c;在编译期间编译器会用函…

AES 与 SM4 加密算法:深度解析与对比

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/literature?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;…

视频怎么转音频mp3?5种视频转音频的方法

在视频剪辑时&#xff0c;将视频中的音频提取出来并转换为MP3格式已成为许多人的需求。无论是为了制作音乐播放列表、剪辑音频片段&#xff0c;还是为了在其他设备上更方便地播放&#xff0c;将视频转换为音频MP3都显得尤为重要。下面将介绍五种实用的方法&#xff0c;帮助你轻…

Maven学习(传统Jar包管理、Maven依赖管理(导入坐标)、快速下载指定jar包)

目录 一、传统Jar包管理。 &#xff08;1&#xff09;基本介绍。 &#xff08;2&#xff09;传统的Jar包导入方法。 1、手动寻找Jar包。并放置到指定目录下。 2、使用IDEA的库管理功能。 3、配置环境变量。 &#xff08;3&#xff09;传统的Jar包管理缺点。 二、Maven。 &#…

【机器学习】分类器

在机器学习(Machine Learning&#xff0c;ML)中&#xff0c;分类器泛指算法或模型&#xff0c;用于将输入数据分为不同的类别或标签。分类器是监督学习的一部分&#xff0c;它依据已知的数据集中的特征和标签进行训练&#xff0c;并根据这些学习到的知识对新的未标记数据进行分…

uni-app在image上绘制点位并回显

在 Uni-app 中绘制多边形可以通过使用 Canvas API 来实现。Uni-app 是一个使用 Vue.js 开发所有前端应用的框架&#xff0c;同时支持编译为 H5、小程序等多个平台。由于 Canvas 是 H5 和小程序中都支持的 API&#xff0c;所以通过 Canvas 绘制多边形是一个比较通用的方法。 1.…