预先设置 C++ 代码的执行时间
set execution time of a c++ code beforehand
我想要一个 C++ 代码 运行 一段特定的时间,并在结束执行之前完成一条语句。例如,考虑以下有关程序执行的场景:
Initialise a counter with 0. If the execution time is equal to x milliseconds then print the current value of the counter, else increment the counter by 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++ 功能解决,这是有利的,但如果一些 shell 调用 C++ 代码的脚本可以解决问题(我很可能 运行 Linux系统)。感谢您的帮助!
一个好的问题解决方案需要更深入地了解代码的组织方式以及计算的执行方式。这是一个可能的解决方案:
将您的计算代码移至 运行 的单独线程中。您可以使用 <thread>
创建线程。将附加标志参数传递给计算线程,或将其设为全局(例如 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
或其他答案建议的警报),那么您将不得不以某种方式跟踪部分结果,因为 kill 信号只会终止您的程序而不会有机会打印当前结果。
您正在寻找 timeout(1)。
如果您更愿意使用 C++(我认为脚本解决方案更好——让程序做一件事并把它做好,除非您的资源极其有限),那么经典的 UNIX 解决方案是 alarm(2)(虽然有几个更新的计时器,但可以基于哪个超时)。
如果您不想在超时到期后让程序死掉,还想做其他事情,那么您需要为 SIGALRM
信号设置一个处理程序。
#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 正在修改任何对象,你可能最终会遇到类似于非线程安全代码的问题。
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)
我想要一个 C++ 代码 运行 一段特定的时间,并在结束执行之前完成一条语句。例如,考虑以下有关程序执行的场景:
Initialise a counter with 0. If the execution time is equal to x milliseconds then print the current value of the counter, else increment the counter by 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++ 功能解决,这是有利的,但如果一些 shell 调用 C++ 代码的脚本可以解决问题(我很可能 运行 Linux系统)。感谢您的帮助!
一个好的问题解决方案需要更深入地了解代码的组织方式以及计算的执行方式。这是一个可能的解决方案:
将您的计算代码移至 运行 的单独线程中。您可以使用 <thread>
创建线程。将附加标志参数传递给计算线程,或将其设为全局(例如 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
或其他答案建议的警报),那么您将不得不以某种方式跟踪部分结果,因为 kill 信号只会终止您的程序而不会有机会打印当前结果。
您正在寻找 timeout(1)。
如果您更愿意使用 C++(我认为脚本解决方案更好——让程序做一件事并把它做好,除非您的资源极其有限),那么经典的 UNIX 解决方案是 alarm(2)(虽然有几个更新的计时器,但可以基于哪个超时)。
如果您不想在超时到期后让程序死掉,还想做其他事情,那么您需要为 SIGALRM
信号设置一个处理程序。
#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 正在修改任何对象,你可能最终会遇到类似于非线程安全代码的问题。
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)