Чому ми повинні чекати вводу-виводу?


28

Завжди було відомо, що операції з диском повільні, і ми знаємо причини, чому вони повільні. Тож питання тут, чому нам доводиться чекати вводу-виводу або чому існує таке поняття, як IOWait тощо?

Я маю на увазі, що я помітив, що коли ви виконуєте якісь завдання вводу-виводу у фоновому режимі, ваш комп'ютер, в основному, стає набагато повільніше, особливо я помітив, що при використанні Linux, якщо ви виконуєте кілька довших завдань вводу / виводу , ОС стає майже непридатним до їх завершення.

Дійсно, я також знайшов цю тему в статті, є фрагмент:

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

Таким чином, це означає, що це уповільнює роботу комп'ютера багато, чому це так? Я маю на увазі гаразд, зараз у нормального комп’ютера є щонайменше 2 ядра, іноді 4, а іноді їх більше через гіперточення чи щось подібне. Але тепер питання полягає в тому, чому процесору насправді доводиться залишатися там, практично не роблячи нічого іншого, як просто чекати IO? Я маю на увазі основну ідею або архітектуру управління процесом, тепер я не знаю, чи відповідальна за це ОС, чи це зводиться до апаратної частини, але процесор повинен зробити можливість чекати або регулярно перевіряйте, фактично виконуючи безліч інших завдань і повертаючись до процесу вводу-виводу тільки тоді, коли він буде готовий. Дійсно, якщо це таке непросте завдання, і процесор повинен буде почекати, чому ж t що ефективніше керувати обладнанням? Як, наприклад, може бути якийсь міні-процесор, який би просто дочекався його і доставив невелику частину даних на реальний процесор, як тільки він повернеться до процесу, і таким чином процес повториться, і у нас не було б практично присвятити ціле ядро ​​процесора для процесу копіювання даних ... Або я був би тим, хто повинен вигадати подібні речі та отримати нобелівський приз за це? : S

Тепер гаразд, я дійсно ставлю це зараз з точки зору спостерігачів, і я дійсно не заглиблювався в цю тему, але я дійсно не розумію, чому процесор повинен працювати зі швидкістю жорсткого диска, хоча це може просто зробіть щось інше і поверніться до жорсткого диска, як тільки він буде готовий. Ідея полягає не в тому, щоб пришвидшити додаток, якому потрібна операція вводу-виводу або процес копіювання, або інше, а ідея полягає в тому, щоб мінімально впливати на споживання процесора під час виконання цієї операції, щоб ОС могла використовувати його для інших процесів та користувача не довелося б відчувати загальний комп’ютерний відставання під час деяких операцій з копіювання ...


41
"в той час як це може просто зробити щось інше" - наприклад? Потрібно працювати з даними. Якщо цих даних немає в кеш-пам'яті L1 процесора, його потрібно отримати з кешу L2. Якщо немає в кеші L2, він повинен отримати з L3 (якщо він є). Якщо він взагалі не знаходиться в кеш-файлах, йому потрібно отримати доступ до основної пам'яті. Якщо немає в основній пам'яті ... потребує доступу до жорсткого диска.
Одід

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

6
Вам потрібно дочекатися, коли програми дістануться до вежі вводу-виводу та надішлють вам свої фризбі!
Алмо

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

2
Зазвичай сучасні ОС роблять те, на що ви скаржаться, що вони не роблять - операції вводу-виводу надсилаються до відповідного обладнання, а апаратне забезпечення генерується перериваннями для означення того, що операції виконані. Процеси, які чекають на IO, зазвичай блокуються під час очікування (це можна змінити). Якщо багато процесів очікують на IO, і жоден інший процес не має нічого робити для процесора, то робити не багато. Ви також можете потрапити в пекло. Написання програм для ефективного використання процесора, пам'яті та вводу-виводу вимагає спеціальних навичок, а те, що ще працює, також впливає на те, що найкраще працює.
nategoose

Відповіді:


19

Схеми вводу / виводу, які ви описуєте, зараз використовуються в комп'ютерах.

чому процесор насправді повинен залишатися там, практично не роблячи нічого іншого, як просто чекати IO?

