Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Накладные расходы стандартных контейнеров 
:(
    Опции темы
W4FhLF
Дата 7.3.2012, 17:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


Профиль
Группа: Участник Клуба
Сообщений: 2831
Регистрация: 2.12.2006

Репутация: 20
Всего: 121



Есть у меня в программе двумерный массив, который хранит некоторые значения (POD типы), допустим double. Известно, что размер массива по одному из измерений не превышает максимальное значение unsigned short.
Строятся эти массивы один раз и новые элементы в них добавляются нечасто. А вот обращение к ij-ому элементу осуществляется десятки и сотни миллионов раз.

Проблема в том, что в большинстве случаев заполнены они только на 30-70%
Т.е. массивы могут занимать приличный объём (например 10000*10000*sizeof(double) = 800 мб) и экономия получается весьма ощутима если отбросить пустые элементы.

Ну думаю дай засуну их в какой-нибудь стандартный контейнер типа std::map<unsigned, double> или std::unordered_map<unsigned, double>. В конце-концов у последнего сложность О(1), что выглядит совсем как массив, хотя на практике конечно же медленнее. В качестве ключа всегда можно сделать: key = j + i*cols_num, где i,j - строка и столбец массива, соответственно.

Каково же было моё удивление, когда я обнаружил, что контейнеры эти занимают в ~10 раз больше памяти, чем массив. Т.е. даже массив, который заполнен только на 30%, будет занимать в 3 раза меньше памяти, чем map или unordered_map. Это в Visual C++ 2010.

Размер элемента в контейнерах можно выразить как:
(sizeof(key) + sizeof(value) + factor)
Этот фактор зависит от реализации библиотеки, в моём случае составляет порядка 60 байт на одну запись, что совсем неприемлемо.

Кто какие решения может предложить? 

Это сообщение отредактировал(а) W4FhLF - 7.3.2012, 20:15


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
boostcoder
Дата 7.3.2012, 18:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Цитата(W4FhLF @  7.3.2012,  17:39 Найти цитируемый пост)
я обнаружил, что контейнеры эти занимают в памяти в ~10 раз больше памяти, чем массив

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

Цитата(W4FhLF @  7.3.2012,  17:39 Найти цитируемый пост)
Кто какие решения может предложить?

а в чем вопрос?
PM WWW   Вверх
W4FhLF
Дата 7.3.2012, 19:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


Профиль
Группа: Участник Клуба
Сообщений: 2831
Регистрация: 2.12.2006

Репутация: 20
Всего: 121



Вопрос как хранить полупустой массив (неважно, двумерный или одномерный, т.к. любой многомерный массив может быть представлен как одномерный) оптимально с точки зрения памяти и случайного доступа к элементам. 

Это сообщение отредактировал(а) W4FhLF - 7.3.2012, 20:26


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
boostcoder
Дата 7.3.2012, 19:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



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

PM WWW   Вверх
rumit7
Дата 7.3.2012, 19:28 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 16.6.2011

Репутация: 6
Всего: 7



Цитата(W4FhLF @ 7.3.2012,  19:11)
Вопрос как хранить полупустой двумерный массив оптимально с точки зрения памяти и случайного доступа к элементам.

Может быть так http://evgeny-lazin.blogspot.com/2011/06/blog-post.html
PM MAIL   Вверх
W4FhLF
Дата 7.3.2012, 19:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


Профиль
Группа: Участник Клуба
Сообщений: 2831
Регистрация: 2.12.2006

Репутация: 20
Всего: 121



Цитата

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


Таким образом ничего не экономится, даже наоборот.

Добавлено через 4 минуты и 4 секунды
rumit7, это не будет работать на массивах размером больше sizeof(int)*8

Добавлено через 5 минут и 42 секунды
Точнее работать будет, если использовать что-то вроде std::bitset или свой вариант, но тогда накладные расходы на доступ будут огромные, хотя по памяти этот вариант выглядит интересно. 

Это сообщение отредактировал(а) W4FhLF - 7.3.2012, 19:31


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
rumit7
Дата 7.3.2012, 19:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 71
Регистрация: 16.6.2011

Репутация: 6
Всего: 7



Цитата(W4FhLF @ 7.3.2012,  19:30)
rumit7, это не будет работать на массивах размером больше sizeof(int)*8

Добавлено @ 19:36
Точнее работать будет, если использовать что-то вроде std::bitset или свой вариант, но тогда накладные расходы на доступ будут огромные, хотя по памяти этот вариант выглядит интересно.

Я сомневаюсь на счет огромных расходов. Во всяком случае, если std::bitset окажется столь медленным, то можно и свою реализацию заточить под данный проект. Если так подумать, то что такое свой bitset? Это массив 32-битных масок (на 64-битных системах можно и 64-битные маски хранить сразу). Нам нужны две операции: 1) доступ к конкретному биту (т.е. смещение внутри массива масок + битовая операция + иногда обновление маски) и 2) постоянный контроль кол-ва установленных бит для всего массива масок (ну это обычный целочисленный счетчик).

