powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / printf vs потоковый ввод/вывод
26 сообщений из 26, показаны все 2 страниц
printf vs потоковый ввод/вывод
    #39186838
зеленый админ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Привет, переживаю когнитивный диссонанс в связи с тем, что потоковый ввод/вывод медленней printf.
Иcточник: олимпиадные задачи
это вообще как возможно?
Я как-то думал, что разрешение перегрузки операторов << и >> при компилировании сделает наоборот потоковый io много быстрее чем printf...
...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39186852
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Для олимпиадных задач скорость ввода/вывода не критична, т.к. объемы незначительны.

А так оба способа тормозные из-за тормозных парсеров. Самый быстрый способ читать блоками по 4-8 кб и парсить самодельным парсером заточенным под свою структуру. Не раз обсуждали, например тут.
...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39186902
YesSql
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
зеленый админПривет, переживаю когнитивный диссонанс в связи с тем, что потоковый ввод/вывод медленней printf.
Иcточник: олимпиадные задачи
это вообще как возможно?
Я как-то думал, что разрешение перегрузки операторов << и >> при компилировании сделает наоборот потоковый io много быстрее чем printf...
Если ты про Визуал Студио, то в последней версии которую я видел, внутри операторов << и >> стояли printf и scanf.
Если мне не изменяет память это была VS2003.
Может они до сих пор там?
...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39186935
Фотография Anatoly Moskovsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YesSqlЕсли ты про Визуал Студио, то в последней версии которую я видел, внутри операторов << и >> стояли printf и scanf.
Вы имеете в виду, что внутри с помощью sprintf и sscanf работали через промежуточный буфер, а уже буфер писался/читался из потока?
...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39187089
YesSql
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Anatoly MoskovskyYesSqlЕсли ты про Визуал Студио, то в последней версии которую я видел, внутри операторов << и >> стояли printf и scanf.
Вы имеете в виду, что внутри с помощью sprintf и sscanf работали через промежуточный буфер, а уже буфер писался/читался из потока?
Да, это я и имел ввиду.
...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39187128
зеленый админ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TА так оба способа тормозные из-за тормозных парсеров.


Из-за какого извините парсера тормозным будет потоковый ввод-вывод? Мне Страуструп в книжке обещал парсинг на этапе компиляции за счет оверлоадинга операторов. Что отнюдь не хуже самодельного заточенного парсера

YesSql Если ты про Визуал Студио...


Нет, я в принципе про нормальный компилятор. Я лично пользуюсь gcc под cygwin.

YesSql внутри операторов << и >> стояли printf и scanf.


Не, я однозначно не про визуал студию
...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39187143
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
зеленый админDima TА так оба способа тормозные из-за тормозных парсеров.


Из-за какого извините парсера тормозным будет потоковый ввод-вывод? Мне Страуструп в книжке обещал парсинг на этапе компиляции за счет оверлоадинга операторов. Что отнюдь не хуже самодельного заточенного парсера
ХЗ чего ты там вычитал и кто тебе чего наобещал. Я же дал ссылку, там был код, бери да тести. Кстати топик начался именно из-за тормозов потокового чтения.
Пример на основе чтения и разбора большого файла с числами.
Добавил потоковый разбор
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
define _CRT_SECURE_NO_WARNINGS

#include <fstream>
#include <time.h>
#include <stdio.h>

#define BUF_SIZE 1024 * 8

// Создание файла
void create_file(const char* filename, int size) {
	FILE* file = fopen(filename, "rb");
	if (file != NULL) {
		// Файл уже есть
		printf("Use file %s\n", filename);
		fclose(file);
		return;
	}
	printf("Create file %s size %d ...\n", filename, size);
	file = fopen(filename, "wb");
	if (file != NULL) {
		for (int i = 0; i < size; i++) {
			fprintf(file, "%d\n", rand());
		}
		fclose(file);
	}
}

// Замер скорости чтения без разбора
void read_speed(const char* filename) {
	int count = 0;
	clock_t start = clock();
	FILE* file = fopen(filename, "rb");
	if (file != NULL) {
		int n = 0;
		bool store = false;
		char buffer[BUF_SIZE];
		size_t bytesRead = 0;
		while ((bytesRead = fread(buffer, 1, sizeof(buffer), file)) > 0) {
			count++;
		}
		fclose(file);
	}
	printf("ONLY READ: Count %d blocks Time %f sec.\n", count, (double)(clock() - start) / CLOCKS_PER_SEC);
}

// Самодельный парсер
void read_ints(const char* filename) {
	clock_t start = clock();
	int count = 0;
	int check = 0;
	FILE* file = fopen(filename, "rb");
	if (file != NULL) {
		int n = 0;
		bool minus = false;
		bool store = false;
		bool overflow = false;
		char buffer[1024 * 8];
		size_t bytesRead = 0;
		while ((bytesRead = fread(buffer, 1, sizeof(buffer), file)) > 0) {
			char* end = buffer + bytesRead;
			for (char* cur = buffer; cur < end; cur++) {
				// считаем что все числа целые и разделены любыми разделителями
				if (*cur >= '0' && *cur <= '9') {
					int k = n * 10 + *cur - '0';
					if (!overflow) overflow = k < n;
					n = k;
					store = true;
				}
				else {
					if (store) {
						// тут сохраняем результат
						if (overflow) {
							printf("overflow\n");// переполнение
							overflow = false;
						}
						else {
							if (minus) {
								n = -n;
								minus = false;
							}
							check ^= n;
							//printf("%d\n", n);
							count++;
						}
						store = false;
						n = 0;
					}
					minus = (*cur == '-');
				}
			}
		}
		fclose(file);
	}
	printf("Block Read %d numbers CheckSum %X Time %f sec.\n", count, check, (double)(clock() - start) / CLOCKS_PER_SEC);
}

// Потоковый парсер С++
void read_stream(const char* filename) {
	clock_t start = clock();
	int count = 0;
	int check = 0;
	std::ifstream stream(filename, std::ios::in);

	int x;
	while(stream >> x) {
		count++;
		check ^= x;
	}
	printf("Stream Read %d numbers CheckSum %X Time %f sec.\n", count, check, (double)(clock() - start) / CLOCKS_PER_SEC);
	stream.close();
}


int main(int argc, char* argv[])
{
	char file[] = "big.txt";
	create_file(file, 10000000); // добавь 1-2 нолика если ждать не лень
	read_speed(file);
	read_ints(file);
	read_stream(file);

	return 0;
}


Результат в MS VC 2015Use file big.txt
ONLY READ: Count 6911 blocks Time 0.031000 sec.
Block Read 10000000 numbers CheckSum 47B5 Time 0.138000 sec.
Stream Read 10000000 numbers CheckSum 47B5 Time 4.329000 sec.
Потоковый способ (read_stream) в 30 раз медленнее самодельного парсера (read_ints).

Можешь потестить другие компиляторы. Должно компилироваться любым.
...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39187185
YesSql
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
[quot Dima T]зеленый админпропущено...

Результат в MS VC 2015Use file big.txt
ONLY READ: Count 6911 blocks Time 0.031000 sec.
Block Read 10000000 numbers CheckSum 47B5 Time 0.138000 sec.
Stream Read 10000000 numbers CheckSum 47B5 Time 4.329000 sec.
Потоковый способ (read_stream) в 30 раз медленнее самодельного парсера (read_ints).

Можешь потестить другие компиляторы. Должно компилироваться любым.

Результат в g++ (GCC) 5.3.1 on Linux 4.4.3-300.fc23.x86_64Use file big.txt
ONLY READ: Count 12797 blocks Time 0.012521 sec.
Block Read 10000000 numbers CheckSum 619D29BC Time 0.202639 sec.
Stream Read 10000000 numbers CheckSum 619D29BC Time 0.990503 sec.
fscanf Read 10000000 numbers CheckSum 619D29BC Time 1.315379 sec.

зеленый админпереживаю когнитивный диссонанс в связи с тем, что потоковый ввод/вывод медленней printf.
На нормальном компиляторе все работает правильно.

fscanf добавка к Диминому тесту
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
// fscanf парсер С
void read_fscanf(const char* filename) {
    clock_t start = clock();
    int count = 0;
    int check = 0;
    FILE* file = fopen(filename, "rb");

    int x;
    while(EOF!=fscanf(file, "%d\n", &x)) {
        count++;
        check ^= x;
    }
    printf("fscanf Read %d numbers CheckSum %X Time %f sec.\n", count, check, (double)(clock() - start) / CLOCKS_PER_SEC);
    fclose(file);
}


...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39187361
Фотография MasterZiv
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
зеленый админПривет, переживаю когнитивный диссонанс в связи с тем, что потоковый ввод/вывод ntf...

