如何在C/C++中测量一个函数或者功能的运行时间(串行和并行,以及三种方法的实际情况对比)

news2024/11/14 23:44:40

本文算是一个比较完整的关于在 C/C++ 中测量一个函数或者功能的总结,最后会演示三种方法的对比。

最常用的clock()

最常用的测量方法是使用clock()来记录两个 CPU 时间点clock_t,然后做差。这个方法的好处在于非常简单易写,如下(第一行是为说明需要导入哪个库):

#include <time.h>
.....

	clock_t begin = clock();

    ...需要被测量的代码
    
    clock_t end = clock();
    int duration = (end - begin)/CLOCKS_PER_SEC;

需要注意 3 点:

  1. CLOCKS_PER_SEC在 macOS 上是 1000000,也就是说(end - begin)的单位是微秒,所以要除以CLOCKS_PER_SEC
  2. 不同平台的clock_t类型是不一样的,有些平台是整数型,有些是使用浮点型。如果是浮点型的话,CLOCKS_PER_SEC或许可以不用写,还是要看time.h的相关内容。
  3. 这个方法中的“clock”一词表示的是时钟频率,而不是时间。早期的计算机是固定频率的(现在的一些计算器或者单片机其实也是固定频率的),这个方法就是诞生于那个时间的。

这种方法最大的弊端就是它测量是 CPU 运行时间,准确的说是该进程使用 CPU 的时间。这就导致了对于非 CPU 密集型程序来说,这个结果可能不是那么精确。当然导致的最大的问题是并行计算程序得到的时间完全不对,而且不能简单地使用核心数计算得到正确的时间。

因为这个方法是将多个 CPU 的运行时间加在一起了,串行计算的程序完全没有问题,但是并行计算的话,CPU 使用率一般不会达到或接近核心数*100%,因为计算机上还有其他任务也需要 CPU。比如说如果串行计算的程序使用率一般在 99% 左右,获取时间为 30 秒,但是对于 6 核的设备上运行的并行计算程序的话,CPU 使用率达到 570% 就很不错了,获取的时间可能为 27 秒,而实际上只用了 5 秒。

这是我在使用 ISPC 编写并行计算程序的时候发现的,所以我想寻找到新的方案,于是我发现了下一个方法。

timespec

timespec是一个简单的日历时间或者时间流逝。通过使用日历时间可以解决上一节中无法测量并行程序的实际运行时间的问题。但是“简单”这点的表现为整数时间,也就是说最小的时间精度是秒,而不是上一种方法中的微秒,不过这对于复杂函数或程序的测试来说没啥问题,毕竟 30 分钟和 31 分钟的性能差距不过 3.22%。

方法如下(第一行是为说明需要导入哪个库):

#include <time.h>
	time_t begin = time(NULL);
	
	...需要被测量的代码
    
    time_t end = time(NULL);
    int duration = (end - begin);

可以看到比上一种还要简单。

但是对于一些小型的测试来说,这个方法又不太行,因为整数带来的误差太大了,比如说 0.6 秒是 1.8 秒性能的三倍,但是在整数上只为 2 倍甚至是 1 倍(为什么有这个“甚至”等会演示可以看到),所以还是需要一个更精确时间测量方法,这个方法不光要适应并行计算,还要有一定的精度。

clock_gettime()

clock_gettime()可以完美的符合要求,但是使用上有点复杂。

clock_gettime()是我从文档的下面发现的。一开始我找到的是gettimeofday(),然后我去看了一下 IEEE 标准的文档 https://pubs.opengroup.org/onlinepubs/9699919799/functions/gettimeofday.html,发现在“FUTURE DIRECTIONS(未来方向)”这一栏表示gettimeofday()可能未来会被废弃;在“APPLICATION USAGE(应用使用)”这一栏表示应用应该使用clock_gettime()而不是gettimeofday。这必须得使用clock_gettime()了。

请添加图片描述

clock_gettime()的复杂之处在于太精确了。先来看看使用方法(第一行是为说明需要导入哪个库):

#include <time.h>
	struct timespec start;
    clock_gettime(CLOCK_REALTIME, &start);
	
	...需要被测量的代码
    
    struct timespec end;
    clock_gettime(CLOCK_REALTIME, &end);
    
	double duration = (double)(end.tv_nsec-start.tv_nsec)/((double) 1e9) + (double)(end.tv_sec-start.tv_sec);

