powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / как быстрее всего прочесть большой файл с числами, каждое с новой строки?
25 сообщений из 101, страница 4 из 5
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39118781
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,

ИМХУ это следствие. Закон Амдала никто не отменил. Все остальное - это следствие. Надо причину обходить.

lock-free алгоритмы зацепили тем что без явной потребности синхронизации потоков они не потребляют (точнее минимально потребляют) лишние ресурсы. Взять тут же задачу топика: если не требуется одновременно писать и читать с одного буфера, то зачем тратить ресурсы на синхронизацию? Синхронизация она же не бесплатная. Как-то я тут проводил тесты разных мутексов и т.п.
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39118791
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В нашем случае Амдал сдулся до 9 секунд.

Будем штурмовать рубеж?
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39118797
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonВ нашем случае Амдал сдулся до 9 секунд.

Будем штурмовать рубеж?
К 9 бы надо прийти для начала. Потом уже с Амдалом спорить.
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39118815
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TТам нет С++11
C без плюсов достаточно
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39119232
alexy_black
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
парни, не бейти сильно, не читал обсуждение до конца, но делаю вброс :)
наверное корутины самое то :) когда выполняется какое-либо условие, можно файл дальше не читать. если например, это произошло в начале файла, то сразу и готово! экономия почти 100%

boost.org/libs/coroutine2
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39119312
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Какое еще условие бро? У нас нет ничего подобного. Надо прочитать 100 млрд текстовых строк.
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39119345
alexy_black
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonКакое еще условие бро? У нас нет ничего подобного. Надо прочитать 100 млрд текстовых строк.
а потом что с ними делать? должно же быть хоть что-то нужное :)
хотя если просто прочитать, то корутины только затормозят процесс - придется прыгать на контекст... но если строк 100 млрд, а прочитав 99 млрд можно остановиться, то корутины сильно укорят, наверное :)
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39119388
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да не ко мне это вопрос. Но в общем случае, если афтор хочет гнать по ним аналитику
то я в принципе не понимаю мотивации останавливаться.

Или ты что-то другое хотел предложить?
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39119776
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Доделал, вроде работает но не быстро :(

Тестовый файл был 1 млрд. чисел. Файл 6 Гб.
На i7 (4 ядра) RAM 32 Гб
ТестВремя сек.Только чтение2.7Однопоточный разбор14.6Многопоточный12.9
На i5 (2 ядра + HT) RAM 4 Гб
ТестВремя сек.Только чтение34.3Однопоточный разбор55.6Многопоточный69.8
Исходник (все три теста и генератор файла)
Код: 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.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
#include <windows.h>
#include <time.h>
#include <process.h>
#include <stdio.h>

#define BUF_COUNT 128
#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 ...", 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("Read %d numbers CheckSum %X Time %f sec.\n", count, check, (double)(clock() - start) / CLOCKS_PER_SEC);
}

//Синхронный printf() из разных потоков
void mt_printf(const char* text, int value = -1) {
	static CRITICAL_SECTION cs;
	volatile static bool init = false;
	if(!init) {
		init = true;
		InitializeCriticalSectionAndSpinCount(&cs, 4000);
	}
	EnterCriticalSection(&cs);
	if(value == -1) {
		printf("%05d: %s\n", clock(), text);
	} else {
		printf("%05d: %s %d\n", clock(), text, value);
	}
	LeaveCriticalSection(&cs);
}

// Буфер
typedef struct {
	volatile long size;
	char data[BUF_SIZE];
} buf_t;

// Параметры потока чтения
typedef struct {
	const char* filename;
	HANDLE wait; // Event для ожидания
	volatile long wait_count; // Количество ожидающих
	CRITICAL_SECTION cs;
	buf_t buf[BUF_COUNT];
	volatile long buf_count; // Количество заполненных буферов
} param_t;


