首页 > 编程语言 >程序的运行时间(超时是咋回事 + 测试实验)

程序的运行时间(超时是咋回事 + 测试实验)

时间:2024-10-11 20:11:04浏览次数:1  
标签:1s ++ long 回事 测试 超时 CPU 运行

一些同学可能对计算机运行的速度还没有概念,只是感觉计算机运行速度应该会很快,那么在OJ(online judge,比如大家熟悉的leetcode)上做算法题目的时候为什么OJ会判断运行的程序超时呢?其超时情况如图所示:
img

超时是怎么回事

在leetcode上练习算法的时候应该都遇到过一种错误是“超时”。

也就是说程序运行的时间超过了规定的时间,一般OJ(online judge)的超时时间就是1s,也就是用例数据输入后最多要1s内得到结果,下文为了方便讲解,暂定超时时间就是1s。

如果写出了一个 O(n)的算法 ,其实可以估算出来n是多大的时候算法的执行时间就会超过1s了。

如果n的规模已经足够让 O(n) 的算法运行时间超过了1s,就应该考虑log(n)的解法了。

从硬件配置看计算机的性能

计算机的运算速度主要看CPU的配置,以2015年MacPro为例,CPU配置:2.7 GHz Dual-Core Intel Core i5 。

也就是 2.7 GHz 奔腾双核,i5处理器,GHz是指什么呢,1Hz = 1/s,1Hz 是CPU的一次脉冲(可以理解为一次改变状态,也叫时钟周期),称之为为赫兹,那么1GHz等于多少赫兹呢

1GHz(兆赫)= 1000MHz(兆赫)
1MHz(兆赫)= 1百万赫兹
所以 1GHz = 10亿Hz,表示CPU可以一秒脉冲10亿次(有10亿个时钟周期),这里不要简单理解一个时钟周期就是一次CPU运算,即一次CPU运算可能需要好几个时钟周期。

例如1 + 2 = 3,cpu要执行四次才能完整这个操作,步骤一:把1放入寄存器,步骤二:把2放入寄存器,步骤三:做加法,步骤四:保存3。

而且计算机的cpu也不会只运行我们自己写的程序上,同时cpu也要执行计算机的各种进程任务等等,我们的程序仅仅是其中的一个进程而已。

所以我们的程序在计算机上究竟1s真正能执行多少次操作呢?

测试计算机的运行速度(做一个测试实验)

在写测试程序测1s内处理多大数量级数据的时候,有三点需要注意:

  1. CPU执行每条指令所需的时间实际上并不相同,例如CPU执行加法和乘法操作的耗时实际上都是不一样的。

  2. 现在大多计算机系统的内存管理都有缓存技术,所以频繁访问相同地址的数据和访问不相邻元素所需的时间也是不同的。

  3. 计算机同时运行多个程序,每个程序里还有不同的进程线程在抢占资源。
    尽管有很多因素影响,但是还是可以对自己程序的运行时间有一个大体的评估的。

引用算法4里面的一段话:

火箭科学家需要大致知道一枚试射火箭的着陆点是在大海里还是在城市中;

医学研究者需要知道一次药物测试是会杀死还是会治愈实验对象;

所以任何开发计算机程序的软件工程师都应该能够估计这个程序的运行时间是一秒钟还是一年。

这个是最基本的,所以以上误差就不算事了。

以下以C++代码为例:

测试硬件:天选3,CPU配置:intel i7-12700H

实现三个函数,时间复杂度分别是 O(n) , O(n2), O(nlogn),使用加法运算来统一测试。

// O(n)
void function1(long long n) {
    long long k = 0;
    for (long long i = 0; i < n; i++) {
        k++;
    }
}

// O(n^2)
void function2(long long n) {
    long long k = 0;
    for (long long i = 0; i < n; i++) {
        for (long j = 0; j < n; j++) {
            k++;
        }
    }

}
// O(nlogn)
void function3(long long n) {
    long long k = 0;
    for (long long i = 0; i < n; i++) {
        for (long long j = 1; j < n; j = j*2) { // 注意这里j=1
            k++;
        }
    }
}

来看一下这三个函数随着n的规模变化,耗时会产生多大的变化,先测function1 ,就把 function2 和 function3 注释掉

int main() {
    long long n; // 数据规模
    while (cout << "输入n:" && cin >> n) {
        milliseconds start_time = duration_cast<milliseconds >(
            system_clock::now().time_since_epoch()
        );
        function1(n);
//        function2(n);
//        function3(n);
        milliseconds end_time = duration_cast<milliseconds >(
            system_clock::now().time_since_epoch()
        );
        cout << "耗时:" << milliseconds(end_time).count() - milliseconds(start_time).count()
            <<" ms"<< endl;
    }
}
  • 来看一下O(n)运行的效果,如下图:
    img

    O(n)的算法,1s内大概计算机可以运行 \(3 * (10^9)\)次计算.

  • 可以推测一下 O(n2)的算法应该1s可以处理的数量级的规模是 \(3 * (10^9)\)开根号,运行效果如下:
    img

    O(n^2)的算法,1s内大概计算机可以运行 55000次计算,验证了刚刚的推测。

  • 再推测一下 O(nlogn)的话, 1s可以处理的数据规模是什么呢?

    理论上应该是比 O(n)少一个数量级,因为 logn 的复杂度 其实是很快,看一下实验数据:
    img

    O(nlogn)的算法,1s内大概计算机可以运行 3 * (10^7)次计算,符合预期。

