计算程序执行耗时
- 返回CPU执行的时间周期数,
cv.getTickCount,
- 每秒CPU时间周期总数
cv.getTickFrequency
计算一段算法处理执行的时间秒数,代码结构如下:
e1 = cv.getTickCount()
// your code execution
e2 = cv.getTickCount()
time = (e2 - e1)/ cv.getTickFrequency()
time是以秒为单位。
计算秒/毫秒/FPS
在算法执行阶段,有三个经常使用的速度性能计量指标分别是秒、毫秒、FPS(每秒多少帧),根据上面的cv.getTickCount与cv.getTickFrequency两个函数,这三个指标的计算代码如下:
e1 = cv.getTickCount()
// your code execution
e2 = cv.getTickCount()
// 计算秒
time = (e2 - e1)/ cv.getTickFrequency()
// 计算毫秒
time2 =( (e2 - e1)/ cv.getTickFrequency() )*1000
// 计算FPS(每秒多少帧)
fps =( cv.getTickFrequency() / (e2 - e1) )
通过网上查阅资料,找到以下几种VC中求取程序运行时间的方法:
方法一 利用GetTickCount函数(ms)
//代码:
CString str;
#include "windows.h"
double t1 = GetTickCount();//程序段开始前取得系统运行时间(ms)
。。。。。。//to do sth
。。。。。。//to do sth
。。。。。。//to do sth
double t2 = GetTickCount();//程序段结束后取得系统运行时间(ms)
double t = t2-t1;//程序运行时间(ms)
str.Format("time:%f ms",t);//程序运行时间
AfxMessageBox(str);
另外一种:(这个比上面的稍微准确一点)
double ta = getTickCount();
。。。。。。//to do sth
。。。。。。//to do sth
。。。。。。//to do sth
Sleep(1000);
double tb = getTickCount();
cout << "tb-ta = " << 1000*(tb-ta)/getTickFrequency() << "ms" << endl;
方法二 利用C/C++计时函数(s)
//代码:
#include "time.h"
clock_t start, finish;
start = clock();
。。。。。。//to do sth
。。。。。。//to do sth
。。。。。。//to do sth
finish = clock();
printf("%f seconds\n",(double)(finish-start)/CLOCKS_PER_SEC);
//VC/MFC中计算程序运行时间
方法三 利用CTime类 获取系统时间
//代码:
CString str;
//获取系统时间
CTime tm;
tm=CTime::GetCurrentTime();
str=tm.Format("现在时间是%Y年%m月%d日 %X");
AfxMessageBox(str);
方法四 利用GetLocalTime类 获取系统时间
SYSTEMTIME st;
CString strDate,strTime;
GetLocalTime(&st);
strDate.Format("M----",st.wYear,st.wMonth,st.wDay);
strTime.Format("-:-:-",st.wHour,st.wMinute,st.wSecond);
AfxMessageBox(strDate);
AfxMessageBox(strTime);
方法五
//算法运行时间
int main()
{
Mat img;
int i, j;
double t,t1;
uchar* data;
int imgSize;
img = imread("lena_gray.jpg", 0);
t = (double)cvGetTickCount();//
for (j = 0; j < img.rows; j++)
{
for (i = 0; i < img.cols; i++)
{
img.at<uchar>(j, i) = 255;
}
}
t1 = cvGetTickCount();
t = (t1-t)/(cvGetTickFrequency()*1000);//
cout << "at operation cost : " << t << "ms" << endl;//
data = img.ptr<uchar>(0);
imgSize = img.rows*img.cols*img.channels();
t = cvGetTickCount();
for (j = 0; j < imgSize; j++)
{
data[j] = 255;
}
t1 = (double)cvGetTickCount();
t = (t1-t)/(cvGetTickFrequency()*1000);
cout << "ptr operation cost : " << t << "ms" << endl;
return 0;
}
经过计算,对512*512的图像进行编历,
at操作耗时为0.424076ms
ptr操作耗时为0.0346413ms
double duration;
duration = static_cast<double>(cv::getTickCount());
。。。。。。//to do sth
。。。。。。//to do sth
。。。。。。//to do sth
duration = static_cast<double>(cv::getTickCount())-duration;
duration /= cv::getTickFrequency(); // the elapsed time in ms
在C语言中统计算法运行时间有多种方法,不同方法的精度、适用场景和系统依赖性各异。以下是四种主流实现方式及其详细说明:
⏱️ 1. 使用 clock()
函数(标准库方法)
原理:测量CPU实际执行代码的时间(处理器时间),不包括I/O等待或睡眠时间。
精度:毫秒级(依赖系统时钟频率)。
适用场景:单线程CPU密集型算法。
示例代码:
#include <stdio.h>
#include <time.h>
int main() {
clock_t start = clock();
// 待测算法
for (int i = 0; i < 1000000; i++); // 示例循环
clock_t end = clock();
double time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
printf("CPU 时间: %.6f 秒\n", time_used);
return 0;
}
注意:多线程环境下可能不准确,因线程切换导致CPU时间统计偏差。
⏱️ 2. 使用 time()
函数(低精度墙上时间)
原理:返回自1970年1月1日(Unix纪元)起的秒数,测量实际流逝时间(墙上时间)。
精度:秒级。
适用场景:长时间运行(>1秒)的算法,如批处理任务。
示例代码:
#include <stdio.h>
#include <time.h>
int main() {
time_t start = time(NULL);
// 待测算法
sleep(2); // 模拟耗时操作
time_t end = time(NULL);
double elapsed = difftime(end, start);
printf("墙上时间: %.2f 秒\n", elapsed);
return 0;
}
缺点:无法测量短于1秒的操作。
⏱️ 3. 使用 gettimeofday()
(微秒级精度)
原理:获取系统当前时间(墙上时间),精确到微秒。
精度:微秒级(10⁻⁶秒)。
适用场景:需高精度但非跨平台的场景(如Linux/macOS)。
示例代码:
#include <stdio.h>
#include <sys/time.h>
int main() {
struct timeval start, end;
gettimeofday(&start, NULL);
// 待测算法
for (int i = 0; i < 1000000; i++);
gettimeofday(&end, NULL);
long seconds = end.tv_sec - start.tv_sec;
long micros = end.tv_usec - start.tv_usec;
double elapsed = seconds + micros / 1e6;
printf("时间: %.6f 秒\n", elapsed);
return 0;
}
注意:系统时间调整(如NTP同步)可能导致结果异常。
⏱️ 4. 高精度计时器(纳秒级)
Windows:QueryPerformanceCounter
#include <stdio.h>
#include <windows.h>
int main() {
LARGE_INTEGER freq, start, end;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&start);
// 待测算法
for (int i = 0; i < 1000000; i++);
QueryPerformanceCounter(&end);
double elapsed = (end.QuadPart - start.QuadPart) / (double)freq.QuadPart;
printf("时间: %.9f 秒\n", elapsed);
return 0;
}
Linux:clock_gettime()
#include <stdio.h>
#include <time.h>
int main() {
struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start);
// 待测算法
for (int i = 0; i < 1000000; i++);
clock_gettime(CLOCK_MONOTONIC, &end);
double elapsed = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9;
printf("时间: %.9f 秒\n", elapsed);
return 0;
}
特点:
- •
精度:纳秒级(10⁻⁹秒)。
- •
时钟源:
CLOCK_MONOTONIC
避免系统时间跳变影响。
📊 方法对比与选择建议
方法 |
精度 |
测量时间类型 |
系统依赖 |
适用场景 |
---|---|---|---|---|
|
毫秒级 |
CPU时间 |
跨平台 |
单线程CPU密集型任务 |
|
秒级 |
墙上时间 |
跨平台 |
长时间任务(>1秒) |
|
微秒级 |
墙上时间 |
POSIX系统(Linux/macOS) |
需高精度但非跨平台 |
|
纳秒级 |
墙上时间 |
系统特定API |
极致精度要求 |
⚠️ 实际应用注意事项
- 1.
多次测量取平均值:减少系统调度和外部干扰的影响,尤其短时任务。
- 2.
避免I/O操作:测量期间尽量减少文件读写、打印等操作,避免额外耗时干扰。
- 3.
编译器优化:使用
volatile
防止循环被优化掉,例如:
volatile int sum = 0;
for (int i = 0; i < 1000000; i++) sum += i;
- 4.
多线程环境:优先使用墙上时间(如
clock_gettime()
),因CPU时间可能漏计其他线程占用。
💎 总结
- •
基础需求:用
clock()
或time()
即可满足多数场景。 - •
高精度需求:
- •
Windows优先选
QueryPerformanceCounter
; - •
Linux/macOS选
clock_gettime(CLOCK_MONOTONIC)
。
- •
- •
关键原则:根据算法类型(CPU密集型 vs I/O密集型)和精度要求选择合适方法,并通过多次测量提升准确性。