Почему мы должны ждать ввода / вывода?


28

Всегда было известно, что дисковые операции медленные, и мы знаем причины, по которым они медленные. Итак, вопрос здесь в том, почему мы должны ждать ввода-вывода или почему существует такая вещь, как IOWait и т. Д.?

Я имею в виду, что я заметил, что когда вы выполняете некоторые задачи ввода-вывода в фоновом режиме, ваш компьютер в основном работает намного медленнее, особенно я заметил, что при использовании Linux, если вы выполняете более длительные задачи ввода-вывода ОС становится практически непригодной для использования, пока они не будут завершены.

Действительно, я также нашел эту тему в статье, есть фрагмент:

Ожидание ввода / вывода составляет 12,1%. Этот сервер имеет 8 ядер (через cat / proc / cpuinfo). Это очень близко к (1/8 ядра = 0,125)

Так что в основном это означает, что это замедляет работу компьютера, почему? Я имею в виду ОК, теперь у нормального компьютера есть как минимум 2 ядра, иногда 4, а иногда их больше из-за гиперпоточности или чего-то в этом роде. Но теперь вопрос в том, почему процессор фактически должен оставаться там, практически ничего не делая, кроме как просто ждать ввода-вывода? Я имею в виду основную идею или архитектуру управления процессами, теперь я не знаю, несет ли ответственность за это ОС или она связана с аппаратной частью, но это должно быть сделано для того, чтобы процессор мог ждать или проверяйте регулярно, фактически выполняя множество других задач и возвращаясь к процессу ввода-вывода, только когда он будет готов. В самом деле, если это такая сложная задача, и процессору придется подождать, почему нет? Т то, что управляется аппаратно более эффективно, чем? Например, может существовать какой-то мини-процессор, который будет просто ждать его и доставлять небольшую часть данных в реальный процессор, как только он вернется в процесс, и поэтому процесс будет повторяться, а у нас не будет практически посвятить целое ядро ​​ЦП процессу копирования данных ... Или я буду тем, кто должен изобрести такие вещи и получить за это Нобелевскую премию? : S

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


41
«в то время как это могло бы просто сделать что-то еще» - такой как? Нужно работать с данными. Если эти данные не находятся в кэше ЦПУ L1, они должны извлечь их из кэша L2. Если нет в кеше L2, он должен извлечь из L3 (если он есть). Если его нет на встроенных кэшах, ему необходим доступ к основной памяти. Если нет в основной памяти ... необходимо получить доступ к жесткому диску.
Одед

39
Компьютер делает что-то еще; ядро блокирует поток до завершения операции ввода-вывода, позволяя другим потокам / процессам выполняться. Но если все ожидает на диске IO, то больше ничего не нужно делать.
Полковник тридцать два

6
Вам нужно дождаться, пока программы достигнут башни ввода / вывода и отправят вам своих фрисби!
Almo

1
@immibis Правильно! :)
Almo

2
Как правило, современные операционные системы делают то, на что вы жалуетесь, что они не делают - операции ввода-вывода направляются на соответствующее оборудование, а аппаратные средства генерируют прерывания, чтобы показать, что операции выполнены. Процессы, ожидающие ввода-вывода, обычно блокируются во время ожидания (это можно изменить). Если многие процессы ожидают ввода-вывода, и никакие другие процессы не имеют ничего для процессора, то делать нечего. Вы также можете оказаться в мемо-свопе Ада. Написание программ для эффективного использования процессора, памяти и ввода-вывода требует специальных навыков, и то, что еще работает, также влияет на то, что работает лучше всего.
nategoose

Ответы:


19

Описанные вами схемы ввода / вывода в настоящее время используются на компьютерах.

почему процессор на самом деле должен оставаться там, практически не делая ничего, кроме ожидания ввода-вывода?

