Сейчас на форуме: jinoweb, bartolomeo (+5 невидимых)

 eXeL@B —› Программирование —› Записать / считать вектор из файла (c++)
Посл.ответ Сообщение


Ранг: 216.9 (наставник), 85thx
Активность: 0.310.15
Статус: Участник
X-Literator

Создано: 07 апреля 2017 05:57 · Поправил: Crawler
· Личное сообщение · #1

Привет.

Есть программа, которая читает очень много строк из файла в vector<string>.

Это крайне долго.

Вопрос: как записать вектор в файл так, чтобы потом его можно было тупо считать из файла одним куском в буфер памяти, а затем сделать из этого куска вектор - сразу, как со структурой, которую ты считываешь и пользуешься через указатель?
С каким-нибудь char-массивом это понятно и легко, а с вектором я что-то туплю.

Спасибо.

-----
Харе курить веники и нюхать клей, к вам едет из Америки бог Шива, и он еврей.





Ранг: 1053.6 (!!!!), 1078thx
Активность: 1.060.81
Статус: Участник

Создано: 07 апреля 2017 07:10
· Личное сообщение · #2

нечеткая задача которая имеет множества решений
1) не использовать вектор. написать свой оптимизированный
2) использовать вектор. заранее делая большой reverve
3) использовать вектор читая данные из памяти. а не из файла. которые предварительно туда загружены(в память)
4) написать свой аллокатор для вектора. который будет юзать к мемори мап для быстрого доступа к данным
итд...фантазиям нет предела




Ранг: 216.9 (наставник), 85thx
Активность: 0.310.15
Статус: Участник
X-Literator

Создано: 07 апреля 2017 07:19 · Поправил: Crawler
· Личное сообщение · #3

reversecode
А что тут нечеткого? Нужно записать вектор в файл, а потом целиком считать его.

1) нет смысла, лучше не выйдет;
2) reserve почти не влияет на скорость процесса, проверено clock()
3) совсем не влияет на скорость, т.к. файл в современных ОС почти наверняка читается из памяти;
4) надо подумать

-----
Харе курить веники и нюхать клей, к вам едет из Америки бог Шива, и он еврей.




Ранг: -0.7 (гость), 170thx
Активность: 0.540
Статус: Участник

Создано: 07 апреля 2017 08:07
· Личное сообщение · #4

вам нужна сериализация.
как пример, если нужно что то сложнее гугл в помощь.



Ранг: 431.7 (мудрец), 390thx
Активность: 0.730.32
Статус: Участник

Создано: 07 апреля 2017 11:34 · Поправил: dosprog
· Личное сообщение · #5

Crawler пишет:
4) надо подумать

Так 4) это же считай то же, что и 3) , только от (с)микрософта...
самое внушительно звучит это 1), если при предыдущем сохранении на диске строки там проиндексированы.
Без предварительной индексации на какой-то выигрыш по времени вряд ли удастся расчитывать





Ранг: 158.4 (ветеран), 123thx
Активность: 0.140.49
Статус: Участник

Создано: 07 апреля 2017 12:25
· Личное сообщение · #6

Crawler пишет:
1) нет смысла, лучше не выйдет;

Лучше не выйдет, если ты напишешь такую же реализацию, но если писать под задачу, скорость вырастет на порядки. Например, можно хранить строки одним массивом, где они будут разделены нулем, а в векторе хранить только указатели на начало каждой строки. Так, выделение памяти, чтение и запись в файл будут выполняться одним вызовом апи, но после чтения нужно будет в дополнительном цикле пробежаться по массиву данных и построить массив указателей.



Ранг: -0.7 (гость), 170thx
Активность: 0.540
Статус: Участник

Создано: 07 апреля 2017 12:33
· Личное сообщение · #7

rmn пишет: Лучше не выйдет

Поддерживаю. Если вектор начинает упираться в скорость, нужно не решать проблему через задницу, пытаясь заставить делать vector то для чего он в принципе не предназначен. Раз данных много и появилась подобная проблема, лучше подумать о какой то мелкой базе, а не делать очередной велосипед с квадратными колесами.




Ранг: 681.5 (! !), 405thx
Активность: 0.420.21
Статус: Участник
ALIEN Hack Team

Создано: 07 апреля 2017 12:49
· Личное сообщение · #8

Crawler

Вариант 3, который советовал reversecode. Поясню в деталях:

1. Берём файл на диске (он представляет собой набор строк, разделённых каким-нибудь \n или \r\rn) и маппим его целиком без разбора в память.
2. Читаем строки (которые пока являются const char[]) в объекты типа std::string и кладём их в вектор.
3. Анмапим файл.

