Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2008.03.23;
Скачать: CL | DM;

Вниз

Про динамические массивы   Найти похожие ветки 

 
Blind Guardian   (2008-02-08 18:50) [0]

Здравствуйте. Парочка вопросов о динамических массивах.

1) Вот в си шарп есть два таких понятия: multidimensional и jugged массивы. И те и те - могут быть многомерными, но в массивах первого типа все элементы одного уровня имеют одну длину. То есть, массив - это всегда, как бы, параллелепипед. У Jugged array же элементами могут быть массивы разной длины. В хелпе ясно сказано, что jugged работают медленнее, чем multidimensional. В Дельфи же все многомерные динамические массивы могут иметь в качестве элементов массивы с разными длинами. Можно ли утверждать, что в дельфи динамический массив-параллелепипед работает медленнее, чем мог бы?

2) В программе у меня циклически выделяется по одному элементу для динамического массива (setLength(ar,n+1); inc(n);) Но программа будет работать намного быстрее, если я буду выделять память блоками, а по окончании выделения обрежу ненужный хвост. Вопросы: можно ли с помощью каких нибудь директив компилятору заставить его автоматически выделять память блоками? Блоки из скольки элементов рациональнее добавлять?


 
ketmar ©   (2008-02-08 18:53) [1]

хотел трактат написать, но пиво кончилось. вкратце:
1. фигня.
2. фигня.

---
Understanding is not required. Only obedience.


 
clickmaker ©   (2008-02-08 18:55) [2]


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

нет.
Но можно себя заставить написать AllocMem или юзать более удобные хранилища, такие как List, например. Там оно уже прикручено. Capacity и все такое


 
Palladin ©   (2008-02-08 18:58) [3]

когда то я писал класс работы с безмерно многомерными массивами...
1. бред
2. посыл не бред, но директива бред
пиво только началось...


 
ketmar ©   (2008-02-08 18:59) [4]

Удалено модератором


 
Palladin ©   (2008-02-08 19:32) [5]

йогурта чтоли? :)


 
Anatoly Podgoretsky ©   (2008-02-08 19:34) [6]

1. не верно
2. в общем неверно, в частном верно.


 
Джо ©   (2008-02-08 19:51) [7]

Удалено модератором


 
clickmaker ©   (2008-02-08 19:57) [8]


> Blind Guardian   (08.02.08 18:50)

кстати. Чего рекомендуешь дунуть, чтобы массив представился параллелипипедом? Или тут грибочки, как минимум, нужны? o)


 
Anatoly Podgoretsky ©   (2008-02-08 20:03) [9]

> clickmaker  (08.02.2008 19:57:08)  [8]

Паралепипед, частный случай кривого массива.


 
clickmaker ©   (2008-02-08 20:05) [10]


>  [9] Anatoly Podgoretsky ©   (08.02.08 20:03)

кривого, в смысле плохо заполненного?


 
Palladin ©   (2008-02-08 20:05) [11]


> [7] Джо ©   (08.02.08 19:51)

нажраться всем формумом - это будет исторический момент...


 
Palladin ©   (2008-02-08 20:06) [12]


> [10] clickmaker ©   (08.02.08 20:05)

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


 
Anatoly Podgoretsky ©   (2008-02-08 20:09) [13]

> clickmaker  (08.02.2008 20:05:10)  [10]

В смысле не паралелипипед, а кривулина.


 
clickmaker ©   (2008-02-08 20:10) [14]


> а одно разным или тоже одинаковым

трехмерный, да еще и кривой массив?
слава Аллаху, у меня в проектах такого нет... o)


 
Anatoly Podgoretsky ©   (2008-02-08 20:11) [15]

> clickmaker  (08.02.2008 20:10:14)  [14]

Это еж какой то получается, а не массив


 
DiamondShark ©   (2008-02-08 20:19) [16]


> Можно ли утверждать, что в дельфи динамический массив-параллелепипед
> работает медленнее, чем мог бы?

А CPU Window на что дадено?

var
 StatArr: array[0..10, 0..10] of integer;
 DynArr: array of array of integer;
...

var
 q: integer;
 i, j: integer;
...

 q := StatArr[5, 5];
      mov eax,[StatArr + $F0] Умный компилятор заранее посчитал смещение

 DynArr[5, 5] := q;
    mov ebx,[DynArr] Тоже всё весьма лаконично, ничего лишнего
    mov ebx,[ebx+$14]
    mov [ebx+$14],eax

...

 q := StatArr[i, j];
    imul eax,edx,$0b
    lea eax,[eax*4+StatArr]
    mov eax,[eax+ecx*4]

 DynArr[i, j] := q;
    mov ebx,[DynArr]
    mov edx,[ebx+edx*4]
    mov [edx+ecx*4],eax


Вывод:
- в случае константных индексов статический массив быстрее (очень немножко)
- в случае переменных индексов... хм... Хэнк его знает, я по тактам не считал. Вообще-то, тут требуется промежуточный доступ к памяти за указателем на второе измерение. Если включить извращённую фантазию, и представить, что страница с нужным куском первого измерения откачана, то, вообще говоря, доступ может потребовать неопределённо большого времени. Но, с другой стороны, кусок статического массива тоже может быть откачан ;)

Так что, по здравому рассуждению, это не тот вопрос, по которому стоит сильно переживать.


 
DiamondShark ©   (2008-02-08 20:28) [17]


> clickmaker ©   (08.02.08 19:57) [8]
>
> кстати. Чего рекомендуешь дунуть, чтобы массив представился
> параллелипипедом? Или тут грибочки, как минимум, нужны?
> o)

