【C++】Google benchmark理解与应用

news/2025/2/5 23:08:10/文章来源:https://www.cnblogs.com/o-O-oO/p/18700302

一、介绍

Google Benchmark 是一个用于 C++ 的微基准测试库。它旨在帮助开发者编写出更高效、更具表现力的基准测试代码。通过使用 Google Benchmark,可以方便地测量函数或代码片段的性能,并且能够生成详细的报告。

二、安装与配置

2.1 安装

在Ubuntu环境中安装Google Benchmark库可以通过多种方式进行,包括使用包管理器直接安装预编译的版本或者从源代码自行编译。
以下是两种常见的方法:

方法一:通过Ubuntu的包管理器安装(推荐)

对于较新的Ubuntu版本,Google Benchmark可能已经包含在官方仓库中,你可以通过apt命令直接安装。

安装Google Benchmark:

使用下面的命令来安装Google Benchmark及其开发文件。

sudo apt update
sudo apt install google-benchmark

如果你需要CMake配置文件和头文件,还可以安装 libbenchmark-dev 包:

sudo apt install libbenchmark-dev

验证安装:安装完成后,你可以通过以下命令检查是否正确安装了Google Benchmark:

dpkg -l | grep benchmark

这种方法的优点是简单快捷,并且通常会自动处理依赖关系。

方法二:从源代码编译安装

如果你需要最新的功能或修复,可以从GitHub上获取源代码并自行编译。

安装依赖项:

首先,确保你已经安装了必要的构建工具和依赖项。你可以使用以下命令来安装这些工具:

sudo apt install cmake git build-essential

克隆Google Benchmark仓库:

使用Git将Google Benchmark的仓库克隆到本地机器上。

git clone https://github.com/google/benchmark.git
cd benchmark

创建构建目录并编译:

创建一个用于构建的子目录,并进入该目录进行编译。

mkdir build && cd build
cmake ..
make -j$(nproc)  # 使用所有可用的核心加速编译过程

安装Google Benchmark:编译成功后,你可以选择安装它到系统路径下。

sudo make install

验证安装:同样地,可以使用

dpkg -l | grep benchmark 

或者尝试编写一个小的C++程序来测试安装是否成功。

这种方法允许你获得最新版本的Google Benchmark,并且可以自定义编译选项。但是,它也要求你手动解决任何可能出现的依赖问题。

【使用 CMake】:

在 CMake 项目中,可以通过以下方式引入 Google Benchmark:

find_package(benchmark REQUIRED)
add_executable(my_benchmark main.cpp)
target_link_libraries(my_benchmark benchmark::benchmark)

2.2 配置

确保你的编译器支持 C++11 或更高版本,并且在 CMake 中设置相应的标准:

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

三、基本用法

3.1 创建基准测试

创建一个基准测试非常简单。你需要定义一个函数,并使用 BENCHMARK 宏来注册该函数。例如:

#include <benchmark/benchmark.h>static void BM_StringCreation(benchmark::State& state) {for (auto _ : state) {std::string empty_string;benchmark::DoNotOptimize(empty_string);}
}
BENCHMARK(BM_StringCreation);BENCHMARK_MAIN();

3.2 运行基准测试

编译并运行你的基准测试程序。你可以通过命令行参数来控制基准测试的行为。例如:

g++ -std=c++11 -I/usr/include -L/usr/lib/x86_64-linux-gnu -o benchmark_test benchmark_test.cpp -lbenchmark -pthread./benchmark_test --benchmark_filter=BM_StringCreation

这段benchmark测试的结果数据提供了关于BM_StringCreation基准测试的详细信息,包括运行环境、CPU特性、负载平均值以及具体的性能测量结果。以下是对这些数据的解释:

【测试环境】:

日期和时间:2025-01-14 18:51:03
执行命令:./benchmark_test
CPU配置:
核心数:16个逻辑处理器
频率:5000 MHz(即5GHz)
缓存层次结构:
L1数据缓存:32KB,共有8个(可能每个物理核心两个)
L1指令缓存:32KB,共有8个(同样,可能每个物理核心两个)
L2统一缓存:256KB,共有8个(每个物理核心一个)
L3统一缓存:16384KB(16MB),共享给所有核心
系统负载:在测试开始时,系统的1分钟、5分钟和15分钟平均负载分别为0.07, 0.23, 0.18,这表明系统几乎空闲。

