Чрезвычайно загруженный процессор будильник

РЕДАКТИРОВАТЬ:

Я хотел бы поблагодарить всех вас за быстрые ответы ^^ Sleep() работает так, как задумано, и эта программа больше не пожирает мой процессор! Я оставлю этот вопрос как есть, но чтобы все знали, что проблема с процессором решена целесообразно и профессионально :D

Кстати, я обязательно позабочусь о том, чтобы микрооптимизация была сведена к минимуму перед лицом более крупных и важных проблем!

================================================================================

По какой-то причине моя программа, консольный будильник, который я сделал для смеха и практики, чрезвычайно интенсивно использует процессор. Он потребляет около 2 МБ ОЗУ, что уже немало для такой маленькой программы, но время от времени он опустошает мой процессор с более чем 50% ресурсов.

Большую часть времени моя программа ничего не делает, кроме обратного отсчета секунд, поэтому я предполагаю, что именно эта часть моей программы вызывает такую ​​большую нагрузку на мой процессор, хотя я не знаю, почему. Если это так, не могли бы вы порекомендовать способ сделать его меньше или, возможно, библиотеку, которую можно использовать вместо этого, если проблема не может быть легко решена?

/* The wait function waits exactly one second before returning to the *
 * called function.                                                   */     
 void wait( const int &seconds )
 {
 clock_t endwait; // Type needed to compare with clock()
 endwait = clock() + ( seconds * CLOCKS_PER_SEC ); 

 while( clock() < endwait ) {} // Nothing need be done here.
 }

Если кто-то просматривает CPlusPlus.com, это настоящая копия/вставка функции clock(), которую они написали в качестве примера для clock(). Почему комментарий //Nothing need be done here такой тусклый. Я еще не совсем уверен, что именно делает clock().

Остальная часть программы вызывает две другие функции, которые активируются только каждые шестьдесят секунд, в противном случае возвращаются к вызывающей стороне и отсчитывают еще одну секунду, поэтому я не думаю, что это слишком интенсивно для ЦП, хотя я не знаю, это моя первая попытка при оптимизации кода.

Первая функция — это очистка консоли с помощью system("cls"), что, я знаю, очень, очень медленно и не очень хорошая идея. Я буду менять этот постпоспешность, но, поскольку он активируется только каждые 60 секунд и наблюдается заметный всплеск задержки, я знаю, что большую часть времени проблема не в этом.

Вторая функция перезаписывает содержимое экрана с обновленным оставшимся временем также только каждые шестьдесят секунд.

Я отредактирую функцию, которая вызывает ожидание, очистку экрана и отображение, если будет ясно, что проблема не в этой функции. Я уже пытался ссылаться на большинство переменных, чтобы они не копировались, а также избегал endl, так как я слышал, что это немного медленно по сравнению с \n.


person IAE    schedule 26.04.2010    source источник
comment
Кроме того, действительно избегайте микрооптимизаций, таких как замена std::endl на '\n', пока вы не поймете, что на самом деле делает ваш код медленным или загружает процессор. Попытки исправлять и возиться с крошечными несущественными вещами, когда есть гораздо более серьезные проблемы, которые нужно решить, только делают ваш код все более нечитаемым и неподдерживаемым.   -  person Tyler McHenry    schedule 27.04.2010


Ответы (6)


Этот:

while( clock() < endwait ) {} 

Не "ничего не делает". Конечно, внутри цикла while ничего не делается, но проверка clock() < endwait не бесплатна. На самом деле, она выполняется снова и снова настолько быстро, насколько это возможно для вашей системы, что увеличивает вашу нагрузку (вероятно, на 50%, потому что у вас двухъядерный процессор, а это однопоточная программа). который может использовать только одно ядро).

Правильный способ сделать это — просто удалить всю эту функцию wait и вместо этого просто использовать:

sleep(seconds);

Что фактически остановит выполнение вашей программы в течение указанного количества секунд и не будет потреблять процессорное время при этом.

