Програмуйте ЗНАЧЕНО повільніше при використанні з TTY


4

Тож у мене програма, написана на C ++.

Це може сказати мені, скільки часу знадобилося зробити всі обчислення, і це робить багато досить важких багатопотокових розрахунків.

Я щойно помітив, що якщо я запускаю програму на точно такій же машині, потрібно робити приблизно 20-21 секунду, щоб зробити всі обчислення, якщо почати з TTY, і лише приблизно 0,2 секунди, якщо запустити її з терміналу GNOME.

Що це викликає? Це буквально той самий файл на одній машині.


Що ви маєте на увазі під CLI (я знаю, що це означає, я маю на увазі, як ви запускаєте його, якщо не з терміналу)? Моя здогадка, що в оболонці, яка її запускає, є деякі проблеми - можливо, вона не оптимізована для багатопотокової нитки.
Даррен

те, що з’являється, коли я натискаю CTRL + ALT + F1
Mac B

1
Гаразд, це називається TTY. Можуть бути різні оболонки за замовчуванням (echo $ SHELL).
Даррен

Відповіді:


4

Деякі фонові теорії

Ну, і те, з чим ви працюєте після CTRL+ ALT+, F1і термінал GNOME - це різні реалізації однієї концепції: емуляція так званого повноекранного терміналу.

Перша річ називається віртуальним терміналом (VT) в Linux, або зазвичай просто "консоль". Він використовує спеціальний "текстовий" відео режим, який все ще надається апаратними відеокартами на платформах, сумісних з x86 (тобто спадщиною "IBM PC", тобто). Останнє є додатком GUI.

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

Проблема під рукою

Гаразд, тепер перейдемо до сприйнятої повільності.

Я впевнений, що суть вашої проблеми полягає в тому, що ваша програма робить так зване "блокування" вводу-виводу. Тобто кожен раз, коли ви робите щось подібне

std::cout << "Hello, world" << endl;

у вашому коді спочатку вводиться код стандартної бібліотеки C ++, пов’язаний із вашою програмою, і обробляє виведення матеріалів, надісланих до зазначеного потоку.

Після певної обробки (і, як правило, деякої буферизації) ці дані фактично повинні вийти з запущеного процесу вашої програми та отримати фактичний вихід на будь-який носій, на який ваші програми надсилають свої програми. У Linux (та інших системах, сумісних з Unix) для цього потрібно викликати ядро ​​- через виділений системний виклик (або короткий syscall ) write().

Тож stdlib C ++ зрештою робить цей write()системний виклик, а потім чекає його завершення - тобто чекає, коли ядро ​​відповість "ОК, одержувач даних повідомив, що він його придбав".

Як можна зробити висновок, приймачем даних, які виводить ваша програма, є термінал (емулятор), на якому працює ваша програма - або Linux VT, або екземпляр терміналу GNOME у ваших тестах. (Повна картинка є складнішою, оскільки ядро ​​не надсилатиме дані прямо в працюючий емулятор терміналу, але не давайте ускладнювати опис.)

І тому швидкість, з якою write()завершується цей системний виклик, дуже залежить від того, наскільки швидко приймає дані обробку даних! У вашому випадку термінал GNOME просто робить це швидше.

Мій погляд на різницю полягає в тому, що драйвер VT прискіпливо видає всі дані, що надсилаються йому, прокручує їх і т.д. відпочинок у так званому "буфері прокрутки", що має більшість емуляторів терміналу GUI.

Витяги робити

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

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

Тож вірний спосіб вимірювання "необробленої" продуктивності обчислень - це наявність у вашій програмі можливості відключення всіх вводу-виводу. Якщо це неможливо чи було б занадто некрасиво реалізувати, принаймні спробуйте направити весь вихід на так званий "нульовий пристрій", /dev/nullзапустивши програму, як

$ ./program >/dev/null

Нульовий пристрій просто відкидає всі передані йому дані. Так, так, все ж кожен раунд вводу-виводу, виконаний stdlib C ++, буде вражати ядро, але принаймні у вас буде майже постійна (і швидка швидкість) написання.

Якщо вам потрібні і заходи, і дані, що генеруються, подумайте про створення так званої оперативної пам’яті та перенаправлення виводу на розташований там файл.

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

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


1
Я не знав, що консоль Linux була такою повільною. ОП повідомляє про різницю в 100 разів, я виміряв коефіцієнт майже 200 (з новим і швидшим терміналом gnome), використовуючи мій улюблений тестовий файл (42 Мб, 660k рядків з кольоровим виходом "ls-lR"): gnome-terminal 3.8s vs .консоль 11м56с. Якщо я перейду на інший VT і назад, консоль завершується за 2 секунди. Вузьке місце, мабуть, ядро ​​розмовляє з відеодрайвером.
Егмонт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.