// Ожидание в пробуждением другого потока
void wait_one(param_t* param, HANDLE thread = NULL) {
	// Возобновление другого потока
	EnterCriticalSection(&param->cs);
	if(param->wait_count != 0) {
		SetEvent(param->wait); 
		Sleep(0);
		while(param->wait_count != 0) {
			//mt_printf("Warning: Sleep(1)");
			Sleep(1);
		}
	}
	// Ожидание
	ResetEvent(param->wait); 
	if(param->wait_count != 0) {
		mt_printf("Error: wake up");
		LeaveCriticalSection(&param->cs);
	} else {
		InterlockedExchangeAdd(&param->wait_count, 1);
		LeaveCriticalSection(&param->cs);
		if(thread) { // Дополнительно ожидать завершение потока
			HANDLE wait[2];
			wait[0] = param->wait;
			wait[1] = thread;
			if(WaitForMultipleObjects(2, wait, FALSE, 1000) == WAIT_TIMEOUT) {
				mt_printf("Error: wait timeout");
			}
		} else if(WaitForSingleObject(param->wait, 1000) == WAIT_TIMEOUT) {
			mt_printf("Error: wait timeout");
		}
		InterlockedExchangeAdd(&param->wait_count, -1);
	}
}

// Пробуждение спящих
void wake_up(param_t* param) {
	if(param->wait_count != 0 && param->buf_count > BUF_COUNT / 2) {
		EnterCriticalSection(&param->cs);
		if(param->wait_count != 0) {
			SetEvent(param->wait); 
			Sleep(0);
			while(param->wait_count != 0) {
				//mt_printf("Warning: Sleep(1)");
				Sleep(1);
			}
		}
		LeaveCriticalSection(&param->cs);
	}
}
// Поток чтения
unsigned __stdcall read_thread(void* par) {
	int count = 0; // счетчик запусков ожидания разбора
	param_t* param = (param_t*) par;
	FILE* file = fopen(param->filename, "rb");   
	if (file != NULL) { 
		long cur_buf = 0;
		size_t read = 0;
		// Чтение в buf[cur_buf]
		while ((read = fread(param->buf[cur_buf].data, 1, BUF_SIZE, file)) > 0) {
			// Установка размера прочитанного
			if(InterlockedExchange(&param->buf[cur_buf].size, read) != 0) {
				mt_printf("Error: Bufer not empty (1)");
				break;
			}
			#ifdef _DEBUG
			mt_printf("read end", cur_buf);
			#endif
			InterlockedExchangeAdd(&param->buf_count, 1);
			wake_up(param); // пробуждение разбора
			// следующий буфер
			cur_buf++;
			if(cur_buf == BUF_COUNT) cur_buf = 0;

			// Проверка что буфер пустой
			if(param->buf[cur_buf].size != 0) {
				// Ожидание пустого буфера
				#ifdef _DEBUG
				mt_printf("read wait", cur_buf);
				#endif
				wait_one(param);
				count++;
			}
			#ifdef _DEBUG
			mt_printf("read start", cur_buf);
			#endif
		}
		if(count > 0) mt_printf("read wait times", count);
	}
	//if(param->wait_count != 0) SetEvent(param->wait);
	_endthreadex(0);
	return 0;
}

