Неперемещаемые динамические массивы

Вопросы программирования на Free Pascal, использования компилятора и утилит.

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

Неперемещаемые динамические массивы

Сообщение SeZuka » 30.07.2013 19:16:02

Возможно ли сделать чтобы при изменении размера динамического массива с помощью SetLength, сам он не перемещался в памяти, т.е. указатель оставался неизменным?
SeZuka
постоялец
 
Сообщения: 209
Зарегистрирован: 05.09.2012 14:58:05

Re: Неперемещаемые динамические массивы

Сообщение Mirage » 30.07.2013 22:24:19

Нет, т.к. для увеличения размера может не хватить свободного места до следующего занятого куска.
Хотя от менеджера памяти зависит.
Mirage
энтузиаст
 
Сообщения: 881
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia

Re: Неперемещаемые динамические массивы

Сообщение debi12345 » 30.07.2013 22:27:18

Он вызывает LIBC/CRT "REALLOC" - там надо и смотреть.
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Re: Неперемещаемые динамические массивы

Сообщение sign » 31.07.2013 10:38:24

Закладываясь на постоянство указателя в памяти, вы закладываете мину в свою программу.
sign
энтузиаст
 
Сообщения: 1131
Зарегистрирован: 30.08.2009 09:20:53

Re: Неперемещаемые динамические массивы

Сообщение SeZuka » 31.07.2013 11:00:26

sign писал(а):Закладываясь на постоянство указателя в памяти, вы закладываете мину в свою программу.

Уже наступил на эту мину, потому и спросил. Пока временно решил проблему выделением большего куска памяти сразу, без дальнейшего увеличения.
SeZuka
постоялец
 
Сообщения: 209
Зарегистрирован: 05.09.2012 14:58:05

Re: Неперемещаемые динамические массивы

Сообщение zub » 31.07.2013 13:21:22

>>Закладываясь на постоянство указателя в памяти, вы закладываете мину в свою программу.
Тут можно уточнить - "начиная писать программу вы закладываете мину в свою программу"))

SeZuka
динамический массив на то и придуман чтоб уйти от указателей. не храните адрес элемента, храните его индекс и всё будет ОК
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Неперемещаемые динамические массивы

Сообщение SeZuka » 31.07.2013 15:34:10

zub писал(а): не храните адрес элемента, храните его индекс и всё будет ОК

как один из вариантов решения, но это сильно усложняет конструкцию, см. далее

Оригинальный код с указателями:
Код: Выделить всё
var
  Strings: array of PChar; // массив с указателями на начало строки в хранилище
  Storage: array of Byte; // хранилище строк
  s: String;
  i: Integer;
  ...
begin
  ...
  s := Strings[i]; // получение строки по ее номеру
  ...

Код с индексами:
Код: Выделить всё
var
  Strings: array of Integer; // массив с индексами на начало строки в хранилище
  Storage: array of Byte; // хранилище строк
  s: String;
  i: Integer;
  ...
begin
  ...
  s := PChar(@Storage[Strings[i]]); // получение строки по ее номеру
  ...

Согласитесь Strings[i] куда понятней и проще чем PChar(@Storage[Strings[i]])
SeZuka
постоялец
 
Сообщения: 209
Зарегистрирован: 05.09.2012 14:58:05

Re: Неперемещаемые динамические массивы

Сообщение zub » 31.07.2013 15:53:46

ну извиняйте)) такова жизнь. либо обеспечить неперераспределение участка памяти (потеряв "динамичность" массива), либо обращаться к элементам массива общепринятыми безопасными способами
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Неперемещаемые динамические массивы

Сообщение Mirage » 31.07.2013 15:59:35

s := Storage[i] подойдет?
Где Storage - класс, у которого есть default array property, выдающий строку по индексу.
Причем он же может как считать адрес по второму методу, так и по первому, автоматом производя фикс-ап указателей при изменении размера.
Единственное что, уже выданные строки могут стать невалидными при изменении размера. Хотя это проблема всех вариантов.

Я так понял, что данные строк почему-то хранятся в каком-то куске памяти, вместо того, чтобы просто управляться менеджером памяти.
В этом случае, у этого самого Storage возникает нетривиальная логика, которая до этого выполнялась менеджером памяти, и которую логично инкапсулировать в классе.
Mirage
энтузиаст
 
Сообщения: 881
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia

Re: Неперемещаемые динамические массивы

Сообщение SeZuka » 31.07.2013 17:11:38

Mirage писал(а):Я так понял, что данные строк почему-то хранятся в каком-то куске памяти, вместо того, чтобы просто управляться менеджером памяти.

Суть задачи: работа ведется с тысячами строк получаемых из файла, сначала создается массив строк в памяти, параллельно сортируясь по алфавиту, затем по ним ведется поиск, затем преобразования, ну и вывод в файл. Создание массива с сортировкой занимает примерно треть от всего объема алгоритма. Так вот заменив всего одну строчку отвечающую за копирование строки в массив:

Код: Выделить всё
  Strings[i] := StrNew(PChar(S));

на пару строк дополнительного кода:

Код: Выделить всё
   Strings[i] := @Storage[StoragePos];
  CopyMemory(Strings[i], PChar(S), Length(S)+1);
  Inc(StoragePos, Length(S)+1);

с индексами это выглядит так:

Код: Выделить всё
   Strings[i] := StoragePos;
  CopyMemory(@Storage[StoragePos], PChar(S), Length(S)+1);
  Inc(StoragePos, Length(S)+1);

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

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

