Cin-Cout против Scanf-Printf
Обычные конкурентоспособные программисты сталкиваются с общей проблемой, когда вводимые данные имеют большой размер, и задача чтения таких вводимых данных из стандартного ввода может оказаться узким местом. Такая проблема сопровождается сообщением «Предупреждение: большие данные ввода-вывода».
Давайте создадим фиктивный входной файл, содержащий строку с 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.