void read_ints_mt(const char* filename) {
	clock_t start = clock();
	// Подготовка и запуск потока чтения
	param_t* param = (param_t*) calloc(1, sizeof(param_t));
	if(!param) {
		mt_printf("Error: no memory");
		return;
	}
	param->filename = filename;
	param->wait = CreateEvent(NULL, FALSE, FALSE, NULL);
	InitializeCriticalSection(&param->cs);
    unsigned th_id;
    HANDLE th = (HANDLE)_beginthreadex(NULL, 0, &read_thread, param, 0, &th_id );
	int wait_count = 0;
	// Разбор
	int n = 0;
	bool minus = false;
	bool store = false;
	bool overflow = false;
	int check = 0;
	int numbers_count = 0;
	size_t cur_buf = 0;
	buf_t* buf = NULL;
	while(1) {
		if(param->buf[cur_buf].size == 0) { // Нечего разбирать
			if(WaitForSingleObject(th, 0) != WAIT_TIMEOUT) break; // Поток приема завершен
			// Ожидание чтения
			#ifdef _DEBUG
			mt_printf("parse wait", cur_buf);
			#endif
			wait_count++;
			wait_one(param, th);
		}
		#ifdef _DEBUG
		mt_printf("parse start", cur_buf);
		#endif
		// Разбор буфера
		char* end = param->buf[cur_buf].data + param->buf[cur_buf].size;
		for(char* cur = param->buf[cur_buf].data; 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) {
						mt_printf("overflow");// переполнение
						overflow = false;
					} else {
						if(minus) {
							n = -n;
							minus = false;
						}
						check ^= n;
						//printf("%d\n", n);
						numbers_count++;
					}
					store = false;
					n = 0;
				}
				minus = (*cur == '-');
			}
		}
		// Пометка буфера разобранным
		if(InterlockedExchange(&(param->buf[cur_buf].size), 0) == 0) {
			if(WaitForSingleObject(th, 0) != WAIT_TIMEOUT) break; // Поток приема завершен
			mt_printf("Error: size == 0 (2)");
			break;
		}
		InterlockedExchangeAdd(&param->buf_count, -1);
		#ifdef _DEBUG
		mt_printf("parse end", cur_buf);
		#endif
		// Переход на следующий буфер
		cur_buf++;
		if(cur_buf == BUF_COUNT) cur_buf = 0;
	}
	WaitForSingleObject(th, INFINITE);
	printf("MT Read %d numbers CheckSum %X Wait %d times Time %f sec.\n", numbers_count, check, wait_count, (double)(clock() - start) / CLOCKS_PER_SEC);
	CloseHandle(th);
	CloseHandle(param->wait);
	DeleteCriticalSection(&param->cs);
	free(param);

}


int main(int argc, char* argv[])
{
	char file[] = "big.txt";
	create_file(file, 1000000000);
	//char file[] = "mini.txt";
	//create_file(file, 100000000);
	read_speed(file);
	read_ints(file);
	read_ints_mt(file);

	return 0;
}


С синхронизацией устал разбираться. Потоки догоняют друг-друга, один еще не успел в ожидание встать, второй уже все закончил и будит первого.
Вчера был вариант с двумя эвентами. По одному на каждый поток. Так он и не заработал. В итоге сделал один эвент на двоих и пробуждение второго если он спит во время усыпления первого. Но и то какой-то изврат получился. Даже Sleep(1) пришлось воткнуть. Функции wait_one() и wake_up()

Может кто идею подкинет как синхронизацию организовать?
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39119781
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima T, большое спасибо за бенчмарки. Сходу могу предположить что синхронизация происходит
слишком часто. Возможно имеет смысл увеличить размер чанка (блока) ?
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39119830
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Размеры тут
Код: plaintext
1.
2.
#define BUF_COUNT 128
#define BUF_SIZE 1024 * 8


BUF_COUNT кол-во буферов, BUF_SIZE размер одного
Работает по кольцу: чтение заполняет по кругу пока на заполненный не наткнется, разбор - разбирает пока на пустой не наткнется.

Забыл кол-во остановок (усыплений) добавить. Перетестил на i7 - оба потока по 4650 раз засыпали. Второй комп недоступен. Завтра только перемерю.

ИМХУ надо эту корявость в синхронизации менять. Вопрос на что? С виду простая задачка, но весь мозг об нее сломал.
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39120011
kolobok0
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,

оптимальный размер блока будет когда
время чтения блока = времени обработки этого блока


(круглый)
ЗЫ
И это апсолютно не максимальный буффер!!!
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39120086
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Перемерил на i5:
со 128 буферами по 8 Кб чтение засыпало 313 раз разбор 6286
сделал 128 по 64 Кб Вот лог трех запусков
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Use file big.txt
ONLY READ: Count 86380 blocks Time 57.236000 sec.
Read 1000000000 numbers CheckSum 4231 Time 57.205000 sec.
MT Read 1000000000 numbers CheckSum 4231 Wait 680 times Time 57.034000 sec.

