Суд C++, печатающий медленно

web2py! django называет контроллер представлением, 'nuf сказанный.

7
задан Community 23 May 2017 в 12:15
поделиться

6 ответов

ПРИМЕЧАНИЕ : Этот экспериментальный результат действителен для MSVC. В другой реализации библиотеки результат будет другим.

printf может быть (намного) быстрее, чем cout . Хотя printf анализирует строку формата во время выполнения, для этого требуется гораздо меньше вызовов функций и на самом деле требуется небольшое количество инструкций для выполнения одного и того же задания по сравнению с cout . Вот краткое изложение моих экспериментов:

Число статических инструкций

В общем, cout генерирует больше кода, чем printf . Скажем, у нас есть следующий код cout для печати с некоторыми форматами.

os << setw(width) << dec << "0x" << hex << addr << ": " << rtnname <<
  ": " << srccode << "(" << dec << lineno << ")" << endl;

На компиляторе VC ++ с оптимизацией он генерирует код размером около 188 байтов. Но когда вы заменяете его код на основе printf , требуется только 42 байта.

Число динамически выполняемых инструкций

Число статических инструкций просто показывает разницу между статическим двоичным кодом. Что более важно, так это фактическое количество инструкций, которые динамически выполняются во время выполнения. Я также провел простой эксперимент:

Тестовый код:

int a = 1999;
char b = 'a';
unsigned int c = 4200000000;
long long int d = 987654321098765;
long long unsigned int e = 1234567890123456789;
float f = 3123.4578f;
double g = 3.141592654;

void Test1()
{
    cout 
        << "a:" << a << “\n”
        << "a:" << setfill('0') << setw(8) << a << “\n”
        << "b:" << b << “\n”
        << "c:" << c << “\n”
        << "d:" << d << “\n”
        << "e:" << e << “\n”
        << "f:" << setprecision(6) << f << “\n”
        << "g:" << setprecision(10) << g << endl;
}

void Test2()
{
    fprintf(stdout,
        "a:%d\n"
        "a:%08d\n"
        "b:%c\n"
        "c:%u\n"
        "d:%I64d\n"
        "e:%I64u\n"
        "f:%.2f\n"
        "g:%.9lf\n",
        a, a, b, c, d, e, f, g);
    fflush(stdout);
}

int main()
{
    DWORD A, B;
    DWORD start = GetTickCount();
    for (int i = 0; i < 10000; ++i)
        Test1();
    A = GetTickCount() - start;

    start = GetTickCount();
    for (int i = 0; i < 10000; ++i)
        Test2();
    B = GetTickCount() - start;

    cerr << A << endl;
    cerr << B << endl;
    return 0;
}

Вот результат Test1 (cout):

  • выполненных инструкций: 423 234 439

  • загрузок / сохранений памяти: прибл. 320 000 и 980 000

  • Истекшее время: 52 секунды

Тогда как насчет printf ? Это результат Test2:

  • выполненных инструкций: 164 800 800

  • загрузок / сохранений памяти: прибл. 70 000 и 180 000

  • Истекшее время: 13 секунд

На этой машине и в компиляторе printf был намного быстрее cout . И в количестве выполненных инструкций, и в количестве загрузки / сохранения (указывает количество промахов кеша) разница в 3-4 раза

Я знаю, что это крайний случай. Также я должен отметить, что cout намного проще, когда вы обрабатываете 32/64-битные данные и требуете независимости 32/64-платформы. Всегда есть компромисс. Я использую cout , когда проверка типа очень сложна.

Хорошо, cout в MSVS просто отстой :)

12
ответ дан 6 December 2019 в 07:26
поделиться

Попробуйте вызвать ios :: sync_with_stdio (false); перед использованием std :: cout / cin, если только не Конечно, вы смешиваете в своей программе stdio и iostream, а это плохо.

4
ответ дан 6 December 2019 в 07:26
поделиться

Я бы посоветовал вам попробовать этот же тест на другом компьютере. У меня нет хорошего ответа, почему это может происходить; все, что я могу сказать, это то, что я никогда не замечал разницы в скорости между cout и printf. Я также тестировал ваш код с помощью gcc 4.3.2 в Linux, и никакой разницы не было.

При этом вы не можете легко заменить cout своей собственной реализацией. Дело в том, что cout является экземпляром std :: ostream, который имеет много встроенных функций, необходимых для взаимодействия с другими классами, которые перегружают операторы iostream.

Изменить:

Любой, кто говорит printf всегда быстрее, чем std :: cout , просто неправ. Я только что запустил тестовый код, опубликованный minjang, с gcc 4.3. 2 и флаг -O2 на 64-битном AMD Athlon X2, а cout был на самом деле быстрее .

Я получил следующие результаты:

printf: 00:00:12.024
cout:   00:00:04.144

Всегда ли cout быстрее, чем printf? Возможно нет. Особенно в старых реализациях. Но в более новых реализациях iostreams, вероятно, будут быстрее, чем stdio, потому что вместо анализа строки формата во время выполнения компилятор знает во время компиляции, какие функции ему нужно вызвать, чтобы преобразовать целые числа / числа с плавающей запятой / объекты в строки.

Но что еще более важно, скорость printf по сравнению с cout зависит от реализации , и поэтому проблему, описанную OP, нелегко объяснить.

Но в более новых реализациях iostreams, вероятно, будут быстрее, чем stdio, потому что вместо анализа строки формата во время выполнения компилятор знает во время компиляции, какие функции ему нужно вызвать, чтобы преобразовать целые числа / числа с плавающей запятой / объекты в строки.

Но что еще более важно, скорость printf по сравнению с cout зависит от реализации , и поэтому проблему, описанную OP, нелегко объяснить.

Но в более новых реализациях iostreams, вероятно, будут быстрее, чем stdio, потому что вместо анализа строки формата во время выполнения компилятор знает во время компиляции, какие функции ему нужно вызвать, чтобы преобразовать целые числа / числа с плавающей запятой / объекты в строки.

Но что еще более важно, скорость printf по сравнению с cout зависит от реализации , и поэтому проблему, описанную OP, нелегко объяснить.

9
ответ дан 6 December 2019 в 07:26
поделиться

Исходя из моего опыта участия в соревнованиях по программированию, printf БЫСТРЕЕ, чем cout.

Я помню много раз, когда мое решение не срабатывало раньше срока только из-за cin / cout , а printf / scanf действительно работал.

Кроме того, кажется нормальным (по крайней мере, для меня), что cout медленнее, чем printf , потому что он выполняет больше операций.

1
ответ дан 6 December 2019 в 07:26
поделиться

Попробуйте использовать некоторые endl или flush es, так как они будут сбрасывать буфер cout , если ОС кэширование вывода вашей программы по любой причине. Но, как говорит Чарльз, этому поведению нет хорошего объяснения, поэтому, если это не помогает, скорее всего, проблема связана с вашей машиной.

0
ответ дан 6 December 2019 в 07:26
поделиться

Вот hax, который должен сделать потоки c ++ такими же быстрыми, как c printf. Я никогда не тестировал его, но считаю, что он работает.

ios_base::sync_with_stdio(0);
-2
ответ дан 6 December 2019 в 07:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: