Если вы пишите на С++, то регулярно бывает так, что ввод написанный через std::cin начинает тормозить из-за громоздких входных данных. Конечно правильнее в таких случаях сразу же писать чтение данных более эффективно - хотя бы с помощью функции scanf. Но если тестирующая система использует GNU C++ (проверял на MinGW 4.4.1, но думаю и на других версиях тоже будет работать), а переписывать программу не хочется, то можно катастрофически ускорить чтение всего одной строкой, размещенной в начале программы: ios_base::sync_with_stdio( 0) .На моем примере, где надо было найти сумму миллиона целых чисел, это ускорило программу в 4.5 раза, приблизив время работы к варианту со scanf. Пробовал запускать этот же тест на MS Visual C++ 9.0 - но не ускоряет.








также виден прирост скорости операций I/O на GNU C++3.4.2
int nextInt() throws IOException { in.nextToken(); return (int)in.nval; }Я тоже пишу на Java. Как раз для таких случаев у меня припасён переписанный Сканер (Извините, если отступы сбились)
class Scanner{
StreamTokenizer in;
Scanner(InputStream stream){
in = new StreamTokenizer(new InputStreamReader(stream));
}
void asserT(boolean e){
if (!e){
throw new Error();
}
}
int nextInt(){
try{
in.nextToken();
asserT(in.ttype == in.TT_NUMBER);
asserT(in.nval == (int)in.nval);
return (int) in.nval;
}catch (Exception e) {
throw new Error();
}
}
}
Ну и метод запуска программы
void run(){
in = new Scanner(System.in);
out = new PrintWriter(System.out);
try {
solve();
}finally{
out.close();
}
}
Никаких посторонних "шаманств" не надо. Ассерты установлены, чтобы программа не дай бог не получила WA или ещё что-нить при некорректном вводе вместо Crash.
Извините за косяк в конструкторе ;)
Scanner(InputStream stream) {
in = new StreamTokenizer(new BufferedReader(new InputStreamReader(stream)));
}
Знающие люди должны оценить то, что эта версия переписанного сканера следует всем правилам хорошего стиля и правильной архитектуры.
Сейчас при решении кодчифа ( http://www.codechef.com/MARCH12/problems/HDELIVER ) столкнулся с одной проблемой.. раньше не встречал.. Кто-нибудь в курсе почему происходит такая вещь?
Значится так: я всегда пишу код в своём шаблоне, где у меня есть также строка ios::sync_with_stdio(0); в самом начале main(). Я обычно считываю cin/cout и программа не захотела заходить по ТЛ… ну естественно в первую очередь написал scanf(), но как бы зачем это делать в тех местах, которые отработают раз 100… так что исправил только там, где много данных считывается. Засылаю, получаю рантайм (ошибка доступа). Вобщем выяснил, что что-то не так считывается. Задача зашла только когда либо закомментил ios::sync_with_stdio(0); либо когда все cin исправил на scanf(). То есть проблема именно в том, что не может быть написано одновременно ios::sync_with_stdio(0); и чередование в середине программы cin и scanf(). Причём мне почему-то кажется, что раньше я так делал и никаких проблем связанных с этим не возникало.
Ну тут чётко написано: If the synchronization is turned off, the C++ standard streams are allowed to act independently. In this case using both C and C++ standard streams at the same time leads to undefined behavior.
О! Спасибо!
Кстати возможно, что до этого всё было норм, ибо я отправлял в MSVS (а в ней работает всё корректно), а тут gcc-4.3.2.
Мелкософт обычно плевать хотели на все стандарты, а тем более на какую-то там ios_base::sync_with_stdio — видно они не заморачиваются и синхронизируют любой i/o, игнорируя Ваши флаги.
Зачем так категорично :) Просто реализация от Microsoft зачастую в случае undefined behavior молча выбирает какой-нибудь из вариантов дальнейшего выполнения программы. Это вполне соответствует требованиям стандарта. Другое дело, что часто такое боком выходит.
Значение флага ios_base::sync_with_stdio — это не undefined behavior, это вполне осмысленное поведение, которое ожидает программист, выставив этот флаг. Но Microsoft этот флаг просто игнорируют (им лень было это реализовывать).
Я вел речь об одновременном использовании sync_with_stdio(false) и чередовании cin/scanf, когда говорил про UB. А о том, что в реализации от Dinkumware (это ведь, кстати, не Microsoft виноват :) ) этот флаг игнорируется, я не знал. Вот что написано у них на сайте: “In this implementation there is no need to call the iostream member function sync_with_stdio to ensure such synchronization, nor is there any performance benefit in disabling it”. И дело тут, похоже, не в лени..
UB при чередовании cin/scanf — есть очевидное следствие отсутствия синхронизации, что в свою очередь дает прирост производительности. То, что в реализации, используемой Microsoft, не реализован такой режим — вовсе не есть плюс.
Я нигде и не говорил, что это плюс. Просто делать утверждения, что во всем виновата Microsoft, лень, etc, не подтверждая это фактами — легко. На деле же, обычно, причины каких-то “косяков” гораздо глубже.
Хм… то, что было предусмотрено проектировщиками языка, но не было реализовано — как это назвать? Если не лень, то чёткий экономический просчёт — зачем тратить деньги на какую-то там оптимизацию, если это и так можно продать?
Главное же как себя подать — можно вон гордо написать “In this implementation there is no need to call the iostream member function sync_with_stdio to ensure such synchronization”, хотя слова “In this implementation” явно лишние — в стандарте чётко прописано поведение по-умолчанию.
Ну а оправдание типа “наш продукт такой гавёный не по нашей вине, а потому что мы покупаем для него такой-то кусок в другой фирме” звучит смешно. ;)
А есть бенчмарки, которые показывают сильно лучшую скорость у gcc при выключенном синке? Если это не так, то я бы назвал это плюсом библиотеки от MS
без синка — TL с синком — заходит за половину отведенного времени. Не редкость.
Я не говорю о разнице gcc с синком и без, я говорю о разнице gcc с выключенным синком и MSVS
Egor, пожалуйста:
1255624 — G++ c включенным синком (200 мс)
1255626 — G++ с выключенным синком (50 мс)
1255627 — MS C++ (230 мс)
Вам очень везло. :-) У меня как и ожидается из названия и описания метода даже следующая простая программа загибается на gcc 4.3 mingw:
А название функции ios::sync_with_stdio не намекает? :)
:-D Ну да… даже не вдумывался, в одно время тупо запомнил и всё :)