简单的耗时检测器

        最近在自测时,需要检测一些代码逻辑的耗时,很简单的做法就是在代码逻辑执行前记录下时间戳,代码逻辑执行后计算当前时间戳与之前所记录时间戳的差值就OK了。为了使得耗时计算逻辑在不同模块的复用,这里对耗时逻辑做了简单的封装,原理很简单,利用了C++类的构造函数以及析构函数来进行自动计算。如下:
time_consuming_detector.h

#ifndef __TIME_CONSUMING_DETECTOR__
#define __TIME_CONSUMING_DETECTOR__
#pragma once

#include <chrono>
#include <functional>
#include <string>

/*
 * @brief 耗时检测器(注意:非线程安全)
 */
class TimeConsumingDetector
{
public:
	/* 开始回调函数 */
	typedef std::function<void(
		const std::string& tag,
		const std::string& file,
		int line,
		const std::string& func)> BEGIN_FUNC;
	/* 抓拍回调函数 */
	typedef std::function<void(
		const std::string& tag,
		const std::string& subTag,
		const std::string& file,
		int line,
		const std::string& func,
		const std::chrono::milliseconds& duration)> CAPTURE_FUNC;
	/* 结束回调函数 */
	typedef std::function<void(
		const std::string& tag,
		const std::string& file,
		int line,
		const std::string& func,
		const std::chrono::milliseconds& duration)> END_FUNC;

public:
	/**
	 * @brief 构造函数
	 * @param beginFunc 开始函数
	 * @param captureFunc 抓拍函数
	 * @param endFunc 结束函数
	 * @param tag 标签
	 * @param file 调用的文件名
	 * @param line 调用的行号
	 * @param func 调用的函数名
	 */
	TimeConsumingDetector(const BEGIN_FUNC& beginFunc, const CAPTURE_FUNC& captureFunc, const END_FUNC& endFunc,
		const std::string& tag = "", const std::string& file = "", int line = 0, const std::string& func = "")
		: m_begin(std::chrono::steady_clock::now())
		, m_capture(m_begin)
		, m_captureFunc(captureFunc)
		, m_endFunc(endFunc)
		, m_tag(tag)
		, m_file(file)
		, m_line(line)
		, m_func(func)
	{
		if (beginFunc)
		{
			beginFunc(tag, file, line, func);
		}
	}
	~TimeConsumingDetector()
	{
		if (m_endFunc)
		{
			m_endFunc(m_tag, m_file, m_line, m_func,
				std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - m_begin));
		}
	}
	/**
	 * @brief 抓拍
	 * @param subTag 子标签
	 * @param file 调用的文件名
	 * @param line 调用的行号
	 * @param func 调用的函数名
	 * @param captureFunc 抓拍函数(若有设置,则回调该函数,否则回调构造时所设置的函数)
	 */
	void capture(const std::string& subTag = "", const std::string& file = "", int line = 0, const std::string& func = "",
		const CAPTURE_FUNC& captureFunc = nullptr)
	{
		std::chrono::steady_clock::time_point preCapture = m_capture;
		m_capture = std::chrono::steady_clock::now();
		std::chrono::milliseconds duration = std::chrono::duration_cast<std::chrono::milliseconds>(m_capture - preCapture);
		if (captureFunc)
		{
			captureFunc(m_tag, subTag, file, line, func, duration);
		}
		else if (m_captureFunc)
		{
			m_captureFunc(m_tag, subTag, file, line, func, duration);
		}
	}

private:
	std::chrono::steady_clock::time_point m_begin;	/* 开始时间 */
	std::chrono::steady_clock::time_point m_capture;	/* 抓拍时间 */
	CAPTURE_FUNC m_captureFunc;	/* 抓拍函数 */
	END_FUNC m_endFunc;	/* 结束函数 */
	std::string m_tag;	/* 标签 */
	std::string m_file;	/* 开始时调用位置的文件名 */
	int m_line;	/* 开始时调用位置的行号 */
	std::string m_func;	/* 开始时调用位置的函数名 */
};

#define TIME_CONSUMING_DETECTOR_VAR_NAME_CONNECTION(var1, var2) var1##var2
#define TIME_CONSUMING_DETECTOR_VAR_NAME(var1, var2) TIME_CONSUMING_DETECTOR_VAR_NAME_CONNECTION(var1, var2)
#define TIME_CONSUMINT_DETECTOR_VAR(var) TIME_CONSUMING_DETECTOR_VAR_NAME(var, __LINE__)

/* 定义耗时检测器对象(非线程安全) */
#define TIME_CONSUMING_DETECTOR(detector, beginFunc, captureFunc, endFunc, tag) \
	TimeConsumingDetector detector(beginFunc, captureFunc, endFunc, tag, __FILE__, __LINE__, __FUNCTION__);