【性能测量结果】:

Benchmark名称:BM_StringCreation

Time (实际时间):3.27 ns(纳秒),这是每次调用BM_StringCreation函数的实际耗时。

CPU (CPU时间):3.27 ns,与实际时间相同,说明几乎没有上下文切换或其他非CPU相关的延迟。

Iterations (迭代次数):210,470,863 次,这是Google Benchmark框架自动确定的最佳迭代次数,以提供足够数量的数据点来计算统计平均值并减少随机误差的影响。

【进一步解读】:

从这些数据中我们可以得出几个结论:

快速操作:创建一个空的std::string对象是非常快的操作,平均只需要3.27纳秒。这是因为这个操作非常轻量级,主要涉及分配少量内存(如果有的话)和初始化对象状态。

高精度计时器:能够测量到纳秒级别的精度,说明测试环境使用了高分辨率的时间计数器。

高效的CPU利用率:实际时间和CPU时间相等,意味着几乎没有等待I/O或者其他资源的情况发生,整个过程都在CPU上高效完成。

大量的迭代:高达2亿多次的迭代次数进一步验证了这是一个非常快速的操作,同时也保证了结果的可靠性。

总的来说,这段benchmark测试显示BM_StringCreation是一个极其高效的函数,它几乎不会成为性能瓶颈。如果你的目标是评估更复杂或者更耗时的操作,这样的快速操作可以作为参考基线,帮助你理解其他部分相对于这一基础操作的表现如何。对于如此快速的操作,即使是很小的变化也可能显著影响结果,因此在优化这类代码时需要特别小心,确保你的修改确实带来了实质性的改进。

四、高级功能

4.1 参数化基准测试

有时候你可能需要对不同的输入进行基准测试。Google Benchmark 提供了参数化基准测试的功能。
例如:

static void BM_StringCopy(benchmark::State& state) {std::string x = "hello";for (auto _ : state) {std::string copy(x);benchmark::DoNotOptimize(copy);}
}
BENCHMARK(BM_StringCopy)->Arg(5)->Arg(10)->Arg(20);BENCHMARK_MAIN();

4.2 自定义计时器

Google Benchmark 允许你自定义计时器,以适应不同的需求。
例如:

