C / C ++ лучший способ отправить количество байтов на стандартный вывод - PullRequest
2 голосов
/ 09 февраля 2009

Профилирование моей программы и функции печати занимает много времени. Как я могу отправить «сырой» байтовый вывод непосредственно на стандартный вывод вместо использования fwrite и сделать это быстрее (необходимо отправить все 9 байтов в print () одновременно на стандартный вывод)?

void print(){
    unsigned char temp[9];

    temp[0] = matrix[0][0];
    temp[1] = matrix[0][1];
    temp[2] = matrix[0][2];
    temp[3] = matrix[1][0];
    temp[4] = matrix[1][1];
    temp[5] = matrix[1][2];
    temp[6] = matrix[2][0];
    temp[7] = matrix[2][1];
    temp[8] = matrix[2][2];

    fwrite(temp,1,9,stdout);

}

Матрица определена глобально как матрица без знака [3] [3];

Ответы [ 9 ]

10 голосов
/ 09 февраля 2009

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

Единственная функция более низкого уровня, которую вы можете использовать (если вы разрабатываете на * nix-машине), - это использовать функцию write, но даже тогда ваша производительность не будет намного выше, чем сейчас. Проще говоря: IO стоит дорого.

7 голосов
/ 27 апреля 2012

Ответ с самым высоким рейтингом утверждает, что IO медленный.

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

Запись 10 миллионов записей из девятибайтового массива

Mint 12 AMD64 на 3 ГГц CoreDuo под gcc 4.6.1

   340ms   to /dev/null 
   710ms   to 90MB output file 
 15254ms   to 90MB output file in "dribs" mode 

FreeBSD 9 AMD64 на 2,4 ГГц CoreDuo под Clang 3.0

   450ms   to /dev/null 
   550ms   to 90MB output file on ZFS triple mirror
  1150ms   to 90MB output file on FFS system drive
 22154ms   to 90MB output file in "dribs" mode

В IO нет ничего медленного, если вы можете позволить себе правильно буферизовать.

#include <stdio.h> 
#include <assert.h> 
#include <stdlib.h>
#include <string.h>

int main (int argc, char* argv[]) 
{
    int dribs = argc > 1 && 0==strcmp (argv[1], "dribs");
    int err;
    int i; 
    enum { BigBuf = 4*1024*1024 };
    char* outbuf = malloc (BigBuf); 
    assert (outbuf != NULL); 
    err = setvbuf (stdout, outbuf, _IOFBF, BigBuf); // full line buffering 
    assert (err == 0);

    enum { ArraySize = 9 };
    char temp[ArraySize]; 
    enum { Count = 10*1000*1000 }; 

    for (i = 0; i < Count; ++i) {
        fwrite (temp, 1, ArraySize, stdout);    
        if (dribs) fflush (stdout); 
    }
    fflush (stdout);  // seems to be needed after setting own buffer
    fclose (stdout);
    if (outbuf) { free (outbuf); outbuf = NULL; }
}
3 голосов
/ 09 февраля 2009

Возможно, ваша проблема не в том, что функция fwrite () работает медленно, а в том, что она буферизована. Попробуйте вызвать fflush (stdout) после fwrite ().

Это все действительно зависит от вашего определения медленного в этом контексте.

2 голосов
/ 09 февраля 2009

Самая грубая форма вывода, которую вы можете сделать, - это вероятный системный вызов write, например

write (1, matrix, 9);

1 - дескриптор файла для стандартного выхода (0 - стандартный вход, 2 - стандартная ошибка). Ваш стандартный выход будет писать только так быстро, как тот, кто читает его на другом конце (то есть терминале или программе, в которую вы передаете), что может быть довольно медленным.

Я не уверен на 100%, но вы можете попробовать установить неблокирующий ввод-вывод на fd 1 (используя fcntl) и надеяться, что ОС будет буферизовать его для вас, пока он не будет использован другим концом. Это было какое-то время, но я думаю, что это работает так

fcntl (1, F_SETFL, O_NONBLOCK);

YMMV хотя. Пожалуйста, исправьте меня, если я ошибаюсь в синтаксисе, как я уже сказал, это было давно.

1 голос
/ 09 февраля 2009

Как уже отмечалось, IO в узком внутреннем цикле стоит дорого. Я обычно заканчивал тем, что делал условный cout Matrix на основе некоторых критериев, когда это требовалось для его отладки.

Если ваше приложение является консольным приложением, попробуйте перенаправить его в файл, это будет намного быстрее, чем обновление консоли. например, app.exe> ​​matrixDump.txt

1 голос
/ 09 февраля 2009

Вы можете просто:

std::cout << temp;

printf больше в стиле C.

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

1 голос
/ 09 февраля 2009

Вся печать довольно медленная, хотя iostreams очень медленная для печати. ​​

Лучше всего будет использовать printf, что-то вроде:

printf("%c%c%c%c%c%c%c%c%c\n", matrix[0][0], matrix[0][1], matrix[0][2], matrix[1][0],
  matrix[1][1], matrix[1][2], matrix[2][0], matrix[2][1], matrix[2][2]);
0 голосов
/ 09 февраля 2009

Попробуйте запустить программу дважды. Один раз с выходом и один раз без. Вы заметите, что в целом, тот, у кого нет io, самый быстрый. Кроме того, вы можете разветвить процесс (или создать поток), одну запись в файл (stdout) и одну операцию.

0 голосов
/ 09 февраля 2009

Что не так с:

fwrite(matrix,1,9,stdout);

и один, и двухмерные массивы занимают одну и ту же память.

...