线程:如何在C或C++中精确计算算法的执行时间(函数的持续时间)

Threads: How to calculate precisely the execution time of an algorithm (duration of function) in C or C++?

本文关键字:算法 计算 执行时间 持续时间 函数 C++ 线程      更新时间:2023-10-16

有一种简单的方法可以计算这里描述的任何函数的持续时间:如何在C++中计算代码段的执行时间

start_timestamp = get_current_uptime();
// measured algorithm
duration_of_code = get_current_uptime() - start_timestamp;

但是,它不允许获得明确的持续时间,因为执行的一些时间其他线程将包括在测量的时间中。

所以问题是:如何考虑代码在其他线程中花费的时间?OSX代码首选项。虽然查看windows或linux代码也很好。。。

upd:理想吗?代码的概念

start_timestamp = get_this_thread_current_uptime();
// measured algorithm
duration_of_code = get_this_thread_current_uptime() - start_timestamp;

我很抱歉地说,在一般情况下,没有办法做你想做的事。您正在寻找最坏情况下的执行时间,有几种方法可以很好地近似它,但没有完美的方法,因为WCET相当于Halting问题。

如果您想排除在其他线程中花费的时间,那么您可以在输入要测量的函数时禁用任务上下文切换。这取决于RTOS,但一种可能性是将当前线程的优先级提高到最大值。如果这个线程是最高优先级,那么其他线程将无法运行。记住在函数结束时再次重置线程优先级。然而,这种测量可能仍然包括在中断中花费的时间。

另一个想法是完全禁用中断。这可能会从您的测量中删除其他线程和中断。但是在中断被禁用的情况下,定时器中断可能无法正常工作。因此,您需要适当地设置硬件计时器,并依靠计时器的计数器值寄存器(而不是计时器中断产生的任何时间值)来测量时间。还要确保您的函数不会调用任何允许上下文切换的RTOS例程。记住在函数结束时恢复中断。

另一个想法是多次运行该函数,并记录多次测量的最短持续时间。较长的持续时间可能包括在其他线程中花费的时间,但最短的持续时间可以只是没有其他线程的函数。

另一个想法是在进入时设置GPIO引脚,并在退出功能时清除它。然后用示波器(或逻辑分析仪)监测GPIO引脚。使用示波器测量GPIO引脚为高电平时的周期。为了减少在其他线程中花费的时间,您需要修改选择要运行的线程的RTOS调度程序例程。当另一个线程运行时,清除调度程序中的GPIO引脚,并在调度程序返回到函数的线程时进行设置。您还可以考虑清除中断处理程序中的GPIO引脚。

您的问题完全取决于操作系统。你能做到这一点的唯一方法是从操作系统那里得到保证,它不会抢占你的进程来执行其他任务,据我所知,这在大多数消费者操作系统中是不可能的。

RTOS通常提供了实现这一点的方法。使用Windows CE,任何以优先级0(理论上)运行的程序都不会被另一个线程抢占,除非它调用了需要另一个螺纹提供服务的函数/os-api/库。

我对OSx不是很熟悉,但看过文档后,OSx是一个"软"实时操作系统。这意味着,从技术上讲,你想要的东西是无法保证的。操作系统可能会决定有比您的流程更重要的"事情"需要完成。

然而,OSX允许您指定实时进程,这意味着操作系统将尽一切努力满足您的请求,不被中断,并且只有在认为绝对必要的情况下才会这样做。

Mac OS X调度文档提供了如何设置实时线程的示例

OSX不是RTOS,因此问题的标题和标记错误。

在真正的RTOS中,您可以锁定调度程序、禁用中断或将任务提升到最高优先级(如果其他任务共享该优先级,则禁用循环调度)以防止抢占-尽管只有禁用中断才能真正防止中断处理程序的抢占。在GPOS中,即使它有优先级方案,通常也只控制在循环调度中允许进程的时隙数量,而不会阻止抢占。

一种方法是进行多次重复测试,并取获得的最小值,因为这可能是发生最少抢占的值。这也将有助于将流程设置为最高优先级,以最大限度地减少抢占次数。但请记住,在GPOS上,来自鼠标、键盘和系统时钟等设备的许多中断都会发生,并且会消耗很小的时间(可能可以忽略不计)。