C / C++ 中的计时函数: clock()

clock() 函数是 C 标准库 time.h 中的一个函数, time.h 标准库中定义了各种涉及日期和时间的函数, 变量类型和宏. 其中, clock() 函数可以返回自程序开始执行到当前位置为止, 处理器走过的时钟打点数(即”ticks”, 可以理解为”处理器时间”). 在 VC++6.0 中, 每过千分之一秒(即 1 毫秒)则 clock() 函数的返回值加 1. 但是, 处理器的时钟打点数并不是一个人类可以直观感知的时间概念, 时钟打点数只描绘了该处理器在处理该问题时所耗费的”处理器时间”. 为了能将获取到的时间转换成便于人类理解且具有普遍性的”时 分 秒”的计时方式, 我们需要引入一个常量, 在 VC++6.0 中, 使用常量 CLOCKS_PER_SEC 来进行转换且 CLOCKS_PER_SEC=1000.
但是在不同的编译环境中, CLOCKS_PER_SEC 的数值可能是不同的. 在 Windows 10 中使用”Everything”这个程序在本机上搜索 stdio.h 可以看到我的这个计算机操作系统中存在”Emacs”, “CodeBlocks”和”Dev-cpp”三款编译器, 因此也就存在三套相互独立的 C 语言编译环境, 如图 1:

图 1

(下面以 Windows 10 下的 CodeBlocks 的编译环境为例, 查看在 C 语言的头文件中关于 CLOCKS_PER_SEC 的定义.)

在我的电脑上, CodeBlocks 的 C 语言头文件位于下面的位置:

C:\GreenSoftware\codeblocks-17.12mingw-nosetup\MinGW\include

在这个目录下找到 time.h 这个头文件, 可以在其中找到如下关于 CLOCKS_PER_SEC 的定义:

/*
 * Number of clock ticks per second. A clock tick is the unit by which
 * processor time is measured and is returned by 'clock'.
 */
#define    CLOCKS_PER_SEC  ((clock_t)1000)
#define    CLK_TCK     CLOCKS_PER_SEC

由上面的头文件中的定义可以知道, 常量 CLOCKS_PER_SEC 的值被定义为 1000, 变量类型为 clock_t.

为了验证, 我们可以在 Windows 平台上的 CodeBlocks 中运行如下 C++ 程序:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
using namespace std;

int main()
{
    int i=10;
    clock_t start,finish;
    double Times, Times1;
    start=clock();
    while(i--){
        cout<<i<<endl;
    };
    finish=clock();
    Times=(double)(finish-start)/CLOCKS_PER_SEC;
    Times1=(double)(finish-start)/CLK_TCK;
    cout<<"start(时钟打点): "<<start<<endl;
    cout<<"finish(时钟打点): "<<finish<<endl;
    cout<<"CLOCKS_PER_SEC: "<<CLOCKS_PER_SEC<<endl;
    cout<<"CLK_TCK: "<<CLK_TCK<<endl;
    cout<<"运行时间(秒)(CLOCKS_PER_SEC): "<<Times<<endl;
    cout<<"运行时间(秒)(CLK_TCK): "<<Times1<<endl;

    return 0;
}

控制台的输出结果是:

9
8
7
6
5
4
3
2
1
0
start(时钟打点): 5
finish(时钟打点): 6
CLOCKS_PER_SEC: 1000
CLK_TCK: 1000
运行时间(秒)(CLOCKS_PER_SEC): 0.001
运行时间(秒)(CLK_TCK): 0.001

Process returned 0 (0x0)   execution time : 0.322 s
Press any key to continue.

根据上面的输出结果也可以证明在 Windows 平台上的 CodeBlocks 编译器中常量 CLOCKS_PER_SEC 的值被定义为 1000.

注: 在 VC++6.0 环境中, CLK_TCKCLOCKS_PER_SEC 均被定义成 1000. 因此, 一般情况下, 在 Windows 环境中, 程序里使用 CLK_TCK 或者 CLOCKS_PER_SEC 的效果是一样的, 但是, 在 Linux 环境中只能使用 CLOCKS_PER_SEC.

Linux 下对于 CLOCKS_PER_SEC 这个常量的定义一般和 Windows 下是不同的.

