向量数据库FAISS之七:GPU上的FAISS

Faiss on the GPU

1.CPU/GPU 互操作

GPU Index 能够容纳宿主和设备的指针作为输入给 add()search()

如果 add()search() 的输入已经与 索引 位于同一 GPU 上,则不会执行任何副本,并且执行速度最快

否则,将执行 CPU -> GPU 复制(或跨设备,如果输入驻留在与索引不同的 GPU 上),完成后会复制回所有结果(例如,对于 search())。

1.转换

启用 从/到GPU 的转换:

index_gpu_to_cpu,

index_cpu_to_gpu,

index_cpu_to_gpu_multiple

传输到 GPU 的两个函数使用一个可选的 GpuClonerOptions 对象,该对象可用于调整 GPU 存储对象的方式。默认值适用于内存不受限制的情况。当内存不足时,可以调整这些字段。

2.Python 中的转换

在 Python 中,index_gpu_to_cpuindex_cpu_to_gpuindex_cpu_to_gpu_multiple可用。

  • index_cpu_to_all_gpus:将 CPU 索引克隆到所有可用 GPU 或 ngpu=3 指定的多个 GPU

  • index_cpu_gpu_list:同样,但另外还需要一个可以用 gpus=[2, 4, 6] 指定的 gpu id 列表

  • index_cpu_to_gpu_multiple_py:实例化多个 GPU 索引时,最好分解 GPU 资源以避免浪费内存。该函数采用可以在索引之间重用的资源对象列表作为其第一个参数,

    ngpu = 4
    resources = [faiss.StandardGpuResources() for i in range(ngpu)]
    index1_gpu = faiss.index_cpu_to_gpu_multiple_py(resources, index1)
    index2_gpu = faiss.index_cpu_to_gpu_multiple_py(resources, index2)
    

2.实施的索引

索引类型 IndexFlatIndexIVFFlatIndexIVFScalarQuantizerIndexIVFPQ 在 GPU 上实现为 GpuIndexFlatGpuIndexIVFFlatGpuIndexIVFScalarQuantizerGpuIndexIVFPQ

除了普通参数之外,它们还接受资源对象作为输入,以及索引存储配置选项和 float16/float32 配置参数。

1.限制

  • 对于所有索引,k 和 nprobe  <= 2048
  • 对于 GpuIndexIVFPQ,允许的每个编码向量的代码大小为 1、2、3、4、8、12、16、20、24、28、32、48、56、64 和 96 字节。
  • 内存通常是 GPU 上较稀缺的资源,因此使用 GPU 索引时需要注意一些事项
    • 由于共享内存限制,每个代码 56 字节或更多的 GpuIndexIVFPQ 需要使用 float16 IVFPQ 模式(例如,48 x 2^8 x sizeof(float) 为 49152 字节);
    • GpuIndexIVFPQ 的预计算表可能会占用大量内存。如果您看到 cudaMalloc 错误,请禁用预计算表
    • 与倒排文件条目对应的索引可以存储在CPU上而不是GPU上,使用indices_options = INDICES_CPU
    • 当内存非常紧张时,倒排列表的几何重新分配可能会溢出内存。为了避免这种情况(通常是为了提高添加速度),如果您知道索引有多大,请在 GpuIndexIVFPQGpuIndexIVFFlat 上调用reserveVecs
    • StandardGpuResources 对象默认保留 512 MiB(<= 4 GiB GPU)、1024 MiB(<= 8 GiB GPU)或最大 1536 MiB(所有其他 GPU)的 GPU 内存用于临时计算空间。如果太多,可以减小大小,但可能会降低速度。
    • 添加或搜索大量向量应分批完成。典型的批量大小是 8192 左右的 2 的幂。
  • 当使用index_cpu_to_gpu从 CPU 索引转换时,默认的 GpuCloneOptions 对象被调整为以内存使用为代价最大化速度。

3. GPU vs CPU 比较

GPU 通常比 CPU 实现有显著的加速,但有两个问题需要记住:

