Деякі фонові теорії
Ну, і те, з чим ви працюєте після 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 або будь-яким іншим), процесор ніколи не спить - завжди є деякі завдання, які роблять речі у фоновому режимі. Це означає, що вимірювання продуктивності обчислень навіть без будь-якого вводу / виводу або зі свого роду "відключеним" вводу / виводу (як пояснено вище) все одно дасть різні результати на кожному пробігу.
Для того, щоб компенсувати це, хороший бенчмаркінг означає виконувати свій обчислення з одними і тими ж вхідними даними в кілька тисяч разів і усереднювати результати за кількістю пробіжок.