2012-02-11 2 views
4

Для интенсивной вычислительной задачи я хочу ограничить время процессора, затраченное программой: если программа не найдет решение за заданный промежуток времени, я хочу, чтобы программа была прекращена. Вместо того, чтобы программа искала решение навсегда, оно должно прекратиться, если ничего не найдено. В случае, если речь идет о платформе, это для UNIX. Как это можно достичь?Как запустить программу за определенное количество времени?

+0

Вы пишете этот вопрос, потому что вопрос [Как запустить алгоритм в C++ в течение 40 секунд] (http://stackoverflow.com/q/9239909/1168156) был закрыт, прежде чем вы написали свой ответ там? Или почему вы это сделали? – LihO

+1

Зачем вам решать свой вопрос в течение трех минут? –

+0

Я в основном написал ответ на вопрос, о котором вы говорили, да. Я чувствовал, что это действительно интересная проблема, и я не мог найти ответ, используя описанную мной технику. Я понимаю, что первоначальный вопрос, возможно, был довольно кратким, но лично я не думаю, что это было неясным или неопределенным вообще. –

ответ

9

Другим решением POSIX это однопоточных и самодостаточным является использование сигналов:

#include <unistd.h> 
#include <csignal> 

std::sig_atomic_t volatile done = 0; 

void game_over(int) { done = 1; } 

int main() 
{ 
    std::signal(SIGALRM, game_over); 
    alarm(5); // this program will self-destruct in 5 seconds 

    while (!done) 
    { 
     do_my_thing(); // or whatever; make sure this returns frequently 
    } 
} 

(Это одна из очень немногих законных и ответственных применений volatile. Мы должны предотвратить компилятор от оптимизации вне while (!done) условна, и компилятор не видит, что done может мутировать, потому что он никогда не касался внутри тела цикла)

POSIX ди подсчитывает использование std::signal в пользу своих собственных, более мощных sigaction. Если вам интересно, обратитесь к руководству, но для простой цели повышения тревоги это решение кажется достаточным.

Если ваша программа не имеет точек прерывания вообще (то есть точек, на которых вы можете проверить done), то вы также можете позвонить abort() в обработчик сигнала.

+0

'alarm' измеряет секунды в реальном времени, задает« время процессора, затраченное программой ». Этот метод полезен на своем месте, но, вероятно, есть овалы вопроса, на который на самом деле отвечает этот ответ. –

+0

@SteveJessop: Вместо этого вы можете использовать 'setitimer' и обрабатывать' SIGVTALRM', если хотите виртуальное время процесса. –

5

Возможный подход - установить лимит процесса для требуемого времени. Ограничения UNIX, установленные с setrlimit(), наблюдаются средой времени выполнения, и они поддерживают как мягкий, так и жесткий предел. Когда достигается мягкий предел, запускается сигнал, который можно использовать, например. установить флаг, указывающий, что программа должна завершаться. Когда достигнут жесткий предел, программа должна быть завершена (хотя, похоже, это не работает на MacOS). Вот простой пример программы:

#include <sys/resource.h> 
#include <iostream> 
#include <signal.h> 

sig_atomic_t finished = false; 
void limit(int) 
{ 
    finished = true; 
} 

int main() 
{ 
    signal(SIGXCPU, limit); 
    struct rlimit limit; 
    limit.rlim_cur = 2; 
    limit.rlim_max = 3; 
    setrlimit(RLIMIT_CPU, &limit); 

    unsigned long long i(0); 
    while (++i && !finished) 
    { 
    } 
    std::cout << "i=" << i << " flag=" << std::boolalpha << bool(finished) << "\n"; 
} 
+2

Также обратите внимание, что вы можете сделать это из командной строки с помощью 'ulimit -t'. – SoapBox

+2

Я думаю, что вам разрешено изменять переменные с помощью белых списков внутри обработчика сигнала, и я не уверен, включен ли в список 'bool'. Тем не менее, 'sig_atomic_t', похоже, специально разработан для этой цели. –

+0

Вы правы: в обработчике сигнала гарантируется только изменение 'sig_atomic_t'. Я скорректировал код соответственно. Спасибо! –

Смежные вопросы