Use file big.txt
ONLY READ: Count 86380 blocks Time 58.854000 sec.
Read 1000000000 numbers CheckSum 4231 Time 57.595000 sec.
MT Read 1000000000 numbers CheckSum 4231 Wait 701 times Time 58.828000 sec.

Use file big.txt
ONLY READ: Count 86380 blocks Time 64.600000 sec.
Read 1000000000 numbers CheckSum 4231 Time 60.949000 sec.
MT Read 1000000000 numbers CheckSum 4231 Wait 736 times Time 54.694000 sec.

Все три варианта сравнялись ))
Если в кэш не влазит и читается с HDD - время чтения величина переменная. Замерять тут что-то бесполезно.

PS Синхронизация один раз сглючила. Остались там какие-то косяки.
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39120308
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Понял в чем у меня проблема с синхронизацией. Думал что раз разбудили поток - значит ему есть что делать, а случаи если нечего - считал ошибкой.
В общем самый первый вариант был правильный. Просто не хватало проверки после пробуждения.

Результаты теста с буфером 64 Кб для МТ 128 буферов
На i7 (4 ядра) RAM 32 Гб
ТестВремя сек.Только чтение1.24Однопоточный разбор14.7Многопоточный13.6
Уходов в спячку: чтение - 1150, разбор - 5
На i5 (2 ядра + HT) RAM 4 Гб
ТестВремя сек.Только чтение55Однопоточный разбор55Многопоточный55
Уходов в спячку: чтение - 0, разбор - 650

Исходник
Код: 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.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
#include <windows.h>
#include <time.h>
#include <process.h>
#include <stdio.h>

#define BUF_COUNT 128
#define BUF_SIZE 1024 * 64

// Создание файла
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);
}

// Блочный парсер
class parser {
	int n;
	bool minus;
	bool store;
	bool overflow;
public:
	int count;
	int check;

	parser() {
		n = 0;
		count = 0;
		check = 0;
		minus = false;
		store = false;
		overflow = false;
	}

	void parse_block(const char* data, int size) {
		const char* end = data + size;
		for(const char* cur = data; 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 == '-');
			}
		}
	}
};

// Однопоточный вариант
void read_ints(const char* filename) {
	clock_t start = clock();
	FILE* file = fopen(filename, "rb");   
	parser p;
	if (file != NULL) { 
		char buffer[BUF_SIZE];
		size_t bytesRead = 0;
		while ((bytesRead = fread(buffer, 1, sizeof(buffer), file)) > 0) p.parse_block(buffer, bytesRead);
		fclose(file);
	}
	printf("Read %d numbers CheckSum %X Time %f sec.\n", p.count, p.check, (double)(clock() - start) / CLOCKS_PER_SEC);
}

// printf()
void mt_printf(const char* text, int value = -1) {
	if(value == -1) {
		printf("%05d: %s\n", clock(), text);
	} else {
		printf("%05d: %s %d\n", clock(), text, value);
	}
}

// Буфер
typedef struct {
	volatile long size;
	char data[BUF_SIZE];
} buf_t;

// Параметры потока чтения
typedef struct {
	const char* filename;
	HANDLE read_wait; // Event для ожидания чтения
	HANDLE parse_wait; // Event для ожидания разбора
	buf_t buf[BUF_COUNT];
	volatile long buf_count; // Количество заполненных буферов
	volatile long read_wait_count; // Счетчик засыпаний чтения
	volatile long read_result; // Результат завершения чтения
} param_t;