Нет тут никакой нетривиальной логики, есть указатель на начало свободной памяти, при копировании очередной строки он просто перемещается на ее конец (см. код), и если очередная строка выходит за пределы, то просто увеличивается размер Storage, при помощи SetLength, вот и все.
SeZuka
постоялец
 
Сообщения: 209
Зарегистрирован: 05.09.2012 14:58:05

Re: Неперемещаемые динамические массивы

Сообщение Vapaamies » 31.07.2013 17:31:48

SeZuka писал(а):Создание массива с сортировкой занимает примерно треть от всего объема алгоритма.

И правильно, ибо нефиг. Двоичные деревья именно для этого и придумали.

SeZuka писал(а):То есть заменив тысячи выделений маленьких кусочков памяти под каждую строку, на один большой кусок где строки лежат друг за другом, получили уменьшение времени работы всего алгоритма в разы!

Мне для компилятора пришлось разработать собственный класс строк, разрешающий доступ только на чтение к большому буферу без копирования данных. Кроме того, чтобы класть строки в контейнеры, они нужны именно в виде классов.
Аватара пользователя
Vapaamies
постоялец
 
Сообщения: 292
Зарегистрирован: 24.07.2012 22:37:59
Откуда: Санкт-Петербург

Re: Неперемещаемые динамические массивы

Сообщение Mirage » 31.07.2013 17:39:15

Странно это. Какой менеджер памяти используется?
Для FastMM, например, выделить тысячи кусков памяти для строк не проблема.
Тут либо менеджер памяти сильно тормозит, либо алгоритм больше ничего не делает, кроме выделения памяти.

Память можно вообще не выделять, а замапить файл в память. В этом случае, кусок с данными будет иметь один и тот же адрес.
Останется только пройтись и построить массив Strings[].

Если же маппинг файла не подходит, то остается подход с созданием специализированного менеджера памяти. Который, собственно, и применяется по всей видимости. Просто автор этого не осознает.
Но нетривиальная логика у такого менеджера таки имеется, т.к. без оной решение не работает, о чем, собственно, топик.
Надо отслеживать изменения расположения данных и учитывать это, производя корректировку указателей.
Можно, кстати, хранить относительные указатели, тогда при выдаче строки можно просто сложить адрес массива-хранилища и относительный указатель.

Но спрятать это все за интерфейсом очень стоит, т.к. это например позволяет начать с тривиальной реализации, с очень большим массивом фиксированного размера. А потом оптимизировать реализацию хранилища, не трогая основной код. Если понадобится.
Mirage
энтузиаст
 
Сообщения: 881
Зарегистрирован: 06.05.2005 20:29:07
Откуда: Russia

Re: Неперемещаемые динамические массивы

Сообщение debi12345 » 31.07.2013 19:09:22

Хм... А когда происходит ресайзинг массива (инвалидирующий шифты от начала массива )? В отдельном треде пареллельно работе алгоритма ?
Аватара пользователя
debi12345
долгожитель
 
Сообщения: 5761
Зарегистрирован: 10.05.2006 23:41:15
Откуда: Ташкент (Узбекистан)

Re: Неперемещаемые динамические массивы

Сообщение Kemet » 31.07.2013 20:01:50

сделай тогда что-то вроде chunkedstring - массив, где хранятся указатели на массивы символов одинаковой длины. тогда решейпить придется только массив чанков, а сами они не будут менять адреса размещения, т.е. нужные тебе адреса останутся на месте. правда несколько усложниться алгоритм размещения и извлечения строк, но не так уж сильно, к тому же лучше это обернуть в соответствующий класс
Kemet
постоялец
 
Сообщения: 241
Зарегистрирован: 10.02.2010 19:28:32
Откуда: Временно оккупированная территория

Re: Неперемещаемые динамические массивы

Сообщение SeZuka » 31.07.2013 20:32:00

Vapaamies писал(а):Двоичные деревья именно для этого и придумали.

Ну а я по вашему методом пузырька что ли сортирую? 10 операций сравнения для 1000 строк и строка стоит в нужном месте.
Mirage писал(а):Странно это. Какой менеджер памяти используется?

Стандартный. FastMM не пробовал.
Mirage писал(а):либо алгоритм больше ничего не делает, кроме выделения памяти

Алгоритм создает словарь для текста, затем для этого же текста выводит в файл уже коды из словаря.
Mirage писал(а):Память можно вообще не выделять, а замапить файл в память.

Была такая мысль, но так как еще имеется предварительное преобразование регистра текста, пока от нее отказались.
Mirage писал(а):Но нетривиальная логика у такого менеджера таки имеется, т.к. без оной решение не работает, о чем, собственно, топик.

Решение было написано менее чем за 5 минут, просто прилетела мысль и захотелось попробовать, из плюсов сильно порадовала скорость работы, из минусов - на больших объемах рушились данные, как выяснилось из-за ресайза хранилища, указатели на строки оставались, а сами строки перемещались в памяти. Почему собственно и создал топик, думал может есть какое-нибудь "волшебное" слово типа fixed или static для динамических массивов.
Mirage писал(а):Можно, кстати, хранить относительные указатели, тогда при выдаче строки можно просто сложить адрес массива-хранилища и относительный указатель.

Так это тоже самое что и индексы, на которые кстати все и переделал.
debi12345 писал(а):Хм... А когда происходит ресайзинг массива (инвалидирующий шифты от начала массива )? В отдельном треде пареллельно работе алгоритма ?

Все в одном треде. Перед копированием строки проверяется, влезет ли она в остаток хранилища, если нет, то хранилище расширяется.
SeZuka
постоялец
 
Сообщения: 209
Зарегистрирован: 05.09.2012 14:58:05

След.

Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2

Рейтинг@Mail.ru
cron