Это самый простой из возможных методов ввода / вывода: запрограммированный ввод / вывод . Многие встроенные системы и микропроцессоры младшего и среднего уровня имеют только одну инструкцию ввода и одну инструкцию вывода. Процессор должен выполнить явную последовательность инструкций для каждого прочитанного или записанного символа.

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

Многие персональные компьютеры имеют другие схемы ввода / вывода. Вместо того, чтобы ждать в замкнутом цикле, пока устройство не будет готово ( ожидание занято ), ЦПУ запускает устройство ввода-вывода, запрашивая его, когда оно выполнит прерывание ( ввод-вывод, управляемый прерыванием ).

Хотя ввод-вывод, управляемый прерываниями, является шагом вперед (по сравнению с запрограммированным вводом-выводом), он требует прерывания для каждого передаваемого символа и стоит дорого ...

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

Решение многих проблем заключается в том, чтобы кто-то другой сделал эту работу! :-)

Контроллер / микросхема DMA (прямой доступ к памяти) позволяет запрограммировать ввод-вывод, но кто-то другой может это сделать!

При использовании DMA ЦП должен только инициализировать несколько регистров, и он может делать что-то еще, пока передача не будет завершена (и не будет создано прерывание).

Даже DMA не является полностью бесплатным: высокоскоростные устройства могут использовать много циклов шины для ссылок на память и ссылок на устройства ( кража циклов ), и процессор должен ждать (микросхема DMA всегда имеет более высокий приоритет шины).

Ожидание ввода / вывода составляет 12,1%. Этот сервер имеет 8 ядер (через cat / proc / cpuinfo). Это очень близко к (1/8 ядра = 0,125)

Я думаю, что это из: Понимание дискового ввода-вывода - когда вы должны беспокоиться?

Что ж, это не странно: система (mySQL) должна извлечь все строки, прежде чем манипулировать данными, и других действий нет.

Здесь нет проблем с архитектурой компьютера / ОС. Это как пример.

Самое большее, это может быть проблема настройки СУБД или проблема SQL-запроса (отсутствующий индекс, неверный план запроса, неправильный запрос ...)


24

Можно написать асинхронный ввод-вывод, в котором вы сообщаете ОС о необходимости чтения / записи диска и затем делаете что-то еще, а потом проверяете, выполнено ли это. Это далеко не новое. Более старый метод использует другой поток для ввода-вывода.

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

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

Когда вы вызываете блокирующую функцию чтения, вы знаете, что она не вернется, пока что-то не будет прочитано, и сразу же после того, как вы сможете начать ее обработку.

Типичный цикл чтения - хороший пример

//variables that the loop uses
char[1024] buffer;
while((read = fread(buffer, 1024, 1, file))>0){
    //use buffer
}

В противном случае вам нужно сохранить текущее состояние функции (обычно в форме обратного вызова + указатель userData) и передать его + идентификатор операции чтения обратно в select()цикл типа. Там, если операция завершена, она сопоставит идентификатор операции чтения с обратным вызовом + указатель данных и вызовет обратный вызов с информацией о выполненной операции.

void callback(void* buffer, int result, int fd, void* userData){
    if(result<=0){
    //done, free buffer and continue to normal processing
    }
    //use buffer

    int readID = async_read(fd, buffer, userData->buff_size);
    registerCallback(readId, callback, userData);
}

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


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

Реальная проблема заключается в том, что и жесткий диск, и процессор используют один и тот же канал для связи с ОЗУ ; шина памяти. И если вы не используете RAID, то для получения данных есть только один диск. Это усугубляется, если вы также используете графически интенсивное приложение, то связь с графическим процессором также будет мешать.

Другими словами, реальным узким местом, вероятно, является аппаратное обеспечение, а не программное обеспечение.


6
«Однако синхронный ввод-вывод против асинхронного ввода-вывода не является причиной общего замедления». Так почему же вы решили сосредоточиться на этой относительно продвинутой теме, когда речь идет об основах?
svick

1
Вероятно, вы должны упомянуть кое-что о DMA
Алек Тил