Це найпростіший можливий метод вводу / виводу: запрограмований введення / виведення . У багатьох вбудованих системах та мікропроцесорах низького та кінцевого рівня є лише одна інструкція на вході та одна інструкція на виході. Процесор повинен виконати чітку послідовність інструкцій для кожного прочитаного чи записаного символу.

але процесор повинен чекати або регулярно перевіряти, фактично виконуючи безліч інших завдань і повертаючись до IO процесу лише тоді, коли він буде готовий

Багато персональних комп'ютерів мають інші схеми вводу / виводу. Замість того, щоб чекати в щільному циклі, щоб пристрій підготувався ( зайнятий очікуванням ), процесор запускає пристрій вводу-виводу з проханням створити переривання, коли це зроблено ( переривання, кероване вводу-виводу ).

Хоча введення / виведення, кероване перериванням, - це крок вперед (порівняно з запрограмованим входом / виводом), він вимагає переривання для кожного переданого символу, і це дорого ...

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

Рішення багатьох проблем полягає в тому, щоб хтось інший виконував роботу! :-)

Контролер / мікросхема DMA (прямий доступ до пам'яті) дозволяє запрограмувати введення / виведення, але дозволити це зробити хтось інший!

З DMA CPU повинен ініціалізувати лише кілька регістрів, і він може робити щось інше, поки передача не буде завершена (і не буде здійснено переривання).

Навіть DMA не є абсолютно безкоштовним: високошвидкісні пристрої можуть використовувати безліч циклів шини для посилань на пам'ять та посилання на пристрої ( крадіжка циклу ), а процесор повинен чекати (чіп DMA завжди має більш високий пріоритет шини).

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

Я думаю, що це з: Розуміння дискового вводу / виводу - коли ви повинні турбуватися?

Ну, це не дивно: система (mySQL) повинна вибирати всі рядки перед тим, як маніпулювати даними, а інших дій немає.

Тут немає проблеми з архітектурою комп’ютера / ОС. Це лише як встановлений приклад.

Щонайбільше це може бути проблема налаштування RDBMS або проблема запиту SQL (відсутній індекс, поганий план запитів, поганий запит ...)


24

Можна написати асинхронний IO там, де ви скажете ОС відправити диск для читання / запису, а потім перейдіть робити щось інше, а потім перевірити, чи це зроблено. Це далеко не нове. Старіший метод - це використовувати інший потік для IO.

Однак це вимагає, щоб у вас було щось робити під час виконання цього читання, і вам не дозволять торкатися буфера, який ви передали для отримання результату.

Це також набагато простіше програмувати, якщо ви припускаєте, що все блокує 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);
}

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


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

Справжня проблема полягає в тому, що і жорсткий диск, і процесор використовують один і той же канал для зв'язку з ОЗУ ; шина пам'яті. І якщо ви не використовуєте RAID, для отримання даних є лише один диск. Це погіршується, якщо ви також використовуєте інтенсивний графічний додаток, тоді спілкування з GPU також буде перешкоджати.

Іншими словами, справжнє вузьке місце, ймовірно, є в апаратному, а не в програмному забезпеченні.


6
"Однак синхронний IO проти асинхронного IO не є причиною загального уповільнення." То чому ви вирішили зосередитись на цій відносно розвиненій темі, коли питання стосується основ?
svick

1
Ви, напевно, повинні згадати щось про DMA
Alec Teal

2
Забавний факт: насправді існує справді старий механізм, який дозволяє програмам робити щось інше під час виконання вводу-виводу, не маючи справи з зворотними викликами; це називається нитками .
користувач253751

2
Гарне обговорення плюсів / мінусів синхронізації / асинхронізації IO. Але ви впевнені, що це причина уповільнення? Як правило, я вважаю, що сповільнення роботи під великим навантаженням вводу-виводу спочатку відбувається через погано зорієнтоване програмне забезпечення, або коли це не так, тому що система використовує один, повільний диск (тобто не-SSD), і все намагається отримати доступ до нього одночасно . Я б звинувачував вузьке вузьке місце в можливості диска обслуговувати запити, перш ніж звинуватити його в насиченні шини пам'яті. Для насичення сучасної шини пам’яті вам потрібне дійсно високого класу пам’яті.
aroth