-----
Stuck to the plan, always think that we would stand up, never ran.




Ранг: 590.6 (!), 408thx
Активность: 0.360.18
Статус: Модератор

Создано: 07 апреля 2017 12:58
· Личное сообщение · #9

rmn
Это ничем не отличается от vector<const char* const> и не надо свое ничего писать. Вычитываем в один vector<uint8_t> и дальше мапим вектор указателей на первый. Но в таком случае если данные изменяются нужно городить свой велосипед с COW (copy-on-write). А если не изменяются проще вообще отказаться от vector<string> в пользу const char* const[].

-----
старый пень




Ранг: 158.4 (ветеран), 123thx
Активность: 0.140.49
Статус: Участник

Создано: 07 апреля 2017 13:24
· Личное сообщение · #10

r_e пишет:
Это ничем не отличается от vector<const char* const> и не надо свое ничего писать.

Это отличается от vector<string>, где нужно будет столько раз вызвать аллокатор, сколько строк в массиве.




Ранг: 216.9 (наставник), 85thx
Активность: 0.310.15
Статус: Участник
X-Literator

Создано: 07 апреля 2017 14:09
· Личное сообщение · #11

ARCHANGEL, да не повысит это производительность.

Я сам тестировал это только вчера, но сильно подозревал заранее, что ничего не выйдет. Так и вышло. Наверняка реализация функции чтения так и делает. Не терзает же она жесткий диск.

-----
Харе курить веники и нюхать клей, к вам едет из Америки бог Шива, и он еврей.





Ранг: 681.5 (! !), 405thx
Активность: 0.420.21
Статус: Участник
ALIEN Hack Team

Создано: 07 апреля 2017 14:12
· Личное сообщение · #12

Crawler
Покажи народу код и образец файла. Может, что-то и порешается.

-----
Stuck to the plan, always think that we would stand up, never ran.




Ранг: -0.7 (гость), 170thx
Активность: 0.540
Статус: Участник

Создано: 07 апреля 2017 14:19
· Личное сообщение · #13

я бы взял https://sqlite.org/inmemorydb.html миллионы записей спокойно вертит и нет проблем с чтением\записью.




Ранг: 1053.6 (!!!!), 1078thx
Активность: 1.060.81
Статус: Участник

Создано: 07 апреля 2017 17:30
· Личное сообщение · #14

когда ставится задача в лоб - хочу хрустальным шариком забивать гвозди и при этом его не разбить
то нужно задачу с самого нуля пересматривать,
может там и не вектор нужен, может там нужно что то по другом переделывать
а не пытаться это все пропихнуть через вектор




Ранг: 216.9 (наставник), 85thx
Активность: 0.310.15
Статус: Участник
X-Literator

Создано: 07 апреля 2017 20:23 · Поправил: Crawler
· Личное сообщение · #15

Всем спасибо.

Решил действительно не совсем через вектор, REVERSECODE тут оказался прав.

Сначала посчитал максимально возможную длину строки из текстового файла, потом переделал файл в другой формат с фиксированной длиной строки. Если строка была меньше максимальной длины, она дополнялась нолями.

То есть всё было записано в char [25].

Получившийся файл считываю в память целиком, потом создаю массив вроде такого:

Code:
  1. unsigned int number_of_strings = filesize/25;
  2. char **strings = new char *[number_of_strings];


А потом просто создаю вектор (для удобства работы, хотя это уже на фиг не нужно):

Code:
  1. vector <string *> str_pointers;


И присваиваю ему указатели на char-строки. Работает:

Code:
  1. for (int i=0; i<number_of_strings; i++)
  2. {
  3.   str_pointers.push_back((string *) &strings[i]);
  4. }


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

-----
Харе курить веники и нюхать клей, к вам едет из Америки бог Шива, и он еврей.




Ранг: 431.7 (мудрец), 390thx
Активность: 0.730.32
Статус: Участник

Создано: 07 апреля 2017 20:29 · Поправил: dosprog
· Личное сообщение · #16

Не намного хуже была бы реализация с индексированием при предыдущем сохранении.
Головняка побольше зато в разы меньше места займёт на диске..

| Сообщение посчитали полезным: Crawler
 eXeL@B —› Программирование —› Записать / считать вектор из файла (c++)
:: Ваш ответ
Жирный  Курсив  Подчеркнутый  Перечеркнутый  {mpf5}  Код  Вставить ссылку 
:s1: :s2: :s3: :s4: :s5: :s6: :s7: :s8: :s9: :s10: :s11: :s12: :s13: :s14: :s15: :s16:


Максимальный размер аттача: 500KB.
Ваш логин: german1505 » Выход » ЛС
   Для печати Для печати