2
Интересный факт: на самом деле существует действительно старый механизм, который позволяет программам делать что-то еще во время ввода-вывода, не обращаясь к обратным вызовам; это называется темы .
user253751 9.09.15

2
Хорошее обсуждение плюсов / минусов синхронизации / асинхронного ввода-вывода. Но вы уверены, что это причина замедления? Обычно я нахожу, что замедление при большой нагрузке ввода-вывода происходит, во-первых, из-за плохо спроектированного программного обеспечения, или, если это не так, то из-за того, что система использует один медленный диск (т. Е. Не SSD), и все пытаются получить к нему доступ одновременно , Я бы обвинял узкое место в способности диска обслуживать запросы, прежде чем обвинять его в насыщении шины памяти. Вам нужно действительно высококачественное хранилище, чтобы насытить современную шину памяти.
Аромат

9

Верьте, что обработка других данных в ожидании ввода-вывода весьма упрощена, максимально приближена к максимально возможной. Когда вы видите, что ваш компьютер ожидает ввода-вывода только 12,1% времени, это означает, что он фактически выполняет множество других операций параллельно. Если бы ему действительно пришлось ждать ввода-вывода, не делая ничего другого, он бы ждал 99,9% времени, вот как медленно работает ввод-вывод.

Единственный способ сделать больше вещей параллельно - это предсказать, что пользователь, возможно, захочет делать дальше, и мы пока не очень хороши в таком прогнозе. Таким образом, если пользователь выполняет операцию, которая требует, чтобы определенный сектор считывался с жесткого диска, а этот сектор еще не попал в кэш, то ОС начнет очень долгий процесс чтения этого сектора, и она постараюсь узнать, есть ли что-нибудь еще сделать в это время. Если есть другой пользователь, которому нужен другой сектор, он также поставит этот запрос в очередь. В какой-то момент все запросы были поставлены в очередь, и мы ничего не можем сделать, кроме как дождаться первого из них, прежде чем мы сможем продолжить. Это просто факт жизни.

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

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

Видите ли, вот что происходит: ваш компьютер просто сидит 99,99% времени, ничего не делая. Когда вы даете ему что-то сделать, оно идет и делает это. Если при этом он должен ждать ввода / вывода, он сидит там и ждет. Если во время ввода / вывода ему нужно что-то еще, он тоже это делает. Но если ему не нужно ничего делать, кроме ввода / вывода, он должен сидеть там и ждать завершения ввода / вывода. Обойти это невозможно, кроме как зарегистрироваться в SETI @ Home.


Пример 12,1% был взят с веб-сайта, и пример был взят с сервера с 8 ядрами. Идея заключалась в том, что почти одно целое ядро ​​было зарезервировано только для этих операций, а остальные ядра могли делать что угодно и с 8 ядрами. Вы хорошо, но что, если у вас есть только одно ядро? : /
Артурас М

3
@ArturasM Либо вы неправильно поняли, что говорит сайт, либо автор сайта что-то не так понял. Компьютер с одним ядром будет тратить меньше времени на ожидание ввода-вывода (поскольку все задачи, которые не ожидают ввода-вывода и выполняются на других ядрах, когда одно ядро ​​находится в режиме ожидания), все должны будут выполняться на одном ядро). Ввод-вывод занимает определенное время, независимо от того, ожидаете вы этого или нет - наличие времени для его ожидания является признаком отсутствия отношения к этому времени.
Random832

6

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

Только в том случае, если нет другого потока или приложения, которое могло бы работать, вы на самом деле накапливаете время ожидания. В цитируемой вами статье (спасибо @manlio за ссылку) это так: у вас 12,1% ожидания против 87,4% бездействия, что означает, что одно ядро ​​ожидает завершения ввода-вывода, а остальные ничего не делают вообще. Дайте этой системе что-то сделать, желательно несколько штук, и процент ожидания должен снизиться.

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

при использовании Linux, если вы выполняете более длительные задачи ввода-вывода, ОС становится практически непригодной для использования, пока они не будут завершены.

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

