【算法】C程序的运行速度测试

C语言程序的运行速度测试

代码随想录上提到了一点,即我们应该学会估计一个时间复杂度较高的算法,在机器上的运行速度。

  • 如果题目给出的数据量级在高复杂度的算法中会超时,那就应该放弃使用这个代码,而想其他时间复杂度更优的解法;
  • 这样能避免在刷题的时候,图简单写了个暴力写法却发现超时不过的尴尬(没错说的就是我自己)

大部分OJ题目,对C/C++代码的时间限制都是1s。所以我们测试的目标也将放在1s上。

image-20230419130619879

1.代码

来源:http://www.360doc.com/content/23/0119/15/2690044_1064211133.shtml

我的Git:Gitee

1.1 循环

首先是func.h,内部包含了三个循环函数,时间复杂度分别为O(N) O(N^2) O(NlogN)

//func.h
#include <stdio.h>
// O(N)
void func1(long long n)
{
    printf("开始执行O(N)的函数:%lld\n",n);
    long long k=0;
    for(long long i=0;i<n;i++)
    {
        k++;
    }
}
// O(N^2)
void func2(long long n)
{
    printf("开始执行O(N^2)的函数:%lld\n",n);
    long long k=0;
    for(long long i=0;i<n;i++)
    {
        for(long long j=0;j<n;j++)
        {
            k++;
        }
    }
}

// O(NlogN)
void func3(long long n)
{
    printf("开始执行O(NlogN)的函数:%lld\n",n);
    long long k=0;
    for(long long i=0;i<n;i++)
    {
        // j要从1开始
        for(long long j=1;j<n;j*=2)
        {
            k++;
        }
    }
}

1.2 获取毫秒级时间戳

随后是主文件,这里我们需要进行时间的测试,所以得想办法获取到毫秒级的时间戳。

time.h中的time函数只能够返回秒级时间戳,对于代码的时间测试来说显然是不够的。我们需要借助Windows和Linux的系统函数,获取到毫秒级时间戳

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdint.h>
#include <stdio.h>
// http://www.360doc.com/content/23/0119/15/2690044_1064211133.shtml
// 宏编译,分别使用windows和linux的系统函数 
#ifdef _WIN32
    #include<time.h>
    #include<windows.h>
#else
    #include <sys/time.h>
    #include <unistd.h>
#endif

// 获取当前毫秒级时间,给一个char指针,则打印到其中(字符串)
// 后三位为毫秒
uint64_t GetCurrentTimerMS(char* szTimer)
{
    uint64_t nTimer = 0;
#ifdef _WIN32
	SYSTEMTIME currentTime;
	GetLocalTime(&currentTime);
	struct tm temptm = { currentTime.wSecond,
		currentTime.wMinute,
		currentTime.wHour,
		currentTime.wDay,
		currentTime.wMonth - 1,
		currentTime.wYear - 1900
	};
	nTimer =  mktime(&temptm) * 1000 + currentTime.wMilliseconds;
#else
	struct timeval tv;
	gettimeofday(&tv,NULL);
	// printf("second:%ld\n",tv.tv_sec);  //秒
	nTimer = tv.tv_sec*1000 + tv.tv_usec/1000;
#endif
    if(szTimer != NULL)
        sprintf(szTimer, "%llu", nTimer);
    return nTimer;
}
// 测试时间函数
int test_def()
{
	char szTimer[64];
	uint64_t nTimer=-1;
	GetCurrentTimerMS(szTimer);	//带参数,字符串
	nTimer = GetCurrentTimerMS(NULL); //不带参数
	printf("millisecond1:%s\nmillisecond2:%llu\n",szTimer,nTimer );  //毫秒
	return 0;
}

1.3 获取时间戳测试

先来执行一下这个测试函数test_def,结果如下

$ gcc test.c -o test
$ ./test
millisecond1:1681878963361
millisecond2:1681878963361

成功打印出了毫秒级的时间戳,分别是字符串类型和uint64_t长整型

#ifdef _WIN32
    #include <time.h>
    #include<windows.h>
#else
    #include <sys/time.h>
    #include <unistd.h>
#endif

这里还采用了宏定义,自动判断windows还是linux,调用各自的系统接口函数。

如下图,在Windows下的Vs2019也成功执行这个函数

image-20230419130044160

2.开始测试

这个命令可以查看linux下的cpu型号

$ cat /proc/cpuinfo | grep 'model name' |uniq
model name      : Intel(R) Celeron(R) N5105 @ 2.00GHz

2.1 示例

先测试O(N)算法在何等数量级时会超过1s

$ ./test
请键入n:500000000
start_time: 1681880952986
开始执行O(N)的函数:500000000
end_time:   1681880954073
diff:       1087ms
start_time: 1681880963999
开始执行O(N)的函数:450000000
end_time:   1681880964993
diff:       994ms
请键入n:460000000
start_time: 1681881111806
开始执行O(N)的函数:460000000
end_time:   1681881112804
diff:       998ms
请键入n:470000000
start_time: 1681881117572
开始执行O(N)的函数:470000000
end_time:   1681881118604
diff:       1032ms
请键入n:400000000
start_time: 1681880967163
开始执行O(N)的函数:400000000
end_time:   1681880968043
diff:       880ms
请键入n:550000000
start_time: 1681880970538
开始执行O(N)的函数:550000000
end_time:   1681880971736
diff:       1198ms

如上,是我的linux服务器的测试结果。

数量级大概在460000000的时候,就会达到998ms,也就是将近1s

所以,当我们看到Oj的测试用量超过4500000000数量级的时候,就应该放弃O(N)算法!


而在windows下,我的R7 5800H笔记本,运行到700000000数量级的时候,才需要1s

请键入n:500000000
start_time: 1681881322528
开始执行O(N)的函数:500000000
end_time:   1681881323236
diff:       708ms
请键入n:1000000000
start_time: 1681881327548
开始执行O(N)的函数:1000000000
end_time:   1681881328965
diff:       1417ms
请键入n:600000000
start_time: 1681881332928
开始执行O(N)的函数:600000000
end_time:   1681881333792
diff:       864ms
请键入n:800000000
start_time: 1681881337404
开始执行O(N)的函数:800000000
end_time:   1681881338537
diff:       1133ms
请键入n:700000000
start_time: 1681881341486
开始执行O(N)的函数:700000000
end_time:   1681881342486
diff:       1000ms

2.2 结果

按如上办法测试,我分别测试了三种时间复杂度在多个平台上的结果。稍微了解这些数字,能帮助我们在判断题目选用算法上提供帮助。

表中E8是科学计数法,代表10的8次方

平台/CPU时间复杂度数量级时间(毫秒)
windows (amd R7-5800H)O(N)7E91000
O(N2)3E41022
O(NlogN)1.7E7996
Centos8 (Intel N5105)O(N)4.5E8994
O(N2)2E4920
O(NlogN)1.8E7966
Centos7.2 (Intel Xeon Platinum 8255C)O(N)5.8E8990
O(N2)2.4E4976
O(NlogN)2.1E7976

数据测试于23.04.19

本来还想测测牛客和leetcode的,结果发现它们运行O(N^2)量级的函数,都E7了还是几ms就搞定了,感觉测试的结果不准,故放弃😂

image-20230419134352787

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

慕雪华年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值