我想要一个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系统上运行代码)。任何帮助表示赞赏!
答案 0 :(得分:2)
您正在寻找timeout(1)。
如果你宁愿用C ++做(我认为脚本解决方案更好 - 让程序做一件事并且做得好,除非你的资源非常受限),那么经典的UNIX解决方案是alarm(2)(超时可以基于,但有几个较新的计时器)。
如果您想要在超时到期后执行除程序之外的其他操作,那么您需要为SIGALRM
信号设置处理程序。
答案 1 :(得分:1)
解决问题的好方法需要更深入地了解代码的准确程度以及执行计算的准确程度。这是一个可能的解决方案:
移动计算代码以在单独的线程中运行。您可以使用<thread>
创建线程。将addional标志参数传递给计算线程,或者只将其设置为全局(例如std::atomic<bool> 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
或其他答案建议的警报),那么您必须以某种方式跟踪部分结果,因为终止信号只会终止您的程序有机会打印当前结果。
答案 2 :(得分:0)
#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正在修改任何对象,您可能会遇到类似于非线程安全代码的问题。
答案 3 :(得分:0)
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)