Вы можете использовать такие инструменты, как, например, iotopчтобы увидеть, как емкость ввода / вывода распределяется между процессами, и ioniceустановить приоритеты ввода / вывода для процессов. Например, на настольном компьютере вы можете классифицировать всю массовую обработку данных в idleклассе планирования, так что в тот момент, когда какое-либо интерактивное приложение будет нуждаться в пропускной способности ввода / вывода, массовая обработка приостанавливается до тех пор, пока интерактивное приложение не будет завершено.


5

Это зависит от кода вашего приложения. Я полагаю, ваш код работает на Linux.

Вы могли бы использовать многопоточность (например, pthreads POSIX ), чтобы связанные с вычислениями потоки выполняли некоторые вычисления, в то время как другие связанные с IO потоки выполняют IO (и ожидают его). Ваше приложение может даже запускать несколько процессов, взаимодействующих с межпроцессным взаимодействием (IPC), см. Pipe (7) , fifo (7) , socket (7) , unix (7) , shm_overview (7) , sem_overview (7) , mmap (2) , eventfd (2) и читать Advanced Linux Programming и т.д ....

Вы можете использовать неблокирующий ввод-вывод , например, перейти O_NOBLOCKк open (2) и т. Д. И т. Д. И т. П .; тогда вам нужно будет опросить (2) и / или использовать SIGIO signal (7) ... и обработать EWOULDBLOCKошибку из read (2) и т. д ...

Вы можете использовать POSIX асинхронный ввод-вывод, см. Aio (7)

Для доступа к файлу вы можете дать подсказки кешу страниц , например, с помощью madvise (2) после mmap (2) и с помощью posix_fadvise (2) ; см. также чтение в Linux (2)

Но вы в конечном итоге достигнете некоторого аппаратного узкого места (шины, оперативной памяти и т. Д.). Смотрите также ionice (1)


1

Я добавляю другую точку зрения, чем другие, возможно, противоречивую:

Типичная проблема операционных систем Linux. Отставание конкретно (поиск "Linux Mouse Lag"). Windows не имеет этой проблемы. У меня двойная загрузка Windows 7 и Linux Mint. Даже при интенсивной работе с дисками в Windows, Windows чувствует себя гладко, мышь движется нормально. В Linux, напротив, это не ощущается, так что smoots и мышь иногда отстают даже во время обычного просмотра веб-страниц.

Вероятно, потому, что разные философии и истории этих двух систем. Windows с самого начала предназначена для обычных пользователей, в основном это графические операционные системы. А для пользователей Windows негладкое поведение системы и прекращение движения мыши являются сигналом того, что что-то не так. Так Microsofts программисты трудились, чтобы спроектировать всю систему, чтобы свести к минимуму случаи, когда система чувствует себя медленно. В противоположность Linux изначально не графическая система, десктоп здесь только стороннее дополнение. А Linux принципиально разработан для хакеров, использующих командную строку. Сделай вещи философии. Linux просто не предназначен для плавного поведения, чувства здесь не имеют значения.

Примечание: я не говорю, что Windows лучше, чем Linux, я говорю, что у них просто другая общая философия, которая в сложной среде может привести к различному поведению / ощущению этих систем на высоком уровне.


Отставание мыши в Linux, вероятно, можно избежать или уменьшить, если тщательно настроить систему (т. Е. Использовать nice& ioniceна голодных процессах). И я использую Linux, и почти никогда не испытывал такого отставания мыши в Linux (кроме случаев, когда я перегружал мой компьютер ...)
Василий Старинкевич

Кстати, Linux - это в основном серверная ОС.
Василий Старынкевич

Отмечу, что в Windows 7 я испытывал задержку пользовательского интерфейса и мыши даже в те времена, когда диспетчер задач и монитор ресурсов указывали на низкое использование памяти и низкую нагрузку на процессор и диск.
8bittree
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.