clock_gettime()的参数CLOCK_REALTIME表示系统层面的实时时间;这个地方还可以用CLOCK_MONOTONIC,这个值是从系统启动开始一直运行的,一直连续的不跳跃的(除非手动改了),这个要比CLOCK_REALTIME精度小一些,所以更快一些。

可以看到计算运行时间的代码,也就是时间差的表达式长了很多,是因为clock_gettime()获取的时间分为两部分:秒和纳秒(在某论坛上有人指出在曾经的 Mac OS X 上这里是微秒,不确定,不过现在也是纳秒了)。秒是int很简单的,但是纳秒用的是long int,这就涉及到转换的问题了。所以就需要分别计算两个部分,转换合成。

实际演示(三种方法的对比)

这里展示一段并行计算程序在三种测量时间方法下的对比,各位可以看看差别(可以推测出测试设备是 6C6T 的 CPU 哦):

请添加图片描述

可以看到有时差别还是挺大的。

参考

21.2 Time Types - GNU

21.4 Processor And CPU Time - GNU

clock_gettime(3) — Linux manual page

What is the proper way to use clock_gettime()? - stack overflow

clock_getres, clock_gettime, clock_settime - clock and timer functions - IEEE

希望能帮到有需要的人~

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

语音机器人的两种常见业务场景

第一个业务场景 之前写过一篇语音机器人是真人录音好&#xff0c;还是TTS转语音更好的文章。今天再来说一说TTS一个很细微的场景。 假设一句话 这里是*****银行委托机构&#xff0c;您在*****银行的信用卡长期逾期至今仍未依照约定履行还款义务&#xff0c;为避免逃废债给您…

vue3父子组件通过$parent与ref通信

父组件 <template><div><h1>ref与$parents父子组件通信 {{ parentMoney }}</h1><button click"handler">点击我子组件的值会减20</button><hr><child ref"children"></child></div> </te…

vue3+ts 指令简写

<template><div class"btns"><button v-has-show"shop:create">创建</button><button v-has-show"shop:edit">编辑</button><button v-has-show"shop:delete">删除</button></div…

如何在Linux中安装和使用dig工具

Dig 命令&#xff08;Domain Information Groper&#xff09;是最流行的 DNS 测试工具之一。您可以用它来在Linux上排查DNS问题。 文章目录 dig如何工作如何在Ubuntu上安装dig常用dig命令使用方法推荐阅读 dig如何工作 "dig"命令是一个用于查询DNS&#xff08;Doma…

IDEA 2022.1 同一个 spring boot main类运行多个实例

普通的 Java 项目 运行多个实例是非常简单的&#xff0c;直接点击 run 多次即可&#xff0c;但在 spring boot 中默认情况下&#xff0c;是不允许把同一个 web 项目改完端口后多次运行的&#xff0c;如下会显示让你先停止当前实例后再启动&#xff1a; 开启运行多个实例的的方法…

Node.js入门指南(五)

目录 MongoDB 介绍 下载与启动 命令行交互 Mongoose 代码模块化 图形化管理工具 hello&#xff0c;大家好&#xff01;上一篇文章我们介绍了express框架&#xff0c;这一篇文字主要介绍MongoDB。来对数据进行存储以及操作。 MongoDB 介绍 各位小伙伴应该多多少少都有接…

15 网关实战: 微服务集成Swagger实现在线文档

上节介绍了网关层面聚合API文档,通过网关的路由信息找到了各个服务的请求地址,这节讲一下微服务如何集成Swagger。 网关的API文档默认调用的是微服务的**/v2/api-docs**这个接口获取API详细信息,比如文章服务的URL:http://localhost:9000/blog-article/v2/api-docs,返回信…

机器视觉:塑造未来的智能视界

&#x1f3a5; 屿小夏 &#xff1a; 个人主页 &#x1f525;个人专栏 &#xff1a; IT杂谈 &#x1f304; 莫道桑榆晚&#xff0c;为霞尚满天&#xff01; 文章目录 &#x1f4d1; 前言&#x1f324;️ 机器视觉技术的实现☁️ 图像采集☁️ 图像处理☁️ 数据建模☁️应用展示…

性能优化的一般策略及方法

