Шаблон мультиварианта.
От: Went  
Дата: 24.02.19 07:31
Оценка:
Доброго дня.
Все еще беспокоит проблема оптимального хранения данных в объекте, которые редко используются. Например, есть некий компонентный объект, у которого огромное множество инкарнаций используют только базовый набор данных, но некоторые используют специальные, причем в произвольных комбинациях. При этом, эти данные разнородные (нельзя завести под общий интерфейс и сложить отдельно) и меняются в процессе исполнения, то есть нельзя сделать шаблон с трейтами.
По мере раздумий пришел к такому мульти-варианту:
void f1()
{
  mystd::multivariant<int, int, string> x; // Пустой объект, в нем ничего нет
  x.get<2>() = "hello"; // Записали строку в 3-ю ячейку.
  ASSERT(!x.has<1>()); // У нас нет 2-го инта.
  x.get<1>() = 1; // 2-ий инт создался и в него записали 1
  ASSERT(x.has<1>()); // У нас есть 2-й инт.
  x.reset<1>(); // Теперь убрали.
}

Таким образом я могу "включать и выключать" любые части мультиварианта. При выключении объект удаляется.
Почему это не сделать набором std::optional, потому что они все едят память, в сумме это может набежать втрое или вдесятеро больше, чем объект в "компактном" виде. Почему не сделать это набором std::unique_ptr — потому что для каждой секции будет свое обращение к куче. А так — все лежит в последовательном буфере. Если объектов мало, они лежат прямо рядом, в статической части, если не помещаются — выделяются на куче. Размер статической части, например, может выбираться как размер наибольшего члена варианта, это уже вопрос оптимизации. Минус такого варианта в том, что операция доступа к тому или иному члену потребует времени, нужно будет посчитать размер предыдущих частей, чтобы найти смещение нужного члена. Ну и всякие "перемещения" при перевыделении памяти.

Вопрос такой: насколько это оправдано или "память давно не ресурс" и ее экономия вылезет большими потерями из-за более сложных алгоритмов доступа? Есть ли где-то такое реализованное?
Re: Шаблон мультиварианта.
От: _NN_ www.nemerleweb.com
Дата: 24.02.19 08:17
Оценка:
Здравствуйте, Went, Вы писали:

W>Доброго дня.

И вам того же.

W>Вопрос такой: насколько это оправдано или "память давно не ресурс" и ее экономия вылезет большими потерями из-за более сложных алгоритмов доступа? Есть ли где-то такое реализованное?


Память всё ещё ресурс, но не стоит злоупотреблять этим лозунгом.
Если у вас в итоге потребляемая память несколько Мб то тут нечего экономить.
Берёте то, что вам больше подходит.

Экономить на int и так не получится без ущерба производительности, обычно размер int равен или меньше размера указателя.
Чем собственно не подходит вариант unique_ptr<string> ?
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: Шаблон мультиварианта.
От: Went  
Дата: 24.02.19 18:44
Оценка:
Здравствуйте, _NN_, Вы писали:
_NN>Экономить на int и так не получится без ущерба производительности, обычно размер int равен или меньше размера указателя.
Ну, про int я писал как пример, а в реале — это небольшие структуры: пары векторов, контейнеры, но иногда неожиданно большие вещи.
_NN>Чем собственно не подходит вариант unique_ptr<string> ?
Потому что уник на каждую структуру потребует по указателю на каждый член варианта и будет выделять в лоб место в куче под каждую мелочь. Мой же умозрительный мультивариант обойдется (в простейшем случае) всего лишь одной битовой маской присутствия членов (да, ограничение на 32 или 64 члена) + указатель на начало буфера. И добавление новых членов в этот мультивариант будет иметь нулевые издержки по памяти, но, очевидно, линейно нарастающую сложность для доступа к члену (каждый следующий член будет требовать на 1 сложение больше).
Re: Шаблон мультиварианта.
От: PM  
Дата: 24.02.19 23:12
Оценка:
Здравствуйте, Went, Вы писали:

W>Вопрос такой: насколько это оправдано или "память давно не ресурс" и ее экономия вылезет большими потерями из-за более сложных алгоритмов доступа? Есть ли где-то такое реализованное?


Может быть, такое подойдет: https://github.com/izvolov/burst#-динамический-кортеж
Re[2]: Шаблон мультиварианта.
От: Went  
Дата: 25.02.19 06:40
Оценка:
Здравствуйте, PM, Вы писали:
PM>Может быть, такое подойдет: https://github.com/izvolov/burst#-динамический-кортеж
Близко, но не совсем то. Через это можно было бы реализовать мой мультивариант, но тогда накладные расходы вероятно превысят пользу от всей идеи в целом.
Ключевая разница — динамический кортеж поддерживает произвольное количество произвольных данных, а, значит, должен где-то хранить порядок записей, их длины, и, очевидно, делетеры для каждой из записей. В моем же случае типы записей известны на момент компиляции, а последовательность выводится из одной единственной битовой маски. Плюс для динамического кортежа потребуется карта соответствий — на каком индексе в этом кортеже хранится тот или иной элемент данных.
Re[3]: Шаблон мультиварианта.
От: _NN_ www.nemerleweb.com
Дата: 25.02.19 08:37
Оценка:
Здравствуйте, Went, Вы писали:

