预先设置 C++ 代码的执行时间

Posted

技术标签:

【中文标题】预先设置 C++ 代码的执行时间【英文标题】:set execution time of a c++ code beforehand 【发布时间】:2016-05-31 21:15:20 【问题描述】:

我希望 C++ 代码运行一段特定的时间并在结束执行之前完成一条语句。例如,考虑以下有关程序执行的场景:

用 0 初始化一个计数器。如果执行时间等于 x 毫秒,则打印计数器的当前值,否则将计数器加 1。

上述任务可以通过编写类似的 C++ 代码来完成:

#include<iostream>
using namespace std;

int main()
    int c=0;
    while(true)
        /* do something to check the execution time, 
        if it is equal to x milliseconds print the value of c and exit*/

        c++;
    
    return 0;

实际上,我想比较两种用 C++ 实现的针对特定问题的优化算法,根据它们在相同时间执行时能给出多少最优解。

我在互联网上搜索,但无法得到我真正想要的。看起来有基于线程的解决方案,但除非非常必要,否则我不希望涉及线程。如果这个问题可以单独通过一些 C++ 特性来解决是有利的,但是如果一些调用 C++ 代码的 shell 脚本可以解决问题(我很可能在 Linux 系统上运行这些代码)。任何帮助表示赞赏!

【问题讨论】:

到目前为止你做了什么(除了描述你的作业),你在哪里卡住了? 你在寻找report progress of computation?的方法 #include &lt;chrono&gt; 你也可以试试 Qt 的插槽和信号的魔力:doc.qt.io/qt-4.8/signalsandslots.html @DYangu:如果我不能没有它,我会尝试。 【参考方案1】:

您正在寻找timeout(1)。

如果您更愿意在 C++ 中执行(我认为脚本解决方案更好——让程序做一件事并做好,除非您资源极度受限),那么经典的 UNIX 解决方案是 alarm(2) (虽然有几个较新的计时器,但可以基于哪个超时)。

如果您不想在超时到期后让程序死掉,那么您需要为SIGALRM 信号设置一个处理程序。

【讨论】:

timeout 实际上不符合要求,因为我希望在结束程序之前完成一些工作(正如您在上一条语句中正确指出的那样)。 alarm 看起来很完美。【参考方案2】:

旧的 alarms 和 signals 怎么样?

#include <unistd.h>
#include<iostream>
using namespace std;

void catchAlarm(int sig) 
    std::cerr << "You will now die, Mr Bond!!\n";
    exit(-1);


int main()
    int c=0;

    // Die in 2 seconds....
    signal(SIGALRM, catchAlarm);
    alarm(2); 

    while(true)
        /* do something to check the execution time, 
        if it is equal to x milliseconds print the value of c and exit*/
        c++;
    
    return 0;

编辑:上面的样板代码不允许您打印任何内部状态,但是由于您使用的是 C++14,您可以简单地在闭包中捕获它,然后使用关闭以挖掘内部结构,例如

#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <iostream>
#include <functional>    
using namespace std;

std::function<void()> myClosure; // The closure needs to be accessible to the alarm-function
void catchAlarm(int sig) 
    myClosure();
    exit(-1);


int main()
    int c=0;

    myClosure = [&]()->void
       std::cerr << "You will now die at age " << c << "\n";
    ;

    // Die in 2 seconds....
    signal(SIGALRM, catchAlarm);
    alarm(2);

    while(true)
        /* do something to check the execution time, 
        if it is equal to x milliseconds print the value of c and exit*/    
        c++;
    
    return 0;

但是(根据您的情况,这可能是大的或小的),信号是由内核触发的,它可能随时执行,包括编译器按顺序执行的代码的中途,但是现在不是因为你的闹钟中途打断了它。在您只打印内容的情况下,您可能会很好,因为最坏的情况会是一些有趣的输出,但如果您的 lambda 正在修改任何对象,您最终可能会遇到类似于非线程安全代码的问题。

【讨论】:

这看起来像我要找的东西!只有2点:1.标题alarm.h不起作用,我必须包含unistd.hsignal.h,2.我可以让函数catchAlarm打印c的最新值而不使@987654330 @一个全局变量? 当然,因为您使用的是 C++14,您可以在 lambda 函数中捕获有趣的东西,然后从信号处理程序中调用它,上面添加了一个示例 - 请注意,如果您使用gnu g++ 您需要在启用 lambda 函数之前将 g++ -std=c++14(或 -std=c++11)作为选项传递 在信号处理程序中允许您执行的操作极为有限。调用std::function 不是其中之一;也不会打印到std::cerr【参考方案3】:

为您的问题提供一个好的解决方案需要更深入地了解您的代码是如何组织的,以及您是如何执行计算的。这是一个可能的解决方案:

移动您的计算代码以在单独的线程中运行。您可以使用&lt;thread&gt; 创建线程。将额外的标志参数传递给计算线程,或者将其设为全局(例如std::atomic&lt;bool&gt; time_s_up)。您的代码应如下所示:

void compute(std::atomic<bool> &time_is_up)

    while (!time_is_up) 
        c++;
    

在主线程中,启动线程后,您可以使用睡眠或计时器,之后您可以:

int main()

    std::atomic<bool> time_s_up = false;
    std::thread t(compute, time_s_up);
    std::this_thread::sleep_for(std::chrono::milliseconds(100));
    time_s_up = true;
    t.join();

另一种解决方案(您实际想到的)也不错,但仅当 c++ 语句是更复杂的计算时,因此获取时间的调用仅代表少量开销:

// auto g_start = std::chrono::high_resolution_clock::now();
// g_time - total number of milliseconds to run
while (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::high_resolution_clock::now() - g_start).count() <= g_time) 
    some_complex_iteration_computations();

如果您使用另一种方法(例如 timeout 或其他答案建议的警报),那么您将不得不以某种方式跟踪部分结果,因为 kill 信号只会终止您的程序而没有机会打印当前结果。

【讨论】:

如果我离不开它们,我会尝试这些解决方案。我有点不愿意使用线程。 线程不是问题。我只是想避免更复杂,因为代码本身已经很复杂。 另外,如果我使用线程,我不清楚如何打印c 的最新值(在这种情况下)。 @SnehasishKarmakar,只需在while(!time_is_up)循环后添加打印语句【参考方案4】:

alarm 是一个很酷的解决方案。

在这里,我提供了一个愚蠢但简单的解决方案。

// c code
int main(int argc, char ** argv[]) 
    for (int i = 1; ; ++i) 
        // do something
        printf("%d\n", i);
    

然后以这种方式运行程序。

#!/bin/bash
./a.out &
sleep 2s && kill $(jobs -p)

【讨论】:

我并不需要这个。我希望程序在退出之前(超过给定的时间限制)打印一次最新结果。 @SnehasishKarmakar 只需添加 |尾巴 -1

以上是关于预先设置 C++ 代码的执行时间的主要内容,如果未能解决你的问题,请参考以下文章

使用 OpenGL 的 C++ 性能怪异

计算机二级考试(C++)复习

OJ网站程序员必备

C++怎么能间隔一定的时间执行指定的代码

如果执行嵌套的异步调用,则函数运行两次,否则运行一次。需要帮助来预先确定何时会发生这种情况

C++ vs C源代码的编译和执行时间