class MyTimer : public benchmark::Timer {
public:MyTimer() : start_(std::chrono::high_resolution_clock::now()) {}double ElapsedTime() const override {return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::high_resolution_clock::now() - start_).count() /1e9;}private:std::chrono::time_point<std::chrono::high_resolution_clock> start_;
};BENCHMARK_RELATIVE(MyCustomBenchmark, n) {MyTimer timer;while (n--) {// Your code here}return timer.ElapsedTime();
}
BENCHMARK_REGISTER_F(MyFixture, MyCustomBenchmark)->Range(1, 10000);

4.3 固定迭代次数

有时候你可能希望固定迭代次数,而不是让 Google Benchmark 自动选择。可以使用 函数来实现:

BENCHMARK(BM_StringCreation)->Iterations(1000);

五、结果分析

Google Benchmark 会生成详细的报告,包括每个基准测试的平均时间、方差等统计信息。你可以通过命令行参数来控制输出格式和详细程度。例如:

./my_benchmark --benchmark_format=json

总结

Google Benchmark 是一个强大且灵活的基准测试工具,可以帮助你更好地理解和优化代码性能。通过本文档的学习,你应该已经掌握了如何安装、配置和使用 Google Benchmark。希望你在实际项目中能够充分利用这个工具,提升代码的性能。
素材来源官方媒体/网络新闻

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/879313.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LRU浅析

LRU算法LRU是Least Recently Used的缩写,即最近最少使用,是一种常用的页面置换算法,选择最近最久未使用的页面予以淘汰。该算法赋予每个页面一个访问字段,用来记录一个页面自上次被访问以来所经历的时间 t,当须淘汰一个页面时,选择现有页面中其 t 值最大的,即最近最少使…

20250205 省选模拟赛 T3

20250205 省选模拟赛 T3 Description 设计一个 \(n\times n\) 的 01 矩阵,使得从 \((1,1)\) 走到 \((n,n)\) 且只能向右或下走且只经过为 \(1\) 的格子的方案数为 \(X\)。 \(n \leq 24\) 时得满分。\(X \leq 10^9\)。 Solution 基于 \(2\) 进制的构造方法我们称从左上到右下的…

Automa:自动化浏览器工作流

🏷️仓库名称:AutomaApp/automa 🌟截止发稿星数: 14340 (今日新增:33) 🇨🇳仓库语言: Vue 🤝仓库开源协议:Other 🔗仓库地址:https://github.com/AutomaApp/automa引言 Automa是一个浏览器扩展,允许用户通过连接模块来自动化浏览器任务。它消除了重复性任务的需…

本地部署DeepSeek教程

本地部署DeepSeek教程 步骤 本地部署DeepSeek教程步骤 1 安装Ollama 2 下载DeepSeek模型 3 可视化图文交互界面Chatbox(可选)1 安装Ollama 访问Ollama官网下载Ollama,默认安装即可。安装完成后打开终端(我这里是windows系统),输入: ollama help即可查看ollama选项,且可…

OpenLDAP篇-安装OpenLDAP服务01

1、OpenLDAP统⼀⽤户认证系统 1.1 为什么需要OpenLDAP 在没有OpenLDAP统⼀⽤户认证系统的环境中,往往会⾯临如下问题:1、当⽤户需要访问多台服务器时,管理员需要在每台服务器上⼿动创建账户。如果员⼯离职,还需逐台删除账户,整体操作繁琐且容易出现遗漏的情况,因此存在较…

集训3 20240127

集训3 20240127 牛客竞赛_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ A: 题目大意:给定 \(n\) ,两个人轮流可以使 \(n\) 减去一个任意小于它且与它互质的数,求最后甲能否取胜 #include<bits/stdc++.h>using namespace std;int main() {long long n;cin&g…

RocketMQ实战—4.消息零丢失的方案

大纲 1.全链路分析为什么用户支付完成后却没有收到红包 2.RocketMQ的事务消息机制实现发送消息零丢失 3.RocketMQ事务消息机制的底层实现原理 4.是否可以通过同步重试方案来代替事务消息方案来实现发送消息零丢失 5.使用RocketMQ事务消息的代码案例细节 6.同步刷盘+Raft协议同步…

qoj7301 AGC036D 题解

qoj7301 orz yxx 有一个很牛的状态设计 \(f_{i,j,0/1}\),\(0\) 为 \(a_{i-1}>a_i\),\(j\) 记录 \(a_{i-1}\) 的值,\(a_i\) 的值未定;\(1\) 为 \(a_{i-1}<a_i\),\(j\) 记录 \(a_i\) 的值 这样可以完美解决 \(a_{i-1}>a_i<a_{i+1}\) 的问题 转移和优化都是简单的…

【PyTorch】对比Torch和Numpy

该部分主要通过对比Torch和Numpy基础知识,方便大家了解PyTorch。Numpy是处理数据的模块,处理各种矩阵的形式来多核加速运算。 Torch自称为神经网络界的Numpy,因为它能将torch产生的tensor(张量)放在 GPU 中加速运算(前提是你有合适的 GPU),就像Numpy会把array放在CPU中…

十. Redis 事务和 “锁机制”—— 并发秒杀处理的详细说明

十. Redis 事务和 “锁机制”——> 并发秒杀处理的详细说明 @目录十. Redis 事务和 “锁机制”——> 并发秒杀处理的详细说明1. Redis 的事务是什么?2. Redis 事务三特性3. Redis 关于事务相关指令 Multi、Exec、discard和 “watch & unwatch”3.1 快速入门(演示…

使用Tauri框架打造的FPS透视

使用Tauri框架打造的FPS透视,使用javascript读内存绘制透视框使用Vue前端和Rust后端打造FPS透视 前端使用P5js进行canvas绘制 后端封装内存读取工具,前端快速编写代码无需重启调试 Vue前端与后端通讯获取内存数据并在前端渲染 作者声明 [仅供学习 请勿非法用途 从事非法用途出…