W>Здравствуйте, _NN_, Вы писали:

_NN>>Экономить на int и так не получится без ущерба производительности, обычно размер int равен или меньше размера указателя.
W>Ну, про int я писал как пример, а в реале — это небольшие структуры: пары векторов, контейнеры, но иногда неожиданно большие вещи.
_NN>>Чем собственно не подходит вариант unique_ptr<string> ?
W>Потому что уник на каждую структуру потребует по указателю на каждый член варианта и будет выделять в лоб место в куче под каждую мелочь. Мой же умозрительный мультивариант обойдется (в простейшем случае) всего лишь одной битовой маской присутствия членов (да, ограничение на 32 или 64 члена) + указатель на начало буфера. И добавление новых членов в этот мультивариант будет иметь нулевые издержки по памяти, но, очевидно, линейно нарастающую сложность для доступа к члену (каждый следующий член будет требовать на 1 сложение больше).

Вам нужен постоянный размер или динамический ? О каком добавлении идёт речь ?
Боюсь, придётся писать такую структуру данных самому.
Чтобы не выделять место под элементы есть optional но у него занимает место индикатор живучести объекта.
Как вариант можно сделать компактный optional где индникатор не будет в самом объекте типа:

Пример: https://github.com/akrzemi1/markable/blob/master/test_markable.cpp#L88
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[4]: Шаблон мультиварианта.
От: Went  
Дата: 25.02.19 09:02
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Вам нужен постоянный размер или динамический ? О каком добавлении идёт речь ?

Члены моего мультиварианта нельзя добавлять и убирать, как в векторе. Их можно включать или выключать. По сути, это optional-на-много-членов. Выгода относительно обычного optional в том, что факт существования хранится в общей битовой маске, а все члены — в едином куске памяти (в простом случае — в куче). В этом случае добавление многообразия новых возможных членов в пределах разрядности маски не будет нести никаких накладных расходов, потому что не будет требовать каждый раз создавать новый объект типа optional<>, статично живущий в теле объекта.
Re: Шаблон мультиварианта.
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 25.02.19 10:46
Оценка:
Здравствуйте, Went, Вы писали:

W>Доброго дня.

W>Все еще беспокоит проблема оптимального хранения данных в объекте, которые редко используются.
Ну напиши свой аллокатор что ли под это.
W>Вопрос такой: насколько это оправдано или "память давно не ресурс" и ее экономия вылезет большими потерями из-за более сложных алгоритмов доступа? Есть ли где-то такое реализованное?
Память ресурс для ресурсоёмких приложений или на серверной стороне. Если у тебя довольно простое приложение с небольшим количеством эелементов то можешь не экономить на "спичках". Вопрос целесообразнаости оптимизации.
Sic luceat lux!
Re: Шаблон мультиварианта.
От: sergii.p  
Дата: 25.02.19 14:35
Оценка:
Здравствуйте, Went, Вы писали:

можно хранить variant<Args> initial и vector<variant<Args>> additionalArgs и написать свой метод std::get который сначала лезет в initial, и если тот бросает исключение, перебирать additionalArgs. Можно протащить метод reserve для вектора наружу, тогда дополнительная память будет выделяться за одно new. Если различия в размере объектов не так велики, вполне приемлемый вариант получается.
Re: Шаблон мультиварианта.
От: Джо  
Дата: 28.02.19 01:39
Оценка:
W>Вопрос такой: насколько это оправдано или "память давно не ресурс" и ее экономия вылезет большими потерями из-за более сложных алгоритмов доступа? Есть ли где-то такое реализованное?

Мое понимание что память снова ресурс из-за того что теперь оптимизируют попадание в кэши: когда рабочие данные небольшие им проще располагаться в кэше процессора и это может сильно ускорить работу. Мне правда не вполне понятно как это можно проверить и границы применимости этой идее, обычно все что я видел это что заметное ускорение получают когда у вас много данных и алгоритм который их обрабатывает. Если ваш мультивариант может участвовать в такого рода алгоритмах то будет лучше если он будет занимать меньше памяти.
Re[2]: Шаблон мультиварианта.
От: Went  
Дата: 28.02.19 06:13
Оценка:
Здравствуйте, Джо, Вы писали:
Джо>Мое понимание что память снова ресурс из-за того что теперь оптимизируют попадание в кэши: когда рабочие данные небольшие им проще располагаться в кэше процессора и это может сильно ускорить работу. Мне правда не вполне понятно как это можно проверить и границы применимости этой идее, обычно все что я видел это что заметное ускорение получают когда у вас много данных и алгоритм который их обрабатывает. Если ваш мультивариант может участвовать в такого рода алгоритмах то будет лучше если он будет занимать меньше памяти.
Да, отчасти по попадание в кэши я и думал, экономя. Но, с другой стороны, если данные мультиварианта не будут помещаться в in-place буфер, то окажутся размазаны по куче, что, наверное, еще сильнее усложнит им попадание в кэш.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.