1.CPU <-> GPU 副本的开销

  • 通常,CPU 通过总线连接到 GPU,该总线的带宽低于 CPU 连接到其主内存的带宽,尤其是 CPU 连接到其自己的缓存的带宽;
    • 例如,PCIe3 的最大速度约为 12 GB/秒,而服务器级 CPU 通常具有 50+ GB/秒。
  • 将填充的索引从 CPU 复制到 GPU 可能需要花费大量时间。只有当您在 GPU 上执行合理数量的查询时,您才会分摊此开销
    • 最好将索引复制到 GPU 并将其保留在那里,或者在 GPU 上创建索引并将其填充在那里。

2.批量大小和索引大小

GPU 通常比 CPU 具有更高的延迟,但和 CPU 相比具有更高的并行吞吐量和内存带宽。

如果可能的话,最好使用 CPU 或 GPU 进行批量查询,因为这可以在所有查询中分摊索引内存的接触。

Index size 应该相对较大才能看到 GPU 获胜。只有几千个向量的索引通常在 CPU 上总是更快(因为它可以容纳 CPU 的缓存),但数十万到数百万/数十亿个向量将非常适合分摊 GPU 的开销。

总结

  • 小查询批量、小索引:CPU 通常更快
  • 小查询批量,大索引:GPU 通常更快
  • 大查询批量,小索引:两种方式都可以
  • 大查询批量、大索引:GPU 通常更快
### Faiss 向量数据库使用指南 #### 安装依赖库 为了能够顺利运行 Faiss 的功能,需要安装相应的 Python 库。可以通过 pip 工具来完成这一操作。 ```bash pip install faiss-cpu # 如果不需要 GPU 加速的话 # 或者对于支持 CUDA 的环境可以选择下面这条命令 pip install faiss-gpu ``` #### 导入必要的模块并初始化索引结构 创建一个简单的向量空间模型,并定义好要使用的距离度量方式以及维度大小。 ```python import numpy as np import faiss d = 64 # 维度数量 nb = 1000 # 数据集中的向量数目 nq = 10 # 查询次数 np.random.seed(1234) # 设置随机种子以便于重现实验结果 xb = np.random.random((nb, d)).astype('float32') # 构建测试数据集 xq = np.random.random((nq, d)).astype('float32') # 构建查询向量集合 index = faiss.IndexFlatL2(d) # 创建 L2 距离计算的平面索引实例 print(index.is_trained) # 输出是否已经过训练的状态信息 index.add(xb) # 将批量的数据加入到索引中去 print(index.ntotal) # 打印当前已存入多少条记录 ``` #### 进行相似性搜索 利用之前建立好的索引来进行 k-nearest neighbors (KNN) 查找任务,找到最接近给定查询点的一些邻居节点。 ```python k = 4 # 假设我们想要找出前四个最近邻 D, I = index.search(xq, k) # 实际执行 KNN 搜索过程;D 表示距离数组而 I 则是指针列表 print(I[:5]) # 显示部分检索出来的 ID 号码 print(D[:5]) # 展现对应的距离数值 ``` #### 高级特性 - 使用量化技术优化性能 当处理大规模数据集时,可以考虑采用 PQ(Product Quantization)等压缩策略以减少内存占用和加速运算速度。 ```python m = 8 # 子空间的数量 nbits = 8 # 每个子空间内编码位数 pq_index = faiss.IndexPQ(d, m, nbits) pq_index.train(xb) # 训练产品量化器 pq_index.add(xb) # 添加原始数据至新构建的索引里头 D_pq, I_pq = pq_index.search(xq, k) # 再次做一次近似 NN 检索 print(f"PQ Index Search Results:\nIDs={I_pq}\nDistances={D_pq}") ``` 通过上述代码片段展示了如何基于 Faiss 来搭建基本框架并对其中涉及的关键概念进行了简单说明[^1]。此外还介绍了更进一步的功能比如引入了 Product Quantization 技术用于提升效率[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值