9

Будьте впевнені, що обробка інших матеріалів під час очікування вводу-виводу є досить обтічною, наближеною до максимально спрощеної. Коли ви бачите, що ваш комп'ютер чекає вводу / виводу лише 12,1% часу, це означає, що він насправді робить багато інших речей паралельно. Якщо б дійсно довелося чекати вводу / виводу, не роблячи нічого іншого, воно чекало б 99,9% часу, ось так повільно відбувається введення / виведення.

Єдиний спосіб зробити більше справ паралельно - передбачити, що користувач може захотіти зробити далі, і ми ще не дуже хороші в такому роді прогнозу. Отже, якщо користувач виконує операцію, яка вимагає зчитувати з жорсткого диска певний сектор, і цей сектор вже не трапляється в кеш, тоді ОС розпочне дуже довгий процес зчитування цього сектору, і він спробуємо побачити, чи є ще щось робити в середній час. Якщо є інший користувач, який бажає іншого сектору, він також поставить в чергу цей запит. У якийсь момент усі запити були поставлені в чергу, і ми нічого не можемо зробити, але чекати, коли перший із них буде задоволений, перш ніж ми зможемо продовжити. Це просто факт життя.

Редагувати:

Пошук вирішення проблеми, як робити інші речі під час виконання вводу-виводу, було б захоплюючим подвигом, оскільки це водночас було б вирішенням проблеми, як робити інші речі в режимі очікування. Дивовижний подвиг, який би був, адже це означало б, що ви знайдете роботу для свого комп’ютера, тоді як його немає.

Розумієте, ось що відбувається: ваш комп'ютер просто сидить 99,99% часу, нічого не роблячи. Коли ви даєте йому щось робити, він іде і робить це. Якщо при цьому йому доведеться чекати вводу-виводу, він сидить там і чекає. Якщо під час вводу / виводу щось ще потрібно зробити, він теж робить це. Але якщо у неї немає нічого іншого, крім вводу / виводу, тоді він повинен сидіти там і чекати завершення вводу / виводу. Не обійти іншого способу, крім реєстрації в SETI @ Home.


Добре, що 12,1% приклад був із веб-сайту, а приклад взятий із сервера з 8 ядрами, ідея полягала в тому, що майже одне ядро ​​було просто зарезервоване для цих операцій, впевнені, що інші ядра вільні робити що-небудь і з 8 ядрами у вас добре, але що робити, якщо у вас є лише одне ядро? : /
Артурас М

3
@ArturasM Або ви неправильно зрозуміли, що говорить веб-сайт, або автор веб-сайту щось зрозумів неправильно. Комп'ютер, що має лише одне ядро, витратить менше часу на очікування вводу-виводу (оскільки всі завдання, які не чекають вводу-виводу, які виконуються на інших ядрах, в той час як одне ядро ​​сидить в режимі очікування, всі повинні були виконати на одному ядро). Введення / виведення потребує певного часу, щоб ви його чекали чи ні - встигнути дочекатися - це симптом того, що не маєте нічого іншого до цього часу.
Випадково832

6

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

Час очікування ви фактично накопичуєте лише в тому випадку, якщо немає іншого потоку чи програми, які могли б працювати. У статті, яку ви цитували (спасибі @manlio за посилання), це так: у вас 12,1% очікування проти 87,4% в режимі очікування, це означає, що одне ядро ​​чекає завершення вводу / виводу, а решта нічого не робить зовсім. Дайте цій системі щось робити, бажано кілька разів, і відсоток очікування повинен впасти.

Однією з найважливіших цілей сучасної розробки програм є забезпечення того, що навіть якщо працює лише одна програма, і навіть якщо ця окрема програма в якийсь момент чекає вводу-виводу, додаток все одно може продовжуватися на іншій роботі. Нитки - це один підхід до цього, не блокуючи введення-виведення, інший, але це дуже залежить від того, яку роботу ви виконуєте, чи можете ви насправді щось зробити без даних, яких ви чекаєте.

при використанні Linux, якщо ви виконуєте кілька довших завдань вводу / виводу, ОС стає майже непридатним до їх завершення.

