C/C++ лучший способ отправить несколько байтов на стандартный вывод

StackOverflow https://stackoverflow.com/questions/528559

Вопрос

Профилирование моей программы и функция печати занимают много времени.Как я могу отправить «необработанный» байтовый вывод непосредственно на стандартный вывод вместо использования 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];

Это было полезно?

Решение

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

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

Другие советы

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

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

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

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

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

FreeBSD 9 AMD64 на процессоре CoreDuo 2,4 ГГц под 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

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

#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; }
}

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

write (1, matrix, 9);

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

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

fcntl (1, F_SETFL, O_NONBLOCK);

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

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

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

Вся печать происходит довольно медленно, хотя 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]);

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

std::cout << temp;

печать это больше C-стиль.

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

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

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

Что случилось с:

fwrite(matrix,1,9,stdout);

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top