совет простой: не переживай!
...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39187364
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YesSqlНа нормальном компиляторе все работает правильно.
В винде такое же отношение результатов и для mingw
...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39187370
YesSql
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
SiemarglYesSql На нормальной системе и с нормальным компилятором все работает правильно.
В винде такое же отношение результатов и для mingw
Я не знаком с MinGW
MinGWMinGW provides a complete Open Source programming tool set which is suitable for the development of native MS-Windows applications, and which do not depend on any 3rd-party C-Runtime DLLs. ( It does depend on a number of DLLs provided by Microsoft themselves, as components of the operating system; most notable among these is MSVCRT.DLL, the Microsoft C runtime library. Additionally, threaded applications must ship with a freely distributable thread support DLL, provided as part of MinGW itself).
Но подозреваю что он использует Микросовтовскую библиотеку. С теми-же scanf и printf в потоковых операторах.
Может кто-либо прояснить?
А может в виндовсе такой ввод-вывод. Интересно посмотреть как этот тестик будет выглядеть на виндовс сервере.
...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39187510
зеленый админ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YesSql,

Спс за тесты. По крайней мере scanf, конечно, должен быть не быстрее чем потоковый. 30% прироста внушительны.

Dima T, тоже спс. Верю, что в vc можно добиться и все 30x ускорения. Но и результат 5x в gcc внушителен. Выходит, не заточено преобразование строки в число...
...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39187515
зеленый админ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
cygwin x64 + gcc version 5.3.0 (GCC) g++ read_test.cpp -O3

$ ./a.exe
Use file big.txt
ONLY READ: Count 12796 blocks Time 0.155000 sec.
Block Read 10000000 numbers CheckSum 52634B0F Time 1.155000 sec.
Stream Read 10000000 numbers CheckSum 52634B0F Time 7.036000 sec.
fscanf Read 10000000 numbers CheckSum 52634B0F Time 13.478000 sec.
...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39187546
Фотография OoCc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
зеленый админрезультат 5x в gcc внушителен. Выходит, не заточено преобразование строки в число...
Я думаю что в gcc может быть еще меньший разрыв. Как сказал один мудрец. "Сначала программа делается быстрой, а потом доводится до рабочего состояния". (c) ????
...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39187682
зеленый админ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
OoCc,

хз. Но тут нужно разрабов библиотек переспрашивать или самому оверлоадить оператор >> на собственный класс а-ля MyInteger.
Вот что разрабы предлагают:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
  template<typename _CharT, typename _Traits>
    basic_istream<_CharT, _Traits>&
    basic_istream<_CharT, _Traits>::
    operator>>(int& __n)
    {
      // _GLIBCXX_RESOLVE_LIB_DEFECTS
      // 118. basic_istream uses nonexistent num_get member functions.
      sentry __cerb(*this, false);
      if (__cerb)
	{
	  ios_base::iostate __err = ios_base::goodbit;
	  __try
	    {
	      long __l;
	      const __num_get_type& __ng = __check_facet(this->_M_num_get);
	      __ng.get(*this, 0, *this, __err, __l);

	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
	      // 696. istream::operator>>(int&) broken.
	      if (__l < __gnu_cxx::__numeric_traits<int>::__min)
		{
		  __err |= ios_base::failbit;
		  __n = __gnu_cxx::__numeric_traits<int>::__min;
		}
	      else if (__l > __gnu_cxx::__numeric_traits<int>::__max)
		{
		  __err |= ios_base::failbit;	      
		  __n = __gnu_cxx::__numeric_traits<int>::__max;
		}
	      else
		__n = int(__l);
	    }
	  __catch(__cxxabiv1::__forced_unwind&)
	    {
	      this->_M_setstate(ios_base::badbit);
	      __throw_exception_again;
	    }
	  __catch(...)
	    { this->_M_setstate(ios_base::badbit); }
	  if (__err)
	    this->setstate(__err);
	}
      return *this;
    }



т.е. создают на стеке каждый раз объект да еще условный оператор на него гоняют зачем-то...
...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39187684
зеленый админ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
зеленый админ,

http://en.cppreference.com/w/cpp/io/basic_istream/sentry
ага, дергают каждый раз поток и проверяют, готов ли к выводу...
...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39187839
Фотография OoCc
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
зеленый админOoCc,

хз. Но тут нужно разрабов библиотек переспрашивать или самому оверлоадить оператор >> на собственный класс а-ля MyInteger.

т.е. создают на стеке каждый раз объект да еще условный оператор на него гоняют зачем-то...

Я не имел ввиду конкретный код.
Это был филосовский пост.
От "Proof of concept" до "Product" очень длинный путь. То что дает на первом этапе 30 кратное увеличение производительности на втором этапе может быть не столь быстрым.
...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39190011
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T,

У тебя в коде немножечко ошибка в блокрид.
Если файл не заканчивается переводом строки, последнее число не читается.
...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39190029
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SiemarglDima T,

У тебя в коде немножечко ошибка в блокрид.
Если файл не заканчивается переводом строки, последнее число не читается.
Как посмотреть. Писалось под вариант с переводом строки в конце. Отсутствие перевода строки можно рассматривать как нарушение формата хранения. Может там кроме перевода еще несколько последних разрядов обрезано, корректно ли читать такое? Зависит от задачи. Т.к. особенности не обсуждались - не стал дописывать.

По-хорошему после выхода из цикла while(), надо добавить сохранение
Код: plaintext
1.
2.
3.
if (store) {
// тут сохраняем результат
...


или наоборот сообщение об ошибке
Код: plaintext
1.
2.
3.
if (store) {
// нарушен формат хранения
...


Скорость разбора не поменяется.
...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39190541
alexy_black
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
может сначала профилировщиком прогнать и замеры сделать - сколько вобще занимает ввод вывод.. обычно это разовые операции: прочитать файл, основная работа по модификации, записать файл..

я думаю, что даже если разогнать парсер в 30 раз, на конечной производительности это никак не скажется. особенно если это не с файла ввода, а человек что-нибудь пишет: он будет писать гораздо дольше любого парсера.
...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39190658
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexy_blackя думаю, что даже если разогнать парсер в 30 раз, на конечной производительности это никак не скажется. особенно если это не с файла ввода, а человек что-нибудь пишет: он будет писать гораздо дольше любого парсера.
Ни разу не видел людей вбивающих инфу в консоль. Лабы студентов не рассматриваем.

Но многократно встречаются задачи: взять инфу полученную извне (файлы) и что-то с ней поделать. Например 18740263
...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39190964
alexy_black
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TНи разу не видел людей вбивающих инфу в консоль. гы, ну да, меня через форум не видно :) я постоянно сижу по ssh на хостинге, да ин на домашнем компе тоже в консоли..

Dima TНо многократно встречаются задачи: взять инфу полученную извне (файлы) и что-то с ней поделать.поделать что? например распарсить на регулярках.. думаю если увеличить скорость чтения файла в 30 раз, то это будет примерно такое же увеличение производительности как ускорение регулярок в 2 раза..

да и к тому же чтение с диска медленное в принцепе (если конечно не из файловой системы в оперативке).
...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39190976
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexy_blackDima TНо многократно встречаются задачи: взять инфу полученную извне (файлы) и что-то с ней поделать.поделать что?
сцылку зачем стер? То и поделать. Например скачать тот файлик с умершими паспортами, распарсить и подготовить к использованию, т.е. к проверке паспорта на валидность.

alexy_blackдумаю если увеличить скорость чтения файла в 30 раз, то это будет примерно такое же увеличение производительности как ускорение регулярок в 2 раза..
Ничего не понял, давай код, затестим.
...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39191026
alexy_black
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ссылку я прочитал.. просто не стоит же задача "прочитать паспортные данные и вырубится". например выделить людей по какому-то признаку. вот те же ругулярки - найти людей с фамилией подходящей под регулярку..

я о коде и говорил - тут без профилировщика не обойтись..

а если говрить о каком-то нереально большом кол-ве людей, то скорее нужна база данных - читаешь небольшой индекс а там все написано где читать о нужно человеке.
...
Рейтинг: 0 / 0
printf vs потоковый ввод/вывод
    #39191743
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
alexy_blackссылку я прочитал.. просто не стоит же задача "прочитать паспортные данные и вырубится". например выделить людей по какому-то признаку. вот те же ругулярки - найти людей с фамилией подходящей под регулярку..
Я же писал, прочитать данные и подготовить к использованию. Даже "найти людей с фамилией подходящей под регулярку.." можно гораздо быстрее если данные в которых искать заранее подготовлены к поиску. Например люди отсортированы по фамилии, а в регулярке задана первая буква Х. Остается проверить только всех на букву Х, что гораздо быстрее чем проверить вообще всех.
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
printf vs потоковый ввод/вывод
    #39627110
зеленый админ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А знаете, было забил уже давно на тему, но вот случайно наткнулся.
https://stackoverflow.com/questions/9371238/why-is-reading-lines-from-stdin-much-slower-in-c-than-python?rq=1

Т.е. при вводе как минимум проблема в синхронизации между iostream объектами и old-school FILE*.

Одна строчка
Код: plaintext
1.
std::ios_base::sync_with_stdio(false);



и код взлетает...
...
Рейтинг: 0 / 0
26 сообщений из 26, показаны все 2 страниц
Форумы / C++ [игнор отключен] [закрыт для гостей] / printf vs потоковый ввод/вывод
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]