跳到主要内容

GPU与CPU对比

GPU 与 CPU 的性能对比

GPU(图形处理器)通常在速度上比 CPU(中央处理器)有明显提升,但在实际应用中需要注意以下两点:

CPU 与 GPU 之间的数据拷贝带来的开销

通常,CPU 与 GPU 之间通过带宽较低的总线(如 PCIe3)连接,其带宽远低于 CPU 与主内存、甚至是 CPU 本地缓存的带宽。例如,PCIe3 最大带宽约为 12 GB/秒,而服务器级 CPU 的总内存带宽常常超过 50 GB/秒。

将已填充的索引(index)从 CPU 拷贝到 GPU,可能需要较长时间。只有当你在 GPU 上执行足够多的查询(query)时,这种数据传输的开销才值得;建议只进行一次索引拷贝到 GPU,并持续在 GPU 上使用,或者直接在 GPU 上创建并填充索引。

另外,如果大量查询向量(query vectors)储存在 CPU,需要将其传输到 GPU 上,也会有延迟。这个问题主要发生在索引比较小的情况下(例如,索引可以放进 CPU 的末级缓存,通常只有几兆字节)。

批处理规模与索引大小

GPU 的延迟通常高于 CPU,但并行处理能力和内存带宽更强。无论在 CPU 还是 GPU 上执行查询,建议采用批处理(batch queries)方式,这样可以更好地分摊访问索引内存的开销,提高整体效率。

只有当索引规模足够大时,GPU 优势才会明显。如果索引只有几千个向量,通常 CPU 速度会更快(因为能够全部放进 CPU 缓存);但当向量数量达到几十万、几百万或更多时,GPU 就可以充分展现出它的巨大优势。

提示

小结:

  • 批量小、索引小:CPU 通常更快
  • 批量小、索引大:GPU 通常更快
  • 批量大、索引小:两者视具体情况而定
  • 批量大、索引大:GPU 优势更明显

GPU 支持来自主机 CPU 或 GPU 内存的查询数据。如果查询数据已经在 GPU 上,直接用 GPU 查询会更高效。因此,除了极端情况(如超小索引和很少的并行任务)外,GPU 大多数场景都有更出色的表现。

GPU 与 CPU 的精度对比

GPU 索引和 CPU 索引实现的是相同的算法,但结果可能并不完全一致,需要注意以下三点:

浮点数运算顺序导致的差异

浮点运算(floating point arithmetic)一般是不满足结合律的。GPU 代码和 CPU 代码的计算顺序可能不同,因此最终返回的距离(distance)结果或候选项的排序也可能不同。即使是最基础的情况,例如 CPU 的 IndexFlatIP 和 GPU 的 GpuIndexFlatIP,也会因为矩阵乘法内核(kernel)在浮点数归约(reduction)上的不同导致结果差异。

相等元素的选取顺序

GPU 对于结果扫描和 K-选取(即k-selection)的顺序不保证与 CPU 完全一致。如果存在多个相等的向量(即不同的向量或者距离完全一样),那么这些元素的相对顺序就没有保证,这类似于排序算法中的不稳定性

举例来说,如果一个索引中有 1000 个完全一样的向量但用户 ID 不同,在最小-k(L2)或最大-k(IP)搜索时,GPU 和 CPU 返回的 ID 可能不同。

float16 精度(半精度浮点)选用

如果在 GPU 上使用 float16(半精度浮点数)算法,例如 GpuIndexFlat,则距离计算的结果也会与 float32 或 double 类型不同。

备注

为了评估 CPU 和 GPU 的结果接近程度,建议采用 Recall@N(召回率)这种指标进行对比。对于 ID 一致的结果,计算出的距离只需在一个合理的误差范围(如 1 到 500 个单位的最后有效位 ULP, Unit in the Last Place)以内即可。