You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何SciPy的distance.cosine函数比手动Python实现更快?

为什么SciPy的余弦相似度计算比手动实现更快?

我用两段代码计算相同向量的余弦相似度,手动实现基本照搬了SciPy的内部逻辑,甚至移除了一些检查,本以为会更快,但实际测试下来SciPy的调用速度反而略快(约0.55ms vs 约0.69ms),想知道原因。

测试代码

import time
import math

import numpy as np
from scipy.spatial import distance

SIZE = 6400000
EXECUTIONS = 10000

path = "" # 向量文件路径
file_data = np.genfromtxt(path, delimiter=',')
A,B = np.moveaxis(file_data, 1, 0).astype('f')

start_time = time.time()
for _ in range(EXECUTIONS):    
    cos_sim = distance.cosine(A,B)

print("SciPy 耗时:%s ms" % (((time.time() - start_time) * 1000)/EXECUTIONS))
cos_sim_scipy = cos_sim

def cosine(u, v, w=None):
    uv = np.dot(u, v)
    uu = np.dot(u, u)
    vv = np.dot(v, v)
    dist = 1.0 - uv / math.sqrt(uu * vv)
    # 修正 rounding error
    return np.clip(dist, 0.0, 2.0)

start_time = time.time()
for _ in range(EXECUTIONS):
    cos_sim = cosine(A,B)

print("手动实现 耗时:%s ms" % (((time.time() - start_time) * 1000)/EXECUTIONS))
cos_sim_manual = cos_sim

print(np.isclose(cos_sim_scipy, cos_sim_manual))

补充:向量生成代码

def generate_random_vector(size):
    """生成两个指定大小的随机向量并保存到文件"""
    A = np.random.normal(loc=1.5, size=(size,))
    B = np.random.normal(loc=-1.5, scale=2.0, size=(size,))
    vectors = np.stack([A, B], axis=1)
    np.savetxt('vectors.csv', vectors, fmt='%f,%f')

generate_random_vector(640000)

测试环境

  • AMD Ryzen 9 3900X 12核处理器
  • 64GB RAM
  • Debian 12
  • Python 3.11.2
  • scipy 1.13.0
  • numpy 1.26.4

核心原因分析

  • SciPy是编译后的C级实现:你手动写的是Python函数,哪怕内部调用numpy的C实现,每次函数调用都要经过Python解释器的调度、参数检查等环节,累计10000次调用后,这些开销就会明显体现。而SciPy的distance.cosine是通过Cython编译成机器码的,直接和numpy的底层C API交互,几乎没有Python层面的额外开销。
  • 更高效的底层计算逻辑:你手动实现里用了math.sqrt(uu * vv),math.sqrt是Python标准库函数,调用开销比SciPy内部用的C级sqrt函数(或numpy的np.sqrt)更高。另外,SciPy计算向量范数时,可能直接调用了BLAS/LAPACK的优化接口(比如dnrm2),这类函数是专门为范数计算优化过的,能利用CPU的SIMD指令集加速,比两次np.dot再加开根号的组合效率更高。
  • 内存与类型的极致优化:SciPy内部会确保输入数据的内存布局是连续的(比如C顺序),同时对数据类型做严格匹配,避免numpy在计算时做隐式的类型转换或内存拷贝。你的手动实现虽然也转成了float32,但函数调用时的参数传递可能会有额外的检查或临时对象创建,累计下来影响了速度。

内容的提问来源于stack exchange,提问作者joseprupi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 20:43:10