// Поток чтения
unsigned __stdcall read_thread(void* par) {
	param_t* param = (param_t*) par;
	FILE* file = fopen(param->filename, "rb");   
	if (file != NULL) { 
		long cur_buf = 0;
		size_t read = 0;
		while (1) {
			// Проверка что буфер пустой
			if(param->buf[cur_buf].size != 0) {
				// Ожидание пустого буфера
				if(WaitForSingleObject(param->read_wait, 1000) == WAIT_TIMEOUT) {
					mt_printf("Error: read wait timeout");
					break;
				}
				if(param->buf[cur_buf].size != 0) continue;
				param->read_wait_count++;
			}
			// Чтение в buf[cur_buf]
			size_t read = fread(param->buf[cur_buf].data, 1, BUF_SIZE, file);
			if(read == 0) { // Файл прочитан
				param->read_result = 1;
				break;
			}
			// Установка размера прочитанного
			if(InterlockedExchange(&param->buf[cur_buf].size, read) != 0) {
				mt_printf("Error: Bufer not empty (1)");
				break;
			}
			// пробуждение разбора если занято более половины буферов
			if(InterlockedExchangeAdd(&param->buf_count, 1) >= BUF_COUNT/2) {
				SetEvent(param->parse_wait);
			}
			// следующий буфер
			cur_buf++;
			if(cur_buf == BUF_COUNT) cur_buf = 0;
		}
	}
	_endthreadex(0);
	return 0;
}

void read_ints_mt(const char* filename) {
	clock_t start = clock();
	parser p;
	// Подготовка и запуск потока чтения
	param_t* param = (param_t*) calloc(1, sizeof(param_t));
	if(!param) {
		mt_printf("Error: no memory");
		return;
	}
	param->filename = filename;
	param->read_wait = CreateEvent(NULL, FALSE, FALSE, NULL);
	param->parse_wait = CreateEvent(NULL, FALSE, FALSE, NULL);
    unsigned th_id;
	HANDLE waits[2];
	waits[0] = param->parse_wait;
    waits[1] = (HANDLE)_beginthreadex(NULL, 0, &read_thread, param, 0, &th_id );
	int wait_count = 0;
	// Разбор
	size_t cur_buf = 0;
	buf_t* buf = NULL;
	while(1) {
		if(param->buf[cur_buf].size == 0) { 
			// Нечего разбирать
			if(WaitForSingleObject(waits[1], 0) != WAIT_TIMEOUT) break; // Поток приема завершен
			// Ожидание чтения
			if(WaitForMultipleObjects(2, waits, FALSE, 1000) == WAIT_TIMEOUT) {
				mt_printf("Error: parse wait timeout");
				break;
			}
			if(param->buf[cur_buf].size == 0) continue;
			wait_count++;
		}
		// Разбор буфера
		p.parse_block(param->buf[cur_buf].data, param->buf[cur_buf].size);
		// Пометка буфера разобранным
		if(InterlockedExchange(&(param->buf[cur_buf].size), 0) == 0) {
			mt_printf("Error: size == 0 (2)");
			break;
		}
		// пробуждение чтения если занято менее половины буферов
		if(InterlockedExchangeAdd(&param->buf_count, -1) <= BUF_COUNT/2) {
			SetEvent(param->read_wait);
		}
		// Переход на следующий буфер
		cur_buf++;
		if(cur_buf == BUF_COUNT) cur_buf = 0;
	}
	WaitForSingleObject(waits[1], INFINITE); // Ожидание завершения потока чтения
	if(param->read_result != 1) {
		mt_printf("Error: read not all");
	} else if(param->buf_count != 0) {
		mt_printf("Error: parse not all");
	}
	printf("MT Read %d numbers CheckSum %X Wait (R/P) %d/%d Time %f sec.\n", p.count, p.check, param->read_wait_count, wait_count, (double)(clock() - start) / CLOCKS_PER_SEC);
	CloseHandle(waits[1]);
	CloseHandle(param->parse_wait);
	CloseHandle(param->read_wait);
	free(param);
}


int main(int argc, char* argv[])
{
	printf("\nTest: size %d Kb count %d  Compile %s %s\n", BUF_SIZE / 1024, BUF_COUNT, __DATE__, __TIME__);
	char file[] = "big.txt";
	create_file(file, 1000000000);
	read_speed(file);
	read_ints(file);
	read_ints_mt(file);

	return 0;
}



