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

Опубликовано: 1 Января, 2022

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

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

// Создание фиктивного файла размером 17 МБ для сравнения 
// производительность scanf () и cin ()
$ да 1111111111111111 | голова -1000000> tmp / dummy

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

// Filename : cin_test.cc to test the
// We redirect above created temp file
// of 17 MB to stdin when this program
// is run.
#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
реальный 0m2.162s
пользователь 0m1.696s
sys 0m0.332s 
// Filename : scanf_test.c to see
// performance of scanf()
// We redirect above created temp file
// of 17 MB to stdin when this program
// is run.
#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 перегружает операцию перенаправления с использованием шаблонов. Это не кажется достаточно веской причиной для пятикратного снижения производительности.

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

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

 std :: ios :: sync_with_stdio (ложь);

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

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

// Filename : cin_test_2.cc to see
// performance of cin() with stdio syc
// disabled using 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
реальный 0m0.380s
пользователь 0m0.240s
sys 0m0.028s
  • Как и во всем, здесь есть одна оговорка. Когда синхронизация отключена, совместное использование cin и scanf () приведет к неопределенному беспорядку.
  • При выключенной синхронизации приведенные выше результаты показывают, что cin на 8-10% быстрее, чем scanf () . Вероятно, это связано с тем, что scanf () интерпретирует аргументы формата во время выполнения и использует переменное количество аргументов, тогда как cin делает это во время компиляции.

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

// Перенаправление содержимого фиктивного файла на null
// устройство (специальное устройство, которое отбрасывает
// информация, записанная в него) с помощью командной строки.
$ time cat / tmp / dummy> / dev / null
реальный 0m0.185s
пользователь 0m0.000s
sys 0m0.092s

Ух ты! Это быстро !!!

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

Вниманию читателя! Не прекращайте учиться сейчас. Освойте все важные концепции DSA с помощью самостоятельного курса DSA по доступной для студентов цене и будьте готовы к работе в отрасли. Получите все важные математические концепции для соревновательного программирования с курсом Essential Maths for CP по доступной для студентов цене.

Если вы хотите посещать живые занятия с отраслевыми экспертами, пожалуйста, обращайтесь к Geeks Classes Live и Geeks Classes Live USA.