В зависимости от вашей платформы вам потребуется включить <unistd.h> (UNIX и Linux) или <windows.h> (Windows) для доступа к этой функции.

person Tyler McHenry    schedule 26.04.2010
comment
А в Windows это Sleep. - person GManNickG; 27.04.2010
comment
Кроме того, в *nix аргумент перехода в спящий режим указывается в секундах, а в Windows — в миллисекундах. - person Nathan Ernst; 27.04.2010

Это называется занятым ожиданием. ЦП крутится на полной скорости в цикле while. Вы должны заменить цикл while простым вызовом sleep или usleep.

Я не знаю о 2 МБ, особенно ничего не зная о программе в целом, но это действительно не то, на что нужно обращать внимание. Возможно, библиотеки времени выполнения C так много поглощают при запуске из соображений эффективности.

person Marcelo Cantos    schedule 26.04.2010
comment
Даже при использовании sleep() это все еще называется ожиданием занятости, но оно определенно решит вашу проблему с процессором. - person Neil; 27.04.2010
comment
А? Спящий режим в течение указанного интервала (когда вы пытаетесь дождаться указанного интервала, а не определенного условия) не является ожиданием занятости. - person Tyler McHenry; 27.04.2010
comment
@ neilwhitaker1, как вы понимаете термин занятое ожидание? sleep усыпляет вызывающий поток (отсюда и название) и пробуждает его, когда приходит время; в этом нет ничего занятого. - person Marcelo Cantos; 27.04.2010
comment
Я думаю, что комментарий @neil был основан на добавлении вызова sleep(n) в цикл while, где n меньше, чем seconds (как ответ Пера), а не на уничтожении всей функции wait и использовании sleep вместо нее. - person Nick Meyer; 27.04.2010
comment
+1, Ник; Спасибо что подметил это. Я скорректировал ответ, чтобы избежать этой возможной путаницы. - person Marcelo Cantos; 27.04.2010

Проблема с процессором решена хорошо. Что касается проблемы с памятью, неясно, что на самом деле измеряют 2 МБ. Это может быть общий размер всех библиотек, сопоставленных с адресным пространством вашего приложения.

Запустите и проверьте программу, которая просто содержит

int main() { for (;;) }

чтобы оценить базовое использование памяти на вашей платформе.

person Potatoswatter    schedule 26.04.2010
comment
Странный результат: эта программа использует больше ресурсов, чем мои часы, что невозможно. Любая причина, почему это может быть? - person IAE; 27.04.2010
comment
@soul: возможно, потому что исходная программа вызывает системный вызов, когда вызывает clock, и ядро ​​​​использует это как возможность заснуть. - person Potatoswatter; 27.04.2010
comment
Вам нужна точка с запятой после for. - person GManNickG; 27.04.2010

Здесь вы вращаетесь без уступок, поэтому неудивительно, что вы сжигаете циклы процессора.

Бросьте

  Sleep(50);

в цикле пока.

person 500 - Internal Server Error    schedule 26.04.2010

Цикл while держит процессор занятым всякий раз, когда ваш поток получает квант времени для выполнения. Если все, что вы хотите, это подождать определенное время, вам не нужен цикл. Вы можете заменить его одним вызовом sleep, usleep или nanosleep (в зависимости от платформы и степени детализации). Они приостанавливают выполнение потока до тех пор, пока не истечет указанное вами количество времени.

В качестве альтернативы вы можете просто отказаться (уступить) оставшемуся временному интервалу, вызвав Sleep(0) (Windows) или sched_yield() (Unix/Linux/и т. д.).

Если вы хотите понять точную причину этой проблемы, прочитайте о планировании.

person jweyrich    schedule 26.04.2010

в то время как ( часы () ‹ endwait ) { Sleep (0); } // переход к потокам с равным приоритетом

person renick    schedule 26.04.2010
comment
Просто примечание: Sleep(0) зависит от Windows. - person jweyrich; 27.04.2010