当前位置: 首页 > article >正文

【Lucene】单个cpu 每秒能支持多少个bm25公式的计算

BM25(Best Matching 25)是一个常用于信息检索中的排名函数,它基于词频(TF)和逆文档频率(IDF)计算文档与查询之间的相关性。对于单个CPU能够每秒支持多少次BM25计算,影响因素有很多,比如CPU的性能(如时钟频率、核心数)、BM25公式的计算复杂度、数据大小、查询和文档的长度等。

一般来说,BM25的计算复杂度主要依赖于以下几个因素:

  1. 查询的长度(包含的词数)
  2. 文档的长度(包含的词数)
  3. 反向索引的查找速度,即是否需要查找每个查询词在文档集合中的频率(或逆文档频率)
  4. 硬件配置,尤其是CPU的性能

如果假设每个查询只包含一个关键词,文档的长度适中,并且系统已经建立了优化的索引,单个BM25计算的时间一般来说在几十微秒到几毫秒之间。在这种情况下,单核CPU每秒可以支持的BM25计算次数大约在10,000到100,000次之间,具体取决于硬件和实现的优化程度。

如果文档和查询更复杂,或者你需要处理大量数据、长查询等,BM25的计算时间可能会增加,这会影响每秒的计算次数。为了提高性能,通常会使用并行计算(多核CPU、分布式计算等)和优化算法(如倒排索引、缓存、批处理等)。

要进行BM25公式的压测,可以通过一个简单的demo来评估每秒能支持多少次计算。假设我们已经有了一个包含多个文档的倒排索引,并且你需要通过查询来计算每个文档的BM25得分。以下是一个基于Python的压测demo,使用time库来衡量性能。

1. 准备BM25计算代码

import math
import time
import random
from collections import Counter

# 示例倒排索引(文档ID -> 词频映射)
index = {
    1: {'apple': 3, 'banana': 2, 'orange': 1},
    2: {'apple': 1, 'banana': 3, 'grape': 2},
    3: {'orange': 2, 'grape': 3, 'banana': 1},
}

# IDF计算:假设文档总数为3,计算每个词的IDF
def compute_idf(index, total_docs):
    idf = {}
    # 计算每个词出现在多少个文档中
    doc_freq = Counter()
    for doc_id, doc in index.items():
        for word in doc:
            doc_freq[word] += 1
    
    # 计算IDF值
    for word, freq in doc_freq.items():
        idf[word] = math.log((total_docs - freq + 0.5) / (freq + 0.5) + 1.0)
    
    return idf

# BM25计算公式
def bm25_score(query, doc, idf, k1=1.5, b=0.75):
    score = 0.0
    doc_length = sum(doc.values())
    avg_doc_length = sum(sum(doc.values()) for doc in index.values()) / len(index)

    for term in query:
        if term in doc:
            tf = doc[term]
            idf_score = idf.get(term, 0)
            score += idf_score * (tf * (k1 + 1)) / (tf + k1 * (1 - b + b * doc_length / avg_doc_length))
    
    return score

# 示例查询
query = ['apple', 'banana']

# 总文档数量
total_docs = len(index)

# 计算IDF
idf = compute_idf(index, total_docs)

# 压测BM25
def benchmark_bm25(index, query, idf, iterations=10000):
    start_time = time.time()
    
    for _ in range(iterations):
        random_doc_id = random.choice(list(index.keys()))
        doc = index[random_doc_id]
        bm25_score(query, doc, idf)
    
    end_time = time.time()
    duration = end_time - start_time
    return duration

# 测试
iterations = 10000  # 压测次数
duration = benchmark_bm25(index, query, idf, iterations)
print(f"Processed {iterations} queries in {duration:.2f} seconds.")
print(f"BM25 queries per second: {iterations / duration:.2f}")

2. 解释

  • 倒排索引 (index):这是一个简单的字典,其中键是文档ID,值是一个字典,表示文档中每个词的词频。
  • IDF计算 (compute_idf):通过倒排索引计算每个词的逆文档频率(IDF)。这里使用的是标准的IDF公式:
    IDF ( w ) = log ⁡ ( N − df ( w ) + 0.5 df ( w ) + 0.5 + 1.0 ) \text{IDF}(w) = \log \left( \frac{N - \text{df}(w) + 0.5}{\text{df}(w) + 0.5} + 1.0 \right) IDF(w)=log(df(w)+0.5Ndf(w)+0.5+1.0)
    其中,N是文档总数,df(w)是包含词w的文档数量。
  • BM25得分计算 (bm25_score):根据BM25公式计算查询和文档的相关性得分。参数k1b是BM25的超参数。
  • 压测函数 (benchmark_bm25):通过随机选择文档,针对给定的查询计算BM25得分,并通过time.time()来测量计算所需的时间。

3. 输出

程序会输出如下结果:

  • 处理指定次数的BM25查询的总时间。
  • 每秒处理的BM25查询次数。

例如:

Processed 10000 queries in 0.65 seconds.
BM25 queries per second: 15384.62

4. 改进与优化

  • 并行计算:如果需要更高的吞吐量,可以考虑在多核CPU上并行处理查询,或者使用GPU加速。
  • 数据集优化:对于大规模数据集,可以利用更高效的倒排索引结构(如Lucene、Elasticsearch等)来加速查询。

通过上述方法,你可以大致了解单个CPU在特定硬件和查询场景下的BM25计算性能。


http://www.kler.cn/a/417529.html

相关文章:

  • [创业之路-286]:《产品开发管理-方法.流程.工具 》-1- IPD两个跨职能团队的组织
  • GitHub 使用教程:从入门到进阶
  • 【算法篇】贪心算法
  • PostgreSQL:字符串函数用法
  • ES面试题
  • 1-ET框架开发环境与demo运行
  • Apache Flink从Kafka中消费商品数据,并进行商品分类的数量统计题
  • 【测试工具JMeter篇】JMeter性能测试入门级教程(四):JMeter中BeanShell内置方法使用
  • 拓扑排序(C++实现)
  • ffmpeg安装(windows)
  • updatexml报错注入原理分析
  • kylinos-server源码安装xrdp
  • 丹摩征文活动 | SD3+ComfyUI的图像部署实践 AIGC图像
  • 基于Java Springboot蛋糕订购小程序
  • 【大模型实战篇】基于大模型GLM的检索增强实践
  • dpcas - v1 (Deep Learning Componentized Application System):深度学习组件化应用系统
  • VBA代码解决方案第二十讲:EXCEL工作表的添加与删除
  • PID模糊控制算法(附MATLAB仿真程序)
  • 【Java】设计模式——策略模式
  • PVE中的VLAN问题
  • 多线程(3)线程中的常用结构
  • 如何实现字符串反转-多语言
  • CSS笔记(二)类名复用
  • SpringBoot开发——结合Nginx实现负载均衡
  • mac下安装Ollama + Open WebUI + Llama3.1
  • [高等数学]一元积分学的应用