性能优化的一般策略及方法 在汽车嵌入式开发领域&#xff0c;性能优化始终是一个无法回避的问题&#xff1a; 座舱 HMI 想要实现更流畅的人机交互 通信中间件在给定的 CPU 资源下&#xff0c;追求更高的吞吐量 更一般的场景&#xff1a;嵌入式设备 CPU 资源告急&#xff0c;需…

uniapp在H5端实现PDF和视频的上传、预览、下载

上传 上传页面 <u-form-item :label"(form.ququ3 1 ? 参培 : form.ququ3 2 ? 授课 : ) 证明材料" prop"ququ6" required><u-button click"upload" slot"right" type"primary" icon"arrow-upward" t…

Ubuntu 22.03 LTS 安装deepin-terminal 实现 终端 分屏

deepin-terminal 安装 源里面自带了这个软件&#xff0c;可以直接装 sudo apt install deepin-terminal 启动 按下Win键&#xff0c;输入deep即可快速检索出图标&#xff0c;点击启动 效果 分屏 CtrlShiftH 水平分割 CtrlShiftJ 垂直分割 最多分割成四个小窗口&#xff0…

Flask Echarts 实现历史图形查询

Flask前后端数据动态交互涉及用户界面与服务器之间的灵活数据传递。用户界面使用ECharts图形库实时渲染数据。它提供了丰富多彩、交互性强的图表和地图&#xff0c;能够在网页上直观、生动地展示数据。ECharts支持各种常见的图表类型&#xff0c;包括折线图、柱状图、饼图、散点…

深度剖析API接口测试工具的企业价值

随着企业软件开发的日益复杂和互联网应用的普及&#xff0c;API接口成为不同软件系统之间信息传递的桥梁。在这一背景下&#xff0c;API接口测试工具的应用变得愈加重要&#xff0c;对企业的发展和软件质量起到了关键性的作用。本文将深入探讨API接口测试工具在企业中的重要性&…

进程(4)——进程地址空间【linux】

进程&#xff08;4&#xff09;——进程地址空间【linux】 一.什么是进程地址空间二.进程地址空间不是真实地址&#xff1f;三.物理地址与进程地址空间的关系&#xff08;整体部分&#xff09;四. 细节4.1 进程地址空间的本质&#xff1a;4.2 为什么要有进程地址空间&#xff1…

机器学习——多元线性回归升维

机器学习升维 升维使用sklearn库实现特征升维实现天猫年度销量预测实现中国人寿保险预测 升维 定义&#xff1a;将原始的数据表示从低维空间映射到高维空间。在线性回归中&#xff0c;升维通常是通过引入额外的特征来实现的&#xff0c;目的是为了更好地捕捉数据的复杂性&#…

MacOS 系统 Flutter开发Android 环境配置

上节我们已经把 开发工具准备齐全&#xff0c;并可以进行Flutter的web开发&#xff0c;本节将做安卓开发环境进行详细说明 接上节这里先说下&#xff0c;系统环境 MacOS14 &#xff08;Sonoma&#xff09; 芯片 Apple M3 执行命令&#xff1a;flutter doctor 提示如下&#…

Shell脚本:Linux Shell脚本学习指南(第三部分Shell高级)一

第三部分&#xff1a;Shell高级&#xff08;一&#xff09; 这一章讲解 Shell 脚本编程的进阶内容&#xff0c;主要涉及重定向、文件描述符、管道和过滤器、子 Shell、信号等。 本章会使用到一些底层的编程知识&#xff0c;有C语言和 C 编程经验的程序员阅读起来将会更加轻松。…

《微信小程序开发从入门到实战》学习三十三

第四章 云开发 本章云开发技术的功能与使用&#xff0c;包括以下几点&#xff1a; 1.学习使用云开发控制台 2.学习云开发JSON数据库功能 3.学习云开文件存储功能 4.学习云函数功能 5.使用云开发技术实现投票小程序的服务端功能 投票小程序大部分已经实现。需要实现&#…

人工智能-优化算法之凸集

凸性 凸性&#xff08;convexity&#xff09;在优化算法的设计中起到至关重要的作用&#xff0c; 这主要是由于在这种情况下对算法进行分析和测试要容易。 换言之&#xff0c;如果算法在凸性条件设定下的效果很差&#xff0c; 那通常我们很难在其他条件下看到好的结果。 此外&…