Почему моя программа работает быстрее, когда я перенаправляю стандартный вывод?

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

$ bin/profiler 50
50 repetitions of Generate Config MLP took: 254 microseconds
50 repetitions of Create Population took: 5318 microseconds
50 repetitions of Create and Score Population took: 218047 microseconds

$ bin/profiler 50 > time_times
$ cat time_times
50 repetitions of Generate Config MLP took: 258 microseconds
50 repetitions of Create Population took: 5438 microseconds
50 repetitions of Create and Score Population took: 168379 microseconds

$ bin/profiler 50
50 repetitions of Generate Config MLP took: 269 microseconds
50 repetitions of Create Population took: 5447 microseconds
50 repetitions of Create and Score Population took: 216262 microseconds

$ bin/profiler 50 > time_times
$ cat time_times
50 repetitions of Generate Config MLP took: 260 microseconds
50 repetitions of Create Population took: 5321 microseconds
50 repetitions of Create and Score Population took: 169431 microseconds

Вот блок, который я использую для измерения времени, функция ptr — это просто ссылка на функцию void, которая выполняет единственный вызов функции. Я знаю, что, возможно, есть лучшие способы рассчитать время, я хотел быстро и грязно, поэтому я начал улучшать код.

void timeAndDisplay(string name,function_ptr f_ptr) {

struct timeval start, end;
long mtime, seconds, useconds;

gettimeofday(&start, NULL);
// Run the code
for (unsigned x = 0; x < reps; x++) {
f_ptr();
}

gettimeofday(&end, NULL);
seconds  = end.tv_sec  - start.tv_sec;
useconds = end.tv_usec - start.tv_usec;
mtime = ((seconds) * 1000000 + useconds/1.0) + 0.0005;

std::cout << reps << " repetitions of " << name << " took: " << mtime << " microseconds" << std::endl;
}

Я собираю и связываю с:

g++ -c -Wall  -O3 -fopenmp -mfpmath=sse -march=native src/profiler.cpp -o build/profiler.o
g++ build/*.o -lprotobuf -lgomp -lboost_system -lboost_filesystem  -o bin/profiler

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

Кто-нибудь знает, что происходит?

Обновление 1:
Первый проход с профилированием не показывает ничего существенного. Почти все главные вызовы связаны с векторной математикой, которую запускает программа (библиотека Eigen). Преобладающая теория заключается в том, что существует некоторая блокировка ввода / вывода для консоли, но вызовы std :: cout находятся за пределами цикла функции и всего их всего 3, поэтому мне трудно принять, что это оказывает такое влияние.

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

1

Решение

Запись в или из стандартной консольной системы ввода / вывода включает в себя буферы и блокировки. Так что я бы сказал, что вы обычно получаете снижение производительности из-за блокировочных буферов.

Я бы порекомендовал следующее Profiler чтобы выяснить, что занимает больше всего времени.

3

Другие решения

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

Перенаправление в файл обычно происходит быстрее, потому что вывод добавляется и графические манипуляции не выполняются.

По крайней мере, это был мой опыт.

1

Вы пытались запустить его с окном за экраном или за другим окном, чтобы его не нужно было рисовать? Я был в некоторых системах, где это могло бы как-то обойти перерисовку окна.

0