Linux 下的 C 语言头文件通常都是放在 /usr/include 这个目录下.

(下面, 我将使用”Kali Linux 2019.1″进行本部分接下来的操作.)

/usr/include 目录下找到并打开 time.h, 在其中可以看到如下内容:

/* This defines CLOCKS_PER_SEC, which is the number of processor clock
   ticks per second, and possibly a number of other constants.   */
#include <bits/time.h>

在这个头文件里没有直接指明 CLOCKS_PER_SEC 的值, 而是选择包含了 bits/time.h 这个头文件. 于是, 我们在 /usr/include/x86_64-linux-gnu/bits 目录下找到 time.h 文件, 可以找到如下内容:

/* ISO/IEC 9899:1999 7.23.1: Components of time
   The macro `CLOCKS_PER_SEC' is an expression with type `clock_t' that is
   the number per second of the value returned by the `clock' function.  */
/* CAE XSH, Issue 4, Version 2: <time.h>
   The value of CLOCKS_PER_SEC is required to be 1 million on all
   XSI-conformant systems. */
#define CLOCKS_PER_SEC  ((__clock_t) 1000000)

由此我们知道, 在该 C 语言编译环境下, CLOCKS_PER_SEC 的值被定义成 1000000.

同样地, 在 Linux 下运行如下程序也可以看到当前编译环境下 CLOCKS_PER_SEC 的数值是多少:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
using namespace std;

int main()
{
    int i=10;
    clock_t start,finish;
    double Times;
    start=clock();
    while(i--){
        cout<<i<<endl;
    };
    finish=clock();
    Times=(double)(finish-start)/CLOCKS_PER_SEC;
    cout<<"start(ticks): "<<start<<endl;
    cout<<"finish(ticks): "<<finish<<endl;
    cout<<"CLOCKS_PER_SEC: "<<CLOCKS_PER_SEC<<endl;
    cout<<"Total Times(s)(CLOCKS_PER_SEC): "<<Times<<endl;

    return 0;
}

运行后, 控制台的输出结果是:

9
8
7
6
5
4
3
2
1
0
start(ticks): 1124
finish(ticks): 1169
CLOCKS_PER_SEC: 1000000
Total Times(s)(CLOCKS_PER_SEC): 4.5e-05

另外, 在 time.h 这个 C 标准库中, 还定义了四个库变量, 其中库变量 clock_t 的作用是存储处理器时间, 因此, 在声明 clock() 函数的时候需要使用 clock_t 声明函数的返回值类型.

使用 clock() 计算程序中一个函数运行耗时的模板如下:

#include <stdio.h>

#include <time.h>
/*
导入 clock() 函数的头文件.
*/

clock_t start, stop;
/*
定义记录开始和结束时间的变量.
clock_t 是 clock() 函数的返回变量类型.
*/

double duration;
/*
记录函数运行时间, 单位为秒.
*/

int main(){

    start=clock();
/*
记录自 main() 函数被执行开始到本次 clock() 被调用一共走过了多少个 ticks.
*/

    MyFunction();//要进行计时的目标函数.

    stop=clock();
/*
记录自 main() 函数被执行开始到本次 clock() 被调用一共走过了多少个 ticks.
*/

    duration=((double)(stop-start))/CLOCKS_PER_SEC;
    //将时钟打点数转换成人类可以直观感知的时间秒数.

    /*
    不在测试范围内的操作写在这里, 例如输出 duration 的数值的操作等.
    */

    return 0;
}

荒原之梦网全部内容均为原创,提供了涵盖考研数学基础知识、考研数学真题、考研数学练习题和计算机科学等方面,大量精心研发的学习资源。

意见反馈 | 内容纠错 | 微信 | QQ | 公众号 | 知乎 | 微博 | 博客园 |CSDN | B 站 | 电子邮件
豫 ICP 备 17023611 号-1 | 公网安备 - 荒原之梦 豫公网安备 41142502000132 号 | SiteMap
Copyright © 2017-2024 ZhaoKaifeng.com 版权所有 All Rights Reserved.

Copyright © 2024   zhaokaifeng.com   All Rights Reserved.
豫ICP备17023611号-1
 豫公网安备41142502000132号

荒原之梦 自豪地采用WordPress