PS ИМХУ бесполезно последовательное чтение параллелить: если данные в кэше - быстро прочитается, если с диска - ОС сама фоном упреждающее чтение делает.
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39120362
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TPS ИМХУ бесполезно последовательное чтение параллелить: если данные в кэше - быстро прочитается, если с диска - ОС сама фоном упреждающее чтение делает.
Есть мысли (только касамемо Windows)
1) Втопку упреждающее.
2) Покурить Джефри Рихтера. На тему Windows I/O
3) Отказаться от FILE*,fopen,fread и перейти к Windows-specific функциям которые описаны в MSDN.
4) Перетестировать заново.
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39120379
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дима sorry я по прежнему озабочен чортовой пендосской медициной. Горят сроки.
И не успеваю даже модерировать плюсы. Так что читать твои сорцы
буду только в СБ-ВС. I think...
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39120425
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ИМХУ быстрее не станет. Нечего тут больше оптимизировать. Забыл померить для второго случая (файл в кэш не влазит): Фар копирует в nul за 54 сек, тесты работают 55. Т.е. с учетом погрешностей примерно одинаково.
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39120450
Зимаргл
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
maytonDima TPS ИМХУ бесполезно последовательное чтение параллелить: если данные в кэше - быстро прочитается, если с диска - ОС сама фоном упреждающее чтение делает.
Есть мысли (только касамемо Windows)
1) Втопку упреждающее.
2) Покурить Джефри Рихтера. На тему Windows I/O
3) Отказаться от FILE*,fopen,fread и перейти к Windows-specific функциям которые описаны в MSDN.
4) Перетестировать заново.
Там флажки есть на опережающее чтение итп
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39120619
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Фух... заскочил на минутку.

Челы качните http://www.hdtune.com/ и посмотрите sequential read/write speed

Убежал...
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39123758
m_Sla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
идеи по парсеру
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
int table[16][16][16];

table[0][0][0] = 0;
...
table[1][2][3] = 123;
...
table[9][9][9] = 999;

int char_to_int_table(char str[])
{
    int  result=0;

    int a = str[0] - '0';
    int b = str[1] - '0';
    int c = str[2] - '0';

    result = table[ a ][ b ][ c ];

    return result;
}

уменьшаем кол-во умножений в 3 раза, но усложняется сам парсер
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39123770
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m_Slaуменьшаем кол-во умножений в 3 раза, но усложняется сам парсер
ИМХУ не взлетит. Умножение целых не такая уж и тяжелая операция.
Можно просто убрать умножение. Заменил n*10 на n<<3 + n<<1.
Затестил. Вообще ничего не изменилось. Время было 13.51 сек, стало 13.49. Это погрешности измерения. Возможно оптимизатор сам заменил и умножения изначально не было.
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39123775
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m_Slaуменьшаем кол-во умножений в 3 раза,
ага, индексация многомерного массива без умножений обходится

PS на интел архитектуре умножение на 10 обычно без команды умножения делается
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39123783
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропилага, индексация многомерного массива без умножений обходится
В данном случае обойдется: *4 легко заменяется на <<2
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39123785
m_Sla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропилm_Slaуменьшаем кол-во умножений в 3 раза,
ага, индексация многомерного массива без умножений обходится

PS на интел архитектуре умножение на 10 обычно без команды умножения делаетсятам два умножения на 16, делается сдвигами

а на 10 как умножается, на lea ?
...
Рейтинг: 0 / 0
как быстрее всего прочесть большой файл с числами, каждое с новой строки?
    #39123825
m_Sla
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
затестил, аппаратное умножение быстро работает
Intel Pentium CPU G2020
Код: 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.
2,559 попугая
           asm{
           mov eax,k
           add eax,eax
           lea eax,[4*eax+eax]
           mov k, eax
           }
           

2,762 попугая           
           asm{
           mov eax,k
           imul eax,eax,10
           mov k, eax
           }
           

2,62 попугая
           asm{
           mov eax,k
           mov edx,k
           shl eax,3
           add edx,edx
           add eax,edx
           mov k, eax
           }
...
Рейтинг: 0 / 0
25 сообщений из 101, страница 4 из 5
Форумы / C++ [игнор отключен] [закрыт для гостей] / как быстрее всего прочесть большой файл с числами, каждое с новой строки?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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