Не, параллелипипедом -- это на и на трезвую (но немножко распаренную) голову можно. А вот тором представить, или бутылкой Клейна -- тут без синтетиков не обойтись.


 
AlexWlad ©   (2008-02-08 21:36) [18]


> Anatoly Podgoretsky ©   (08.02.08 20:03) [9]
>
> > clickmaker  (08.02.2008 19:57:08)  [8]
>
> Паралепипед, частный случай кривого массива.


Эта-пять... маладец...


 
Palladin ©   (2008-02-08 21:37) [19]

Кстати обратное тоже справедливо...


 
AlexWlad ©   (2008-02-08 21:37) [20]

Удалено модератором


 
AlexWlad ©   (2008-02-08 21:39) [21]

Удалено модератором


 
Palladin ©   (2008-02-08 21:40) [22]

Удалено модератором


 
Blind Guardian   (2008-02-08 22:06) [23]

1. Jagged и multidimensional
http://www.mycode.ws/index.php?elif=ucsharp/arrays.aspx.htm
В C Sharp имеется три основных типа массивов: одномерные, многомерные и неровные(jagged)
...
Неровные (jagged) массивы - это, по сути, массивы массивов.
...
Отметим, что многомерные массивы являются важным отличием от других подобных языков (Java), ибо по сравнению с неровными массивами, обеспечивают гораздо большую производительность.


2.
Программа показывает, за какое время выделаются 10000000 байт по одному, и за сколько - по 1000.

program Project2;

{$APPTYPE CONSOLE}

uses
 SysUtils;

const
 c=10000000;
 block=1000;

var
 i1,n1,n2:integer;
 ar:array of byte;
 d1:double;

begin
 n1:=0;
 d1:=gettime;
 //Выделяем по 1 элементу
 for i1:=1 to c do begin
   inc(n1);
   setLength(ar,n1);
 end;
 writeln(gettime-d1:0:15);
 n1:=0;
 n2:=0;
 setLength(ar,0);
 d1:=gettime;
 //Выделяем блоками
 for i1:=1 to c do begin
   inc(n1);
   if n1>n2 then begin
     inc(n2,block);
     setLength(ar,n2);
   end;
 end;
 setLength(ar,n1);
 writeln(gettime-d1:0:15);
 readln;
end.

У меня эта программа вывела следующее:

0.000030555555556
0.000000914351852

Выигрыш во времени примерно в 33 раза.


 
Blind Guardian   (2008-02-08 22:21) [24]

и в чем я не прав?...


 
Palladin ©   (2008-02-08 22:24) [25]

в том что ты решил что неправ


 
Sapersky   (2008-02-09 19:17) [26]

1.
q := StatArr[i, j];
   imul eax,edx,$0b
   lea eax,[eax*4+StatArr]
   mov eax,[eax+ecx*4]

DynArr[i, j] := q;
   mov ebx,[DynArr]
   mov edx,[ebx+edx*4]
   mov [edx+ecx*4],eax


А если "в условиях, приближенных к боевым":

For i:=0 to 9 do
  For j:=0 to 9 do
    StatArr[i, j] := q;

For i:=0 to 9 do
  For j:=0 to 9 do
    DynArr[i, j] := q;

... то разница есть, в случае статического массива компилятор использует инкремент указателя, в случае динамического - на каждой итерации заново рассчитывает адрес элемента.
Т.е. - да, динамический должен быть медленнее, хотя на сколько конкретно - не замерял.
В качестве альтернативы можно использовать "двумерный массив-указатель", по аналогии со свойством Pixels из библиотеки FastLIB:

Type
 PArray    =^TArray;
 TArray    = array[0..0] of Integer;
 PArr2D  =^TArr2D;
 TArr2D  = array[0..0]of PArray;
Var  DynArr2 : PArr2D;
GetMem(DynArr2, 10 * 10 * SizeOf(Integer));
For i:=0 to 9 do
  For j:=0 to 9 do
    DynArr2[j, i] := q; // внимание! индексы пишутся в обратном порядке!
FreeMem(DynArr2);

Впрочем, компилятор и здесь считает адрес на каждой итерации - получается всего на одну команду меньше, чем с дин. массивом, за счёт более простой структуры (данные выделяются "одним куском"; наверное, так же устроен и multidimensional из C#).
Вывод - если всерьёз боремся за скорость, нужно вручную расписывать цикл на указателях (что, собственно, и делается в той же FastLIB).

2.
Да, выделять блоками - быстрее. Для D7 и более ранних к тому же уменьшает фрагментацию, которая при использовании SetLength(Length+1) может привести к преждевременному out of memory. Здесь:
http://sapersky.narod.ru/files/Arrays.rar
пример работы с дин. массивом в стиле TList - Length(Array) играет роль Capacity, реальная длина хранится в отдельной переменной. При "росте" массива выделяется в два раза больше, чем было, что может показаться несколько расточительным, зато минимизирует кол-во перевыделений (помнится, Джоэл Спольски именно так и рекомендовал делать, правда, применительно к менеджеру памяти Windows, не дельфийскому). Если нужна экономия - можно использовать алгоритм аналогичный TList.Grow.



Страницы: 1 вся ветка

Текущий архив: 2008.03.23;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.013 c
15-1202446356
ketmar
2008-02-08 07:52
2008.03.23
музыка a-la End Zone — Thalatta Et Thanatos


2-1203511255
Ultimate
2008-02-20 15:40
2008.03.23
Эффекты появления


15-1202479294
Kerk
2008-02-08 17:01
2008.03.23
Возможно буду оригинален


2-1204052315
Эрни
2008-02-26 21:58
2008.03.23
Как найти набор последовательных символов в файле


11-1186121703
BMouradov
2007-08-03 10:15
2008.03.23
Поворот изображений