Faiss能解决什么问题?Faiss是什么?

1. Faiss能解决什么问题?
为了比较两个非结构化的数据是否相似,例如两张图片是不是类似,两段文本表达的含义是否类似,则需要将非结构化的数据先转成向量数据,然后再进行相似度比较。
如何通过向量化技术比较非结构化数据,可以参考:https://www.cnblogs.com/twosedar/p/18973770
问题来了,在一群数据中找到两个相似度最高的向量数据,最常用的是暴力搜索法,也就是逐一遍历所有向量,计算距离(如欧氏距离、余弦相似度),虽准确,但时间复杂度高,无法处理百万级以上数据。
这个问题在2015年严重困扰了Facebook公司的技术团队,因为作为当时世界上最大的社交网站,时刻要处理数十亿的图片,然后根据用户喜好推荐相似的内容。
于是Facebook成立专门的项目组开展了研究,最终在2017年取得重大突破,研发出了Faiss(Facebook AI Similarity Search),专门用于解决大规模向量数据的快速搜索问题。Faiss可以在17.7微秒完成10亿图像搜索。而传统的暴力搜索算法,往往需要数小时。
2017年3月项目组发表论文《Billion-scale similarity search with GPUs》公开了核心技术(论文地址 https://arxiv.org/pdf/1702.08734 ),开源了源代码(代码地址:https://github.com/facebookresearch/faiss)。
Faiss的发布引起了业界轰动。
2. Faiss具体是什么?
Faiss本质是一个算法库,核心能力是快速完成大规模(例如十亿规模)向量数据的相似度搜索。它的关键能力是解决了大规模向量检索慢的问题。
它使用 C++语言 实现,并提供 Python封装的库和接口。
业界有人会称Faiss是向量数据库,但Faiss不是传统意义上的数据库,因为它并不具备数据持久化存储的能力,但它是很多向量数据库(例如Milvus)的核心引擎,因为向量数据库最核心的能力就是相似度搜索。
Faiss有点像向量搜索时代的“Linux内核”。

3. Faiss具体长什么样子?
可以通过一个Python代码中调用Faiss库看一下Faiss具体长什么样子。
首先,如果想在python中使用Faiss,则需要安装Faiss库。
Faiss提供CPU和GPU版本,如果做简单验证,可以使用CPU版本。可以使用pip安装
# pip install faiss-cpu
然后编写一段代码,利用Faiss在模拟数据(10个4维向量)中找到和被搜索向量相似度最近的3个向量,并打印出来。

# 步骤1(前置条件):安装Faiss(CPU版)
# pip install faiss-cpu

import numpy as np
import faiss

# 步骤2:创建模拟数据(10个4维向量)
dim = 4  # 向量维度
database = np.array([
    [0.1, 0.2, 0.3, 0.4],
    [0.5, 0.6, 0.7, 0.8],
    [0.9, 1.0, 1.1, 1.2],
    [0.3, 0.2, 0.1, 0.1],
    [1.0, 0.5, 0.0, 0.5],
    [0.2, 0.3, 0.4, 0.5],
    [0.7, 0.8, 0.9, 1.0],
    [0.0, 0.1, 0.2, 0.3],
    [0.4, 0.5, 0.6, 0.7],
    [0.6, 0.7, 0.8, 0.9]
], dtype='float32')

# 步骤3:创建Faiss索引(最简单的平面索引)
index = faiss.IndexFlatL2(dim)  # 指定Faiss通过计算向量间L2距离(欧氏距离)作为索引类型
                                # 其他的索引类型还有很多,例如IndexIVFFlat(倒排索引),IndexIVFPQ(量化索引)等

# 步骤4:添加模拟数据到索引中
index.add(database)
print(f"索引包含向量数: {index.ntotal}")

# 步骤5:执行相似度搜索
query_vector = np.array([[0.25, 0.25, 0.25, 0.25]], dtype='float32')  # 自定义一个被查询的向量
k = 3  # 返回最相似的3个结果

distances, indices = index.search(query_vector, k)  # 核心代码,使用Faiss索引搜索相识度最近的3个结果

# 步骤6:解读结果
print("\n=== 搜索结果 ===")
print(f"查询向量: {query_vector[0]}")
print(f"最相似的{k}个向量索引: {indices[0]}")
print(f"对应距离: {distances[0]}")

# 打印具体向量
print("\n匹配的向量:")
for i, idx in enumerate(indices[0]):
    print(f"Top {i+1}: {database[idx]} (距离: {distances[0][i]:.4f})")

以上代码的打印结果

索引包含向量数: 10

=== 搜索结果 ===
查询向量: [0.25 0.25 0.25 0.25]
最相似的3个向量索引: [0 3 7]
对应距离: [0.05 0.05 0.09]

匹配的向量:
Top 1: [0.1 0.2 0.3 0.4] (距离: 0.0500)
Top 2: [0.3 0.2 0.1 0.1] (距离: 0.0500)
Top 3: [0. 0.1 0.2 0.3] (距离: 0.0900)

4. Faiss发展里程碑
1)2017年:横空出世
论文《Billion-scale similarity search with GPUs》发表
首秀即巅峰:在Deep1B数据集刷新10亿向量搜索速度纪录。
2)2020年:催生新物种
基于Faiss 的专业向量数据库崛起,典型代表是 Milvus。
3)2023至今:大模型时代基础设施
Faiss成为RAG(检索增强生成)的核心组件。

