Snehasish Karmakar
Snehasish Karmakar

Reputation: 726

set execution time of a c++ code beforehand

I want a C++ code to run for a specific amount of time and complete a statement before ending the execution. For example, consider the following scenario regarding the execution of a program:

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.

The above task might be accomplished by writing a C++ code something like:

#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;
}

Actually, I want to compare two optimization algorithms implemented in C++ for a particular problem based on how much optimal solution they can give if executed for the same amount of time.

I searched on the Internet, but could not get what I actually want. It looks like thread based solutions are there, but I don't want threads to be involved unless it is extremely necessary. It is favourable if the problem can be solved by some C++ features alone, but it is okay if some shell script to invoke the C++ code would do the trick (I am likely to run the codes on Linux system). Any help is appreciated!

Upvotes: 0

Views: 2027

Answers (4)

Soren
Soren

Reputation: 14718

What about good old alarms and 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;
}

EDIT: the boilerplate code above does not allow you to print any of the internal state, however since you are using C++14 you can simply capture that in a closure, and then use the closure to dig into the internals, like

#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;
}

However (and this may be a big however or small one depending on your case), signals are triggered by the kernel, and it may execute at any time, including while half way through code which the compiler was executing sequentially, but now are not as your alarm interrupted it halfway though. In your case where your just print stuff, you may be fine as worst case would be some funny output, but if your lambda is modifying any object you may end up with problems that resemble that of non-thread safe code.

Upvotes: 1

pjincz
pjincz

Reputation: 2122

alarm is a cool solution.

Here I provide a stupid but easy solution.

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

then run program by this way.

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

Upvotes: 0

kaspersky
kaspersky

Reputation: 4117

A good solution for your problem requires more insight on how exactly your code is organized and how exactly you perform the computation. Here is a possible solution:

Move your computation code to run in a separate thread. You can use <thread> to create threads. Pass an addional flag argument to the computation thread, or just make it global (e.g. std::atomic<bool> time_s_up). Your code should look like:

void compute(std::atomic<bool> &time_is_up)
{
    while (!time_is_up) {
        c++;
    }
}

In the main thread, after you start your thread, you can use a sleep or timer, after which you do:

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();
}

Another solution (the one you actually thought of) is also good, but only when the c++ statements are more complex computations, so the calls to get the time would represent only a slight overhead:

// 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();
}

If you use another approach, (like timeout or alarms as suggested by other answers), then you'll have to somehow keep track of partial results, because the kill signal will just terminate your program without getting a chance to print the current result.

Upvotes: 1

Petr Skocik
Petr Skocik

Reputation: 60143

You're looking for timeout(1).

If you'd rather do it in C++ (I think the script solution is better -- let programs do one thing and do it well unless the you're extremely resource-constrained) then the classical UNIX solution is alarm(2) (which timeout could be based on, though there are a couple newer timers).

If you'll want to do something other than have the program die after the timeout expires, then you'll need to setup a handler for the SIGALRM signal.

Upvotes: 2

Related Questions