Це, як правило, вказівка ​​на деяку ситуацію, пов'язану з введенням-виведенням. Смію сказати, що система не стає повільною, оскільки вона не може виконати достатню обробку процесора. Швидше за все, це повільно, тому що ряд даних залежить від даних із жорсткого диска, який зайнятий на той час. Це можуть бути програми, які ви хочете запустити, але які повинні завантажувати свої виконувані файли, бібліотечні файли, піктограми, шрифти та інші ресурси. Це можуть бути додатки, які ви вже працюєте, але які замінили частину своєї пам’яті і тепер потрібно їх замінити, щоб продовжити. Це може бути якийсь демон, який з тієї чи іншої причини вважає, що йому потрібно не тільки записати рядок у файл журналу, але насправді промити цей файл журналу, перш ніж відповісти на якийсь запит.

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


5

Це залежить від коду вашої програми. Я припускаю, що ваш код працює в Linux.

Ви можете використовувати багатопотокові потоки (наприклад, pthreads POSIX ), щоб обчислювальні потоки робили деякі обчислення, тоді як інші потоки, пов'язані з IO, виконують IO (і чекають його). У вас навіть може бути запущено декілька процесів, що спілкуються з міжпроцесорним зв’язком (IPC), див. Труба (7) , фіфо (7) , сокет (7) , unix (7) , shm_overview (7) , sem_overview (7) , mmap (2) , eventfd (2) та читати розширене програмування Linux тощо.

Ви можете використовувати незаблокувальний IO , наприклад, пропуск O_NOBLOCKдля відкриття (2) тощо, тощо, тощо; тощо; тоді вам потрібно буде опитувати (2) та / або використовувати SIGIO сигнал (7) ... та обробляти EWOULDBLOCKпомилку з прочитаного (2) тощо тощо.

Ви можете використовувати POSIX асинхронний IO, див. Aio (7)

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

Але ви врешті-решт дістанетесь до деякого технічного вузького місця (шина, оперативна пам’ять тощо). Дивіться також іоніс (1)


1

Я додаю іншу точку зору, ніж інші, можливо суперечливі:

Його типова проблема операційних систем Linux. Спеціально відставання (пошук "відставання миші Linux"). У Windows немає цієї проблеми. У мене є подвійне завантаження Windows 7 та Linux Mint. Навіть виконуючи інтенсивні операції з дисками в Windows, Windows відчуває згладженість, миша рухається нормально. У Linux в протилежному режимі він не відчуває себе так згладженим, а миша іноді відстає навіть під час звичайного веб-перегляду.

Можливо, це тому, що різні філософія та історія цих двох систем. Windows з самого початку розробляється для звичайних користувачів, її принципово графічних операційних систем. А для користувачів Windows негладна поведінка системи та зупинка руху миші - це сигнал про те, що щось не так. Таким чином, програмісти Microsofts наполегливо працювали над розробкою всієї системи, щоб мінімізувати випадки, коли система відчуває себе повільно. Навпаки, Linux спочатку не є графічною системою, робочий стіл тут є лише стороннім доповненням. А Linux в основному розроблений для хакерів, що використовують командний рядок. Займіться філософією. Linux просто не призначений для плавної поведінки на увазі, почуття тут не мають значення.

Примітка. Я не кажу, що Windows краща за Linux, я кажу, що вони просто мають різну загальну філософію, що в складних умовах може спричинити різні поведінки / почуття цих систем на високому рівні.


Відставання миші Linux, ймовірно, можна було б уникнути або зменшити шляхом ретельної конфігурації системи (тобто використання nice& ioniceголодних процесів). І я користуюся Linux, і майже ніколи не відчував відставання миші Linux (крім випадків, коли перевантажував мій комп'ютер ...)
Basile Starynkevitch

BTW, Linux - це в основному серверна ОС.
Базиль Старинкевич

Зауважу, що я відчував відставання у користувальницькому інтерфейсі та миші на Windows 7, навіть у часи, коли диспетчер завдань та монітор ресурсів вказували на низьке використання пам'яті та низьку активність процесора та диска.
8bittree
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.