Я думаю, выжав максимум можно приблизиться к оригинальному времени массива.. ну во всяком случае для двумерного массива - не проиграть слишком много..
PM MAIL   Вверх
feodorv
Дата 7.3.2012, 20:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Цитата(rumit7 @  7.3.2012,  20:59 Найти цитируемый пост)
постоянный контроль кол-ва установленных бит для всего массива масок (ну это обычный целочисленный счетчик)

Чешу тыкву со времён этой ветки. Не пойму, почему дело ограничивается обычным целочисленным счётчиком:
Цитата

Для получения индекса i-го элемента в массиве, мы должны выполнить следующие операции:
    int bit = 1 << i; 
    if (mask & bit == 0) return null;
    int index = numberOfSetBits(mask & (bit - 1));
    return array[index]; 

bit - всегда степень двойки, а (bit-1) - двоичное число из i единиц. Таким образом, нужно считать число установленных бит в позициях (0,i-1) (для i > 0), а это для битового набора произвольной длины задача не столь тривиальная. В общем, одним целочисленным счётчиком не отделаться...


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
W4FhLF
Дата 7.3.2012, 20:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


Профиль
Группа: Участник Клуба
Сообщений: 2831
Регистрация: 2.12.2006

Репутация: 20
Всего: 121



rumit7, для массива размером 1000000 в котором только половина значений нелувые у тебя будет 15625 64х битных числа, которые будут хранить маску и собственно массив из 500000 ненулевых элементов. Нужно обратить к i-му элементу. Как быстро вычислить его позицию в массиве ненулевых элементов?


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
borisbn
Дата 7.3.2012, 20:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 22
Всего: 135



Цитата(W4FhLF @  7.3.2012,  17:39 Найти цитируемый пост)
Каково же было моё удивление, когда я обнаружил, что контейнеры эти занимают в ~10 раз больше памяти, чем массив.

Debug или Release ?


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
feodorv
Дата 7.3.2012, 20:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Между прочим, в той ветке была дана ссылка не некую библиотеку sparcelib++. Я её не смотрел, но, может, она решит проблему?


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
W4FhLF
Дата 7.3.2012, 20:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


Профиль
Группа: Участник Клуба
Сообщений: 2831
Регистрация: 2.12.2006

Репутация: 20
Всего: 121



borisbn, release конечно.

Добавлено через 2 минуты и 53 секунды
Цитата(feodorv @ 7.3.2012,  20:36)
Между прочим, в той ветке была дана ссылка не некую библиотеку sparcelib++. Я её не смотрел, но, может, она решит проблему?

Судя по названию речь идёт о разряженных массивах. То есть когда количество ненулевых элементов много меньше общего числа элементов.


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
feodorv
Дата 7.3.2012, 21:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Цитата(W4FhLF @  7.3.2012,  21:45 Найти цитируемый пост)
То есть когда количество ненулевых элементов много меньше общего числа элементов. 

О "много меньше" там ни слова. Более того, даже если все элементы матрицы ненулевые, то всё равно библиотекой можно пользоваться (будут накладные расходы по памяти и доступу). 
Хранение данных там чуть более своеобразно, чем прямой путь решения. В любом случае, пользоваться самой библиотекой смысла нет (уж больно она математизирована), но ведь можно подсмотреть, как она устроена smile

Добавлено через 6 минут и 53 секунды
Всё же, возвращаясь к постановке задачи:

Цитата(W4FhLF @  7.3.2012,  18:39 Найти цитируемый пост)
новые элементы в них добавляются нечасто. А вот обращение к ij-ому элементу осуществляется десятки и сотни миллионов раз.

Проблема в том, что в большинстве случаев заполнены они только на 30-70%


Насколько важна экономия памяти по сравнению со снижением скорости доступа? По-моему, лучше простого массива здесь ничего не придумаешь...


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
W4FhLF
Дата 7.3.2012, 22:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


found myself
****


Профиль
Группа: Участник Клуба
Сообщений: 2831
Регистрация: 2.12.2006

Репутация: 20
Всего: 121



feodorv, с форматами хранения разряженных матриц я знаком. Они эффективны когда бОльшая часть элементов == 0, к тому же время доступа там в лучшем случае логарифмическое. 

По поводу того, что лучше двумерного массива ничего не найти я догадывался ещё до создания этой. smile


--------------------
"Бог умер" © Ницше
"Ницше умер" © Бог
PM ICQ   Вверх
feodorv
Дата 7.3.2012, 22:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 11
Всего: 45



Цитата(W4FhLF @  7.3.2012,  23:03 Найти цитируемый пост)
По поводу того, что лучше двумерного массива ничего не найти я догадывался ещё до создания этой. 

Ага, понятно  smile 

Меня смущает (даже больше чем "объём vs доступ") то, что там линейные массивы, размером в число ненулевых элементов. При добавлении нового ненулевого элемента можно нарваться на перезаказ памяти нехилого размера (а непрерывного участка памяти такого размера может и не оказаться в наличии после нескольких перезаказов...)

Если же заранее известен размер двумерного массива, то ничего перезаказывать не нужно.

Цитата(W4FhLF @  7.3.2012,  23:03 Найти цитируемый пост)
к тому же время доступа там в лучшем случае логарифмическое

Гм. А где оно не логарифмическое?)))


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0857 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.