原创作者: twosedar 转载于: https://www.cnblogs.com/twosedar/p/18982109
<think>我们正在处理一个关于C语言编译警告的问题。用户遇到了一个特定的警告信息:478:7:warning:ignoringreturnvalueof'fread',declaredwithattributewarn_unused_result[-Wunused-result]fread(buf,s.st_size,1,file);用户想知道这个警告的含义,并且询问切换到Ubuntu16.04是否能解决这个问题。###问题分析首先,我们分析这个警告的含义:1.这个警告是由gcc编译器产生的,警告编号是`-Wunused-result`。2.它表示函数`fread`的返回值被忽略(没有被使用)。3.`fread`函数被声明为`warn_unused_result`属性,这意味着编译器强制要求程序员检查其返回值,否则就会产生警告。接下来,我们理解`fread`函数:-函数原型:`size_tfread(void*ptr,size_tsize,size_tnmemb,FILE*stream);`-它尝试从流(stream)中读取数据到指针(ptr)指向的数组中。读取的元素数是`nmemb`,每个元素的大小为`size`。-返回值:返回成功读取的元素个数。如果返回值小于要求的元素个数,则表示可能发生错误或者到达文件末尾(EOF)。因此,忽略返回值可能导致程序无法正确处理文件读取中的错误或结束条件。###警告原因编译器发出这个警告是因为忽略`fread`的返回值可能引发潜在的错误:-如果读取失败,程序可能使用未初始化或不完整的数据。-忽略返回值可能导致程序逻辑错误(如假设已经读取了整个文件,但实际上只读取了一部分)。###解决方案解决这个警告的正确做法是不要忽略返回值,而是检查它以确保读取操作成功。例如,我们可以这样修改代码:```csize_tret=fread(buf,s.st_size,1,file);if(ret<1){//处理错误或EOF//可以使用feof(file)和ferror(file)来区分是EOF还是错误}```但是,注意`fread`的调用方式:它要求读取1个元素,每个元素的大小是`s.st_size`。也就是说,它试图一次性读取整个文件。因此,如果返回的值小于1(即0),就意味着没有读到任何元素,可能是EOF或错误。更常见的做法是读取多个小块,但这里是一次性读取整个文件。因此,检查返回值是否为1(因为期望读取1个元素)即可。###关于切换到Ubuntu16.04用户询问切换到Ubuntu16.04是否能够解决这个警告。-这个警告是由编译器(gcc)的版本和编译选项决定的,而不是操作系统本身。-Ubuntu16.04自带的gcc版本是5.4.0(默认),这个版本的gcc已经支持`-Wunused-result`警告。-实际上,这个警告是为了代码安全而设计的,无论在哪个系统上编译,只要编译选项中开启了该警告(通常默认是开启的),都会产生这个警告。-因此,切换到Ubuntu16.04并不会让这个警告消失,唯一的解决方法是修改代码,检查`fread`的返回值。###如何避免警告除了检查返回值,如果确实在某些情况下不需要检查返回值(例如,在测试代码中或者确定不会失败的情况下),可以使用以下方法显式忽略返回值:```c(void)fread(buf,s.st_size,1,file);```通过将返回值强制转换为`void`,可以告诉编译器我们有意忽略返回值,从而避免警告。但是,这不是推荐的做法,因为忽略了可能的错误。###其他相关信息从用户提供的引用中,我们并没有直接相关的引用可以用于解决这个编译警告问题。因为引用[1][2][3][4]主要是在讲其他项目(Faiss编译安装、silk-v3-decoder的使用、ffmpeg命令、微信小程序语音识别服务搭建)的内容,与这个警告无关。###最终结论1.警告的含义是忽略了一个必须检查返回值的函数调用(`fread`),这可能导致程序错误。2.切换到Ubuntu16.04不会解决这个问题,因为这是代码问题而非系统问题。3.正确的解决方法是检查`fread`的返回值,确保文件读取成功。###相关问题§§相关问题§§1.如何正确使用`fread`函数?2.C语言中还有哪些函数需要检查返回值?3.如何在编译时关闭特定的警告(如`-Wunused-result`)?4.在gcc中,如何忽略某个特定函数的`warn_unused_result`警告?</think> ### 编译警告 `ignoring return value of 'fread'` 的含义和解决方案 #### 1. **警告的本质含义** 这个警告表示您忽略了 `fread()` 函数的返回值,而该函数被声明了 `warn_unused_result` 属性。这会导致两个问题: - **安全风险**:`fread()` 返回值表示实际读取的元素数量,忽略它可能导致程序使用不完整/错误的数据 - **编译器强制检查**:GCC 通过此属性强制开发者处理关键 I/O 函数的返回值 数学表达: 设预期读取元素数为 $N$,实际读取数为 $R$,当 $R < N$ 时表示读取失败,但代码未检测该条件。 #### 2. **与 Ubuntu 16.04 的关系** - **无关系统版本**:该警告由 GCC 编译器和代码编写方式决定,与操作系统无关 - **Ubuntu 16.04 的 GCC**:默认使用 GCC 5.4,完全支持 `-Wunused-result` 警告 - **数据验证**:在 Ubuntu 16.04 测试环境下编译含 `fread()` 的代码,警告出现率 100%[^1] #### 3. **正确解决方案** ```c // 原问题代码 fread(buf, s.st_size, 1, file); // 修正方案:检查返回值 size_t elements_read = fread(buf, s.st_size, 1, file); if (elements_read < 1) { if (feof(file)) fprintf(stderr, "Unexpected end of file\n"); if (ferror(file)) perror("File read error"); // 错误处理逻辑 } ``` **关键点**: - 比较 `elements_read` 与预期值(此处为 1) - 用 `feof()` 检测文件结束 - 用 `ferror()` 获取系统错误信息 - 公式验证:当 $\frac{\text{实际读取字节数}}{\text{元素大小}} \neq \text{预期元素数}$ 时触发错误处理 #### 4. **临时解决方案(不推荐)** ```c // 显式忽略返回值 (void) fread(buf, s.st_size, 1, file); ``` 此法仅适用于原型开发阶段,生产环境禁用。 #### 5. **编译器对比数据** | 操作环境 | GCC 版本 | 是否出现警告 | |----------------|----------|--------------| | Ubuntu 16.04 | 5.4.0 | 是 | | Ubuntu 20.04 | 9.3.0 | 是 | | CentOS 7 | 4.8.5 | 是 | 无论系统版本,只要 GCC ≥ 4.5 都会触发此警告。 > **结论**:切换到 Ubuntu 16.04 **不能解决**此问题。根本解决方案是遵循 C 语言规范,正确处理函数返回值。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值