Книга: Алгоритмы для жизни: Простые способы принимать верные решения
Назад: Последствия приоритетного прерывания: контекстное переключение
Дальше: Объединение прерываний

Пробуксовка

Гейдж: Господин Цукерберг, я занимаю все ваше внимание?
Цукерберг: Нет, я уделяю вам лишь толику своего внимания.
Социальная сеть
Компьютер работает в режиме многозадачности посредством организации поточной обработки, которая подобна жонглированию мячами. Жонглер за раз подбрасывает вверх только один мяч, но при этом три других остаются в воздухе. Так и центральный процессор: в каждый момент времени он работает только над одной программой, но, переключаясь между программами с невероятной скоростью (за одну сотую секунды), он, кажется, успевает и проигрывать фильм, и искать информацию в интернете, и сообщать вам о поступившем письме – и все одновременно.
В 1960-е годы программисты задумались, как можно было бы автоматизировать процесс совместного использования ресурсов компьютера разными программами и пользователями. В воспоминаниях Питера Деннинга, ныне одного из ведущих экспертов в области компьютерной многозадачности (который тогда работал над своей докторской диссертацией в Массачусетском технологическом институте), это было удивительное время. Удивительное и полное неопределенности: «Как разделить основную память между множеством разных задач, когда одна из задач хочет расширить объем своей деятельности, другая, наоборот, – уменьшить, и они планируют взаимодействовать между собой, пытаясь украсть память, и тому подобное?.. Как управлять всем этим рядом взаимодействий? Никто понятия не имел».
Неудивительно, что, поскольку исследователи и сами не вполне понимали, что делают, они столкнулись с препятствиями. И одно из них особенно привлекло внимание ученых. Как объяснял Деннинг, при определенных условиях неожиданная проблема «появляется, если вы добавите еще больше задач в эту многозадачную смесь. В некотором роде вы проходите через критический порог. Невозможно предсказать его появление, но вы сразу это поймете, когда внезапно система начнет умирать».
Снова представим жонглера. Пока один мяч находится в воздухе, у жонглера есть достаточно времени, чтобы подбросить вверх остальные. Но если жонглер берет еще один лишний мяч, с которым он уже не успевает справиться? Он уронит не этот мяч, он уронит все. Вся система в буквальном смысле слова рушится. Как комментировал такую ситуацию Деннинг, «присутствие одной лишней программы привело к полному краху работы системы… Очевидная разница между этими двумя случаями вначале заставляет игнорировать интуитивное ощущение, что по мере добавления новых программ в перегруженную основную память начинается постепенная деградация деятельности компьютера». А вместо этого происходит катастрофа.
И если в случае с жонглером мы понимаем, что он просто не рассчитал силы и не справился, что может стать причиной такого финала для машины?
Здесь теория планирования пересекается с теорией кеширования. Вся суть кеша заключается в том, чтобы держать рабочий набор необходимых элементов в свободном доступе. Один из способов – хранить информацию, которую в данный момент использует компьютер, в быстрой памяти, а не на медленном винчестере. Но, если задаче требуется держать в поле зрения так много нюансов, что эта информация уже не помещается в объеме быстрой памяти, компьютеру приходится постоянно подкачивать данные в память и отправлять обратно на винчестер, вместо того чтобы выполнять реальную работу. Более того, когда вы переключаетесь между задачами, новое активное задание может пытаться освободить место для своего рабочего набора, вытесняя сегменты других рабочих наборов из памяти. Следующее задание, активированное вновь, будет снова возвращать части своего рабочего набора с жесткого диска и заталкивать их обратно в память, занимая места других наборов. Такая ситуация – когда задачи крадут место друг у друга – может и дальше усугубляться в системах, где существует иерархия кеша между процессором и памятью. По словам Питера Зилистра, одного из разработчиков диспетчера операционной системы Linux, «кеши уже достаточно разогреты для текущей загрузки, и, когда вы переключаетесь с задачи на задачу, вы в значительной мере лишаете сил все кеши. И это больно». В крайнем случае программа может работать ровно столько, сколько нужно, чтобы закачать необходимые элементы в память, прежде чем уступить место другой программе, которая будет активна до тех пор, пока не перепишет все эти элементы.
Это и есть пробуксовка: система работает на полную катушку, но ни одна задача не решается. Деннинг впервые обнаружил этот феномен в контексте управления памятью, но сегодня программисты используют термин «пробуксовка» для обозначения практически любой ситуации, когда система отказывает, будучи окончательно перегруженной метаработой. Работа буксующего компьютера не приостанавливается постепенно. Она просто врезается в стену на полном ходу. «Реальная» работа в какой-то момент становится равной нулю, что также означает, что выбраться будет практически невозможно.
Пробуксовка – типичное состояние и для человека. Вы когда-нибудь испытывали желание немедленно прекратить делать все, чтобы просто получить возможность записать все, что вам необходимо сделать, но у вас не было на это времени? В этот момент вы начинали буксовать. Причина здесь та же, что и у компьютеров: каждая задача – это привлечение наших ограниченных когнитивных ресурсов. Когда необходимость помнить обо всем, что необходимо сделать, занимает все наше внимание или выстраивание очередности всех заданий занимает все время, которое мы должны потратить на их решение, или же ход наших мыслей постоянно прерывается, не позволяя нам обратить их в действия, наступает что-то вроде паники или паралича от гиперактивности. Это пробуксовка, и компьютеры о ней наслышаны.
Если вам доводилось бороться с буксующей системой (или если вы сами бывали в таком состоянии), то, возможно, вам будет интересно, какой выход из подобной ситуации предлагает компьютерная наука. В 1960 году в своей знаковой работе по теме Деннинг отметил, что болезнь легче предупредить, чем лечить. Самый простой способ профилактики – увеличение памяти: например, достаточное количество ОЗУ поможет уместить в памяти сразу все рабочие наборы запущенных программ и сократить время, необходимое на переключение контекстов. Но такие превентивные меры не помогут вам, если вы уже начали буксовать. Более того, когда речь заходит о человеческом внимании, мы явно можем использовать только то, что у нас есть, и не более.
Другой способ предотвратить пробуксовку до ее наступления – научиться говорить «нет». В частности, Деннинг агитировал за то, что система должна попросту отказывать в добавлении новой задачи, если ей не хватает памяти, чтобы разместить очередной рабочий набор. Эти меры способны предотвратить пробуксовку машин, и это разумный совет для всех угощаемых, чья тарелка уже полна. Но вместе с тем такой подход может показаться непозволительной роскошью для тех из нас, кто чувствует себя уже перегруженным – или неспособным сдерживать все, что на него валится.
В таких случаях, очевидно, нет возможности работать усердней, но вы всегда можете работать… хуже. Помимо памяти, одним из самых больших источников метаработы при контекстном переключении служит само действие выбора дальнейших действий. Временами эти действия тоже утягивают компьютер в трясину метаработы.
Если наш почтовый ящик заполнен n входящими сообщениями, то, как мы помним из теории сортировки, многократный просмотр писем с целью обнаружить самое важное из них, требующее немедленного ответа, потребует от нас выполнения O(n2) операций – n просмотров n писем. Это значит, что, обнаружив утром в почтовом ящике в три раза больше писем, чем обычно, вы потратите в девять раз больше времени на работу с ним. Более того, просматривая почту, вы поневоле подкачиваете каждое сообщение в свой мозг, одно за другим, прежде чем ответите хоть на одно из них: стопроцентный способ заставить ваш разум буксовать.
В таком состоянии вы не можете двигаться дальше, поэтому даже выполнять задачи в неверном порядке лучше, чем не делать ничего. Вместо того чтобы отвечать на самые важные сообщения в первую очередь (что требует оценки масштаба ситуации, которая займет у вас больше времени, чем сам ответ), возможно, вам стоит сделать шаг в сторону, минуя зыбь квадратичного времени, и отвечать на письма в произвольном порядке или в том, в котором они появляются на вашем экране. Размышляя в том же ключе, рабочая группа Linux несколько лет назад заменила свой диспетчер новым, который хоть и не был так силен в вычислении очередности процессов, но сполна компенсировал это скоростью вычисления. Если для вас все еще важно сохранить приоритеты, есть и другие, гораздо более интересные сделки, на которые вы можете пойти, чтобы вернуть себе продуктивность.
Назад: Последствия приоритетного прерывания: контекстное переключение
Дальше: Объединение прерываний