LINUX.ORG.RU

mmap памяти в память


1

3

Можно ли сделать mmap не файла, а куска памяти?

Задача такая: у меня есть массив данных double[] и алгоритм, который в процессе работы этот массив меняет. При этом алгоритм должен вызываться много раз на первоначальных данных, т.е. напрямую менять их нельзя. Особенность такова, что в хорошем случае (таких большинство) он изменит лишь малую часть массива, но в плохом изменит его весь. В результате получается, что если тупо делать копию данных для каждого вызова алгоритма, большую часть времени программа копирует данные (фактически зря, потому что менять надо будет мало). А если не копировать данные, а делать std::map/unordered_map только с изменившимися значениями, всё начинает работать медленно из-за плохих вариантов, и профайлер показывает что время тратится в кишках map и аллокаторах.

В общем, нужно что-то типа гибридного решения: без мапы, но и чтобы всё не копировать. Показалось логичным использовать возможности виртуальной памяти и сделать что-то типа copy on write, чтобы при изменении страницы копировалась только она одна. Как такое можно сделать без костылей типа записи исходного массива в файл?

★★★★★

запускаешь один процесс, иницилизируешь массив в памяти, делаешь форк - есть две одинаковых копии, но в разных процессах. В процессе изменения данных ОС через CoW делает что тебе нужно. Соответственно, для каждых входных параметров форкаемся от процесса родителя.

mashina ★★★★★ ()

COW aka lazy map в линуксовом mmap с горбатых времён.

Анонимный приватный mmap можно (MAP_PRIVATE, MAP_ANONYMOUS).

mv ★★★★★ ()
Последнее исправление: mv (всего исправлений: 1)

нет, в линупсе такое напрямую сделать нельзя (хотя я так и не понял, почему).

как правильно подсказали выше, нужно юзать shared memory. в linux несколько разных api для доступа к ней (posix, sysv (эти двое описаны в shm_overview(7)), просто руками в tmpfs), все они в разной степени уродливы и неудобны.

выбирай, какой больше нравится.

anonymous ()

Возможно проще будет сделать вручную. Разбить массив на «страницы», т.е. сделать двумерным double[][], и в случае чего копировать страницы целиком. Сам массив превратится в массив ссылок на страницы. Размер страницы желательно делать так, чтобы он влезал в хотя бы в кеш L2.

soomrack ★★★ ()
Последнее исправление: soomrack (всего исправлений: 1)
Ответ на: комментарий от mv

COW aka lazy map в линуксовом mmap с горбатых времён.
Анонимный приватный mmap можно (MAP_PRIVATE, MAP_ANONYMOUS)

Это не делает того что мне нужно.

нет, в линупсе такое напрямую сделать нельзя

Понял, спасибо. Кстати, вопрос был не про линупс, а про «кросс-платформенно».

Возможно проще будет сделать вручную. Разбить массив на «страницы», т.е. сделать двумерным double[][], и в случае чего копировать страницы целиком.

Двумерность тут совершенно не нужна. Гораздо лучше (в плане оверхеда по памяти, минимизации косвенных обращений и фрагментации кучи) оставить тот же одномерный массив, но добавить рядом битовую маску флажков инициализированности страниц. Read в зависимости от флажка читает из себя либо оригинала, а write копирует страницу и поднимает флажок. Ну, там на самом деле не read и write а operator[] и const operator[].

Собственно, так и сделал - получил прирост в полтора раза, чисто копирования памяти стало меньше не порядок. Думается, это в любом случае эффективней VM, ибо page fault всё-таки затратная штука, и страницы эффективней брать намного меньше 4k. Видимо действительно под размер строки кэша - у меня быстрее всего получилось 32-64 байта.

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

slovazap ★★★★★ ()
Ответ на: комментарий от slovazap

Думается, это в любом случае эффективней VM, ибо page fault всё-таки затратная штука

По сравнению с копированием страницы - не очень.

и страницы эффективней брать намного меньше 4k

Не на x86.

mv ★★★★★ ()
Последнее исправление: mv (всего исправлений: 1)

YO DAWG, YOU CAN PUT SHMEM INTO YOUR SHMEM SO YOU CAN MMAP WHILE YOU MMAP

anonymous ()
Ответ на: комментарий от slovazap

Поясни.

PAGE_SIZE 4096. Меньше, IIRC, не бывает.

mv ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.