Рубрики

Cin-Cout против Scanf-Printf

Обычные конкурирующие программисты сталкиваются с общей проблемой, когда ввод велик, и задача чтения такого ввода из stdin может оказаться узким местом. Такая проблема сопровождается «Предупреждение: большие данные ввода / вывода».

Давайте создадим фиктивный входной файл, содержащий строку с 16 байтами, за которой следует символ новой строки, и имеющий 1000000 таких строк, поэтому файл объемом 17 МБ должен быть достаточно хорошим.

// Creating a dummy file of size 17 MB to compare 
// performance of scanf() and cin()
$ yes 1111111111111111 | head -1000000 > tmp/dummy

Давайте сравним время, затраченное на чтение файла из stdin (получение файла с диска в stdin с помощью перенаправления), используя scanf () и cin.

// Имя файла: cin_test.cc для проверки
// Перенаправляем выше созданный временный файл
// из 17 МБ к stdin, когда эта программа
// выполняется.
#include<iostream>

using namespace std;

  

int main()

{

    char buffer[256];

    while (cin >> buffer)

    {

    }

    return 0;

}

Вывод вышеуказанной программы, когда фиктивный файл перенаправлен на стандартный ввод.

$ g++ cin_test.cc –o cin_test
$ time ./cin_test < /tmp/dummy
real	 0m2.162s
user	 0m1.696s
sys	 0m0.332s

// Имя файла: scanf_test.c, чтобы увидеть
// производительность scanf ()
// Перенаправляем выше созданный временный файл
// из 17 МБ к stdin, когда эта программа
// выполняется.
#include<cstdlib>
#include<cstdio>

int main()

{

    char buffer[256];

    while (scanf("%s", buffer) != EOF)

    {

    }

    return 0;

}

Вывод вышеуказанной программы, когда фиктивный файл перенаправлен на стандартный ввод.

$ g++ scanf_test.cc –o scanf_test
$ time ./scanf_test < /tmp/dummy
real	 0m0.426s
user	 0m0.248s
sys	 0m0.084s

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

Почему scanf быстрее чем cin?
На высоком уровне они оба являются обертками над системным вызовом read () , просто синтаксическим сахаром. Единственное видимое отличие состоит в том, что scanf () должен явно объявить тип ввода, тогда как в cin операция перенаправления перегружена с использованием шаблонов. Это не кажется достаточной причиной для снижения производительности в 5 раз.

Оказывается, iostream использует систему буферизации stdio . Таким образом, cin тратит время на синхронизацию с буфером stdio C-библиотеки, так что вызовы как scanf (), так и cin могут чередоваться.

Хорошо, что libstdc ++ предоставляет возможность отключить синхронизацию всех стандартных потоков iostream с соответствующими им стандартными потоками C, используя

std::ios::sync_with_stdio(false);

и cin становится быстрее, чем scanf (), как и должно быть.

Подробная статья о быстром вводе в конкурентном программировании

// Имя файла: cin_test_2.cc, чтобы увидеть
// выполнение cin () с помощью stdio syc
// отключено с помощью sync_with_stdio (false).
#include<iostream>

using namespace std;

  

int main()

{

    char buffer[256];

    ios_base::sync_with_stdio(false);

  

    while (cin >> buffer)

    {

  

    }

    return 0;

}

Запуск программы:

$ g++ cin_test_2.cc –o cin_test_2
$ time./cin_test_2 </tmp/dummy
real    0m0.380s
user   0m0.240s
sys    0m0.028s 
  • Как и во всех вещах, здесь есть оговорка. Если синхронизация отключена, совместное использование cin и scanf () приведет к неопределенному беспорядку.
  • При отключенной синхронизации приведенные выше результаты показывают, что cin на 8-10% быстрее, чем scanf () . Вероятно, это связано с тем, что scanf () интерпретирует аргументы формата во время выполнения и использует переменное число аргументов, тогда как cin делает это во время компиляции.

Теперь интересно, как быстро это можно сделать?

// Redirecting contents of dummy file to null
// device (a special device that discards the
// information written to it) using command line.
$time cat /tmp/dummy > /dev/null
real   0m0.185s
user   0m0.000s
sys    0m0.092s

Вот это да! Это быстро !!!

Эта статья предоставлена Аюшем Говилом . Если вам нравится GeeksforGeeks и вы хотите внести свой вклад, вы также можете написать статью и отправить ее по почте на contrib@geeksforgeeks.org. Смотрите свою статью, появляющуюся на главной странице GeeksforGeeks, и помогите другим вундеркиндам.
Пожалуйста, напишите комментарии, если вы обнаружите что-то неправильное, или вы хотите поделиться дополнительной информацией по обсуждаемой теме

Рекомендуемые посты:

Cin-Cout против Scanf-Printf

0.00 (0%) 0 votes