/* 耗时检测器对象抓拍(非线程安全) */
#define TIME_CONSUMING_DETECTOR_CAPTURE(detector, subTag) \
	detector.capture(subTag, __FILE__, __LINE__, __FUNCTION__);

/* 定义带标识的简单耗时检测器对象(非线程安全,自动命名变量) */
#define SIMPLE_TIME_CONSUMING_DETECTOR(endFunc, tag) \
	TIME_CONSUMING_DETECTOR(TIME_CONSUMINT_DETECTOR_VAR(_timeConsumingDetector_), nullptr, nullptr, endFunc, tag)

#endif /* __TIME_CONSUMING_DETECTOR__ */

        基于耗时检测器,封装了一个超时监控器,如下:
timeout_monitor.h

#ifndef __TIMEOUT_MONITOR__
#define __TIMEOUT_MONITOR__
#pragma once

#include "time_consuming_detector.h"

/*
 * @brief 默认的超时监控时长(单位:毫秒)
 */
const auto DEFAULT_TIMEOUT_MONITORING_TIME = std::chrono::milliseconds(50);

/*
 * @brief 超时监控器(注意:非线程安全)
 */
class TimeoutMonitor
{
public:
	TimeoutMonitor(const TimeConsumingDetector::CAPTURE_FUNC& captureFunc, const TimeConsumingDetector::END_FUNC& endFunc,
		const std::chrono::steady_clock::duration& timeout = DEFAULT_TIMEOUT_MONITORING_TIME,
		const std::string& tag = "", const std::string& file = "", int line = 0, const std::string& func = "")
	{
		m_detector = new TimeConsumingDetector(
			nullptr, nullptr,
			[timeout, endFunc](
				const std::string& tag,
				const std::string& file,
				int line,
				const std::string& func,
				const std::chrono::milliseconds& duration)
			{
				if (duration >= timeout)
				{
					if (endFunc)
					{
						endFunc(tag, file, line, func, duration);
					}
				}
			}, tag, file, line, func);
		m_captureFunc = captureFunc;
	}

	~TimeoutMonitor()
	{
		if (m_detector)
		{
			delete m_detector;
			m_detector = nullptr;
		}
	}

	void capture(const std::chrono::steady_clock::duration& timeout = DEFAULT_TIMEOUT_MONITORING_TIME,
		const std::string& subTag = "", const std::string& file = "", int line = 0, const std::string& func = "")
	{
		if (m_detector)
		{
			m_detector->capture(subTag, file, line, func,
				[timeout, captureFunc = m_captureFunc](
					const std::string& tag,
					const std::string& subTag,
					const std::string& file,
					int line,
					const std::string& func,
					const std::chrono::milliseconds& duration)
				{
					if (duration >= timeout)
					{
						if (captureFunc)
						{
							captureFunc(tag, subTag, file, line, func, duration);
						}
					}
				});
		}
	}

private:
	TimeConsumingDetector* m_detector;	/* 检测器 */
	TimeConsumingDetector::CAPTURE_FUNC m_captureFunc;	/* 抓拍函数 */
};

/* 启动超时监控器(非线程安全) */
#define START_TIMEOUT_MONITOR(monitor, captureFunc, endFunc, timeout, tag) \
	TimeoutMonitor monitor(captureFunc, endFunc, timeout, tag, __FILE__, __LINE__, __FUNCTION__);

/* 超时监控抓拍(非线程安全) */
#define TIMEOUT_MONITOR_CAPTURE(monitor, timeout, subTag) \
	monitor.capture(timeout, subTag, __FILE__, __LINE__, __FUNCTION__);

/* 启动简单超时监控器(非线程安全,自动命名变量) */
#define START_SIMPLE_TIMEOUT_MONITOR(endFunc, timeout, tag) \
	START_TIMEOUT_MONITOR(TIME_CONSUMINT_DETECTOR_VAR(_timeoutMonitor_), nullptr, endFunc, timeout, tag)

/* 启动简单超时监控器(非线程安全,自动命名变量,默认指定监控时长) */
#define START_EASY_TIMEOUT_MONITOR(endFunc, tag) START_SIMPLE_TIMEOUT_MONITOR(endFunc, DEFAULT_TIMEOUT_MONITORING_TIME, tag)

#endif /* __TIMEOUT_MONITOR__ */

示例:

#include <iostream>
#include <thread>
#include "timeout_monitor.h"

void onDetectorBegin(const std::string& tag, const std::string& file, int line, const std::string& func)
{
	std::cout << "detector[start]: [" << tag << "] [" << file << "] [" << line << "] [" << func << "]" << std::endl;
}

void onDetectorCapture(const std::string& tag, const std::string& subTag, const std::string& file, int line, const std::string& func, const std::chrono::milliseconds& duration)
{
	std::cout << "detector[capture]: [" << tag << "][" << subTag << "] [" << file << "] [" << line << "] [" << func << "] [" << duration.count() << " ms]" << std::endl;
}

void onDetectorEnd(const std::string& tag, const std::string& file, int line, const std::string& func, const std::chrono::milliseconds& duration)
{
	std::cout << "detector[finish]: [" << tag << "] [" << file << "] [" << line << "] [" << func << "] [" << duration.count() << " ms]" << std::endl;
}

void onMonitorCapture(const std::string& tag, const std::string& subTag, const std::string& file, int line, const std::string& func, const std::chrono::milliseconds& duration)
{
	std::cout << "monitor[capture]: [" << tag << "][" << subTag << "] [" << file << "] [" << line << "] [" << func << "] [" << duration.count() << " ms]" << std::endl;
}

void onMonitorEnd(const std::string& tag, const std::string& file, int line, const std::string& func, const std::chrono::milliseconds& duration)
{
	std::cout << "monitor[finish]: [" << tag << "] [" << file << "] [" << line << "] [" << func << "] [" << duration.count() << " ms]" << std::endl;
}

void testTimeConsumeDetector1()
{
	TIME_CONSUMING_DETECTOR(detector, onDetectorBegin, onDetectorCapture, onDetectorEnd, "testTimeConsumeDetector1");
	for (int i = 0; i <= 5; ++i) {
		std::this_thread::sleep_for(std::chrono::milliseconds(i * 100));
		TIME_CONSUMING_DETECTOR_CAPTURE(detector, std::to_string(i));
	}
	std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

void testTimeConsumeDetector2()
{
	SIMPLE_TIME_CONSUMING_DETECTOR(onDetectorEnd, "testTimeConsumeDetector2");
	std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

void testTimeoutMonitor1()
{
	START_TIMEOUT_MONITOR(monitor, onMonitorCapture, onMonitorEnd, std::chrono::seconds(1), "testTimeoutMonitor1");
	for (int i = 0; i <= 5; ++i) {
		std::this_thread::sleep_for(std::chrono::milliseconds(i * 100));
		TIMEOUT_MONITOR_CAPTURE(monitor, std::chrono::milliseconds(50), std::to_string(i));
	}
	std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

void testTimeoutMonitor2()
{
	START_SIMPLE_TIMEOUT_MONITOR(onMonitorEnd, std::chrono::milliseconds(100), "testTimeoutMonitor2-1");
	std::this_thread::sleep_for(std::chrono::milliseconds(100));
	START_EASY_TIMEOUT_MONITOR(onMonitorEnd, "testTimeoutMonitor2-2");
	std::this_thread::sleep_for(std::chrono::milliseconds(100));
}

int main()
{
	testTimeConsumeDetector1();
	testTimeConsumeDetector2();
	std::cout << std::endl << std::endl;
	testTimeoutMonitor1();
	testTimeoutMonitor2();
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
根据引用\[1\]中提到的方法,有几种可以提高yolov5检测小目标的效果的方法。首先是将图片压缩成大尺寸进行训练,但这可能需要更多的显存。其次是添加小检测头,这对于P5模型可能有一定的效果,但对于P6模型可能没有太大帮助。还可以尝试添加一些检测模型和玄学机制,这可能需要参考相关论文来了解更多细节。最后一种方法是切图检测,虽然这种方法比较耗时且繁琐,但可以尝试使用。\[1\] 关于yolov5的检测耗时,根据引用\[2\]中提到的推理过程,可以根据不同的情况进行推理。如果使用的是pt格式的权重,可以通过设置参数来决定是否进行可视化,然后使用模型进行推理。如果使用的是onnx格式的权重,可以根据是否使用dnn来选择不同的推理方式。如果使用的是tensorflow模型,则可以根据具体的模型类型来进行推理。\[2\] 需要注意的是,当yolov5在图像中存在ground truth(即真实标签)但模型未能检测到对象时,这被称为False Negative(FN),即假阴性。\[3\]所以在评估yolov5的检测耗时时,需要考虑到这种情况。 #### 引用[.reference_title] - *1* [YOLOv5小目标切图检测](https://blog.csdn.net/qq_58355216/article/details/128318604)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [解决yolov5使用onnxruntime推理时耗时问题(cpu环境)](https://blog.csdn.net/athrunsunny/article/details/121241315)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [YOLOv5基础知识点——性能指标](https://blog.csdn.net/qq_50645064/article/details/125984978)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值