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

为何std::lower_bound性能优于std::ranges::lower_bound?何时后者更优?

std::lower_bound与std::ranges::lower_bound的性能差异及适用场景

一、为什么std::lower_bound性能优于std::ranges::lower_bound?

在你的基准测试中,std::lower_bound(算法库版本)比std::ranges::lower_bound表现更优,核心原因在于标准库实现的优化差异:

  • 旧版算法的特殊化适配:部分主流标准库(如GCC/libstdc++)对std::lower_bound做了特殊处理——当传入关联容器(如std::set)的迭代器时,会直接调用容器自带的lower_bound成员函数(利用红黑树结构实现O(log n)复杂度查找),而非执行通用的双向迭代器线性遍历逻辑。
  • Ranges版本的抽象开销:std::ranges::lower_bound为了适配范围概念的通用抽象,需要处理更多模板参数和范围适配逻辑,部分实现中暂时没有针对关联容器做同样的委托优化;额外的抽象层也可能导致编译器优化效果略逊于旧版算法,最终性能落后。

从测试结果来看,std::set::lower_bound性能最优(直接利用容器内部结构),其次是旧版std::lower_bound(借助特殊化调用成员函数),而std::ranges::lower_bound因缺少该优化,可能退化为低效的线性遍历,导致性能差距。

二、std::ranges系列算法何时能超过数据结构自带算法?

std::ranges算法并非总是落后,在以下场景中,其性能可能反超数据结构自带的算法:

  • 随机访问迭代器场景:对于std::vector这类提供随机访问迭代器的容器,std::ranges::lower_bound和旧版算法一样执行O(log n)二分查找,且由于Ranges的现代设计,部分实现可能在编译优化上更高效,性能持平甚至略优。
  • 视图(View)结合场景:当需要对过滤、转换后的子范围操作时,std::ranges算法可直接在视图上工作,无需构造临时容器。例如用std::views::filter筛选元素后,直接调用std::ranges::lower_bound,避免了拷贝数据的开销;而数据结构自带算法只能操作原始容器,无法直接处理视图。
  • 自定义范围类型场景:若使用满足Ranges概念的自定义范围类型,且其迭代器支持随机访问,std::ranges::lower_bound可直接利用特性执行高效查找;而数据结构自带算法通常只针对自身容器优化,无法适配自定义范围。
  • 流水线操作场景:Ranges算法支持链式调用,配合视图可构建高效的数据处理流水线,减少中间临时对象的创建,整体性能优于多次调用数据结构自带算法+手动处理中间结果的方式。

测试代码

#include <set>
#include <ranges>
#include <algorithm>

std::set<int> my_set;

static void RangeLowerBound(benchmark::State& state) {
  for (auto i = 0; i <= 1'000'000; ++i) {
    my_set.insert(i);  
  }
  auto search{900'000};
  for (auto _ : state) {
    auto it = std::ranges::lower_bound(my_set, search);
    benchmark::DoNotOptimize(it);
  }
}
BENCHMARK(RangeLowerBound);

static void StdLowerBound(benchmark::State& state) {
  for (auto i = 0; i <= 1'000'000; ++i) {
    my_set.insert(i);  
  }
  auto search{900'000};
  for (auto _ : state) {
    auto it = std::lower_bound(my_set.begin(), my_set.end(), search);
    benchmark::DoNotOptimize(it);
  }
}
BENCHMARK(StdLowerBound);

static void SetLowerBound(benchmark::State& state) {
  for (auto i = 0; i <= 1'000'000; ++i) {
    my_set.insert(i);  
  }
  auto search{900'000};
  for (auto _ : state) {
    auto it = my_set.lower_bound(search);
    benchmark::DoNotOptimize(it);
  }
}
BENCHMARK(SetLowerBound);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 13:35:33