完整测试代码

#include <iostream>
#include <chrono>
#include <thread>
using namespace std;
using namespace chrono;
// O(n)
void function1(long long n) {

    long long k = 0;
    for (long long i = 0; i < n; i++) {
        k++;
    }
}

// O(n^2)
void function2(long long n) {
    long long k = 0;
    for (long long i = 0; i < n; i++) {
        for (long j = 0; j < n; j++) {
            k++;
        }
    }

}
// O(nlogn)
void function3(long long n) {
    long long k = 0;
    for (long long i = 0; i < n; i++) {
        for (long long j = 1; j < n; j = j*2) { // 注意这里j=1
            k++;
        }
    }
}
int main() {
    long long n; // 数据规模
    while (cout << "输入n:" && cin >> n) {
        milliseconds start_time = duration_cast<milliseconds >(
            system_clock::now().time_since_epoch()
        );
        cout << "O(n)算法,";
        function1(n);
        // cout << "O(n^2)算法,";
        // function2(n);
        // cout << "O(nlogn)算法,";
        // function3(n);
        milliseconds end_time = duration_cast<milliseconds >(
            system_clock::now().time_since_epoch()
        );
        cout << "耗时:" << milliseconds(end_time).count() - milliseconds(start_time).count()
            <<" ms"<< endl;
    }
}

标签:1s,++,long,回事,测试,超时,CPU,运行
From: https://www.cnblogs.com/hisun9/p/18459186

相关文章

  • AI预测体彩排3采取888=3策略+和值012路或胆码测试10月11日升级新模型预测第101弹
            经过100多期的测试,当然有很多彩友也一直在观察我每天发的预测结果,得到了一个非常有价值的信息,那就是9码定位的命中率非常高,已到达90%的命中率,这给喜欢打私菜的朋友提供了极高价值的预测结果~当然了,大部分菜友还是走的正常渠道,因此,得想办法进行缩水,尽可能少的缩......
  • AI预测福彩3D采取888=3策略+和值012路或胆码测试10月11日新模型预测第107弹
            经过100多期的测试,当然有很多彩友也一直在观察我每天发的预测结果,得到了一个非常有价值的信息,那就是9码定位的命中率非常高,100多期一共只错了12次,这给喜欢打私房菜的朋友提供了极高价值的预测结果~当然了,大部分菜友还是走的正常渠道,因此,得想办法进行缩水,尽可能......
  • ROS1,用C++实现获取激光雷达数据,并使用gazebo测试
    实现步骤构建一个新的软件包,包名叫做lidar_pkg。cdcatkin_ws/src/catkin_create_pkglidar_pkgroscpprospysensor_msgs输入code,打开vscode在软件包中新建一个节点,节点名叫做lidar_node。在节点中,向ROS大管家NodeHandle申请订阅话题/scan,并设置回调函数为......
  • 聊聊影响性能测试成熟度的内容项
    目录一、性能测试流程规范1.1、性能需求型模式下的流程规范1.2、性能常态化模式下的流程规范1.3、性能平台化模式下的规范流程二、性能测试环境2.1、无性能测试环境2.2、性能测试与功能测试共用测试环境2.3、有独立的性能测试环境三、工具及平台3.1、性能测试压测工......
  • ui自动化测试框架po框架
    一、po基本介绍(1)PO框架是Page Object的缩写(2)po框架:业务流程与页面元素操作分离的模式,可以简单理解为每个页面下面都有一个配置class, 配置class就用来维护页面元素或操作方法(3)提高测试用例的可维护性、可读取性(4)对比:传统的设计测试用例存在的弊端:1.易读性差2.复用性差3.可维护性......
  • 智驾仿真测试实战之自动泊车HiL仿真测试:自动泊车系统简介|自动泊车HiL仿真测试系统|
    1.引言汽车进入智能化时代,自动泊车功能已成为标配。在研发测试阶段,实车测试面临测试场景覆盖度不足、效率低下和成本高昂等挑战。为解决这些问题,本文提出一种自动泊车HiL仿真测试系统方案,可大幅度提升测试效率及测试场景覆盖度、缩短测试周期、加速产品迭代升级。Jum......
  • 测试要不要转岗项目经理?
    前天写了一篇文章《测试要不要转岗产品经理》,本意是针对星球同学的问题分享我的一些思考,没成想引起了很多同学的讨论。随着话题进一步发酵,问题延伸到了转岗上面,有同学问我测试能否转岗为项目经理,延长职场生涯。这篇文章,聊聊转岗这个话题,顺带探讨一下职业生涯发展规划。 转岗......
  • Android主流厂商云真机测试体验
    在Android平台下应用开发,机型适配是绕不开的话题,今天跟大家分享大厂商提供的云真机测试服务的使用体验。在我们开发分身产品空壳过程中,需要耗费大量的精力确保各厂商的设备稳定性,而针对主流手机厂商适配则是重中之重。以往我们需要外租对应的设备测试,耗资高,效率低,管理麻烦......
  • vue3 props 响应式测试,props使用,ref独立ts解构
    概论vue3的props是深度响应的,深度数据改变都能监听到,并改变模板3.2左右的版本解构props子对象不能响应式若遇到props子对象不能响应式监听,一般就是改变之前的数据和改变之后的数据没产生变化,所以没发生响应式代码父组件<template><divclass='box'>demo<c......
  • 【测试项目】——个人博客系统测试报告
    ......