Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > Слишком большой массив?


Автор: Alemand 30.11.2010, 01:39
Добрый день!
Пишу программу в Delphi, попытался создать двумерный массив 1000x1000 элементов (даже не Real, а Single). Программа компилируется, но при попытке присвоить какое-нибудь значение элементу массива выдаётся сообщение "Stack overflow"... Вроде размер не такой большой - миллион элементов, если тип Single, то каждый - 4 байта, а максимальный размер до 2 Gb, насколько я знаю. Или миллион элементов в массиве - это слишком много?
Кроме того, мне дальше придётся работать с трёхмерными массивами 1000x1000x1000, но тут я понимаю вообще шансов на успех нет?

Автор: remax 30.11.2010, 02:42
Конечно стека не хватит если объявлять массивы такого размера внутри процедуры. Объявляй как глобальный массив и все будет ок.  Хотя, возможно, и надо пересмотреть идеологию проги, чтобы не пользовать такие огромные массивы....

Автор: skyboy 30.11.2010, 15:17
а если создавать объект? он же не в стеке создастся, да?
динамические массива, кстати, в стеке создаются?

Добавлено через 1 минуту и 3 секунды
и последний вопрос: а что за данные в массиве? не http://ru.wikipedia.org/wiki/%D0%A0%D0%B0%D0%B7%D1%80%D0%B5%D0%B6%D1%91%D0%BD%D0%BD%D1%8B%D0%B9_%D0%BC%D0%B0%D1%81%D1%81%D0%B8%D0%B2 ли он, этот массив? если разреженный, то хранить лучше по-другому, компактнее.

Автор: Alemand 1.12.2010, 21:59
remax, спасибо за совет, двумерный случай заработал!
А вот с трёхмерным не знаю что делать - просчитывать по чуть-чуть и всё время записывать информацию в файл, очищая после этого массив?

Вот код для трёхмерного случая, который у меня получился:
Код

unit lsm3d;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Math, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

const Points = 5;
      h = 0.1;
      xmax = Round(100/h);
      ymax = Round(100/h);
      zmax = Round(100/h);
      dt = 0.00025;
      b = 1;
      dtau = 0.1*h;
var
  Form1      : TForm1;
  dnosign    : array[1..xmax,1..ymax,1..zmax] of single;
  dsign      : array[1..xmax,1..ymax,1..zmax] of single;
  phi        : array[1..xmax,1..ymax,1..zmax] of single;
  phi1        : array[1..xmax,1..ymax,1..zmax] of single;
  X,Y,Z      : array[1..Points] of single;
  graf        : array[1..xmax,1..ymax,1..zmax] of shortint;
  



implementation

{$R *.dfm}


procedure TForm1.Button1Click(Sender: TObject);
  var i,j,k,q, maxx, maxy, maxz, minx, miny, minz : Integer;
      temp1,temp2 : single;
      a1,a2,a3,a4,a5,a6 : Integer;
      grad_plus, grad_minus, phi_x_plus, phi_x_minus, phi_y_plus, phi_y_minus, phi_z_plus, phi_z_minus : single;
begin


  X[1]  := 70.0; X[2]  := 69.7; X[3]  := 69.1; X[4]  := 67.7; X[5]  := 66.2;
  Y[1]  := 50.1; Y[2]  := 53.2; Y[3]  := 56.2; Y[4]  := 59.1; Y[5]  := 61.8;
  Z[1]  := 30.0; Z[2]  := 30.3; Z[3]  := 31.0; Z[4]  := 32.2; Z[5]  := 33.8;

  // Вычисление расстояния от каждой точки сетки до множества данных
  for i:=1 to xmax  do
    for j:=1 to ymax  do
      for q:=1 to zmax do
        begin
          temp1:=1000;
          for k:=1 to Points do begin
            temp2 := sqrt((i*h - X[k])*(i*h - X[k]) + (j*h - Y[k])*(j*h - Y[k]) + (q*h-Z[k])*(q*h-Z[k]));
            if temp1>temp2 then temp1 := temp2;
          end;
          dnosign[i,j,q] := temp1;
        end;

  // Нахождение минимальных и максимальных элементов в массивах X и Y
  minx:=1; miny:=1; minz := 1; maxx:=1; maxy:=1; maxz:=1;
  for k:=2 to Points do
    begin
      if X[k]<X[minx] then minx := k;
      if Y[k]<Y[miny] then miny := k;
      if Z[k]<Z[minz] then minz := k;
      if X[k]>X[maxx] then maxx := k;
      if Y[k]>Y[maxy] then maxy := k;
      if Z[k]>Z[maxz] then maxz := k;
    end;

  // Задание границ квадрата, ограничивающего исходное множество данных
  a1 := Round(X[minx]/h)-Round(500*h);
  a2 := Round(X[maxx]/h)+Round(500*h);
  a3 := Round(Y[miny]/h)-Round(500*h);
  a4 := Round(Y[maxy]/h)+Round(500*h);
  a5 := Round(Z[minz]/h)-Round(500*h);
  a6 := Round(Z[maxz]/h)+Round(500*h);

  // Вычисление расстояния со знаком
  for i:=1 to xmax  do
    for j:=1 to ymax  do
      for q:=1 to zmax do
        begin
          if((i>a1)and(i<a2)and(j>a3)and(j<a4)and(q>a5)and(q<a6)) then
            dsign[i,j,q] := - dnosign[i,j,q]
          else
            dsign[i,j,q] := dnosign[i,j,q];
        end;

  // Задание начального приближения
  for i:=1 to xmax  do
    for j:=1 to ymax  do
      for q:=1 to zmax do
        phi[i,j,q] := dsign[i,j,q];


  // Решение уравнения LS
  for k:= 1 to 12000 do
    begin
      
    for i:=1 to xmax  do
      for j:=1 to ymax  do
        for q:=1 to zmax do

          begin

          // Вычисление производных
          
          if(i>1)and(i<xmax)and(j>1)and(j<ymax)and(q>1)and(q<zmax) then
          begin
            phi_x_plus  := (phi[i+1,j,q]-phi[i,j,q])/h;
            phi_x_minus := (phi[i,j,q]-phi[i-1,j,q])/h;
            phi_y_plus  := (phi[i,j+1,q]-phi[i,j,q])/h;
            phi_y_minus := (phi[i,j,q]-phi[i,j-1,q])/h;
            phi_z_plus  := (phi[i,j,q+1]-phi[i,j,q])/h;
            phi_z_minus := (phi[i,j,q]-phi[i,j,q-1])/h;
          end;


          grad_plus  := sqrt(max(phi_x_minus,0)*max(phi_x_minus,0) + min(phi_x_plus,0)*min(phi_x_plus,0) + max(phi_y_minus,0)*max(phi_y_minus,0) + min(phi_y_plus,0)*min(phi_y_plus,0) + max(phi_z_minus,0)*max(phi_z_minus,0) + min(phi_z_plus,0)*min(phi_z_plus,0));

          grad_minus := sqrt(max(phi_x_plus,0)*max(phi_x_plus,0) + min(phi_x_minus,0)*min(phi_x_minus,0) + max(phi_y_plus,0)*max(phi_y_plus,0) + min(phi_y_minus,0)*min(phi_y_minus,0) + max(phi_z_plus,0)*max(phi_z_plus,0) + min(phi_z_minus,0)*min(phi_z_minus,0));

          phi1[i,j,q] := phi[i,j,q] - dt*(max(dsign[i,j,q],0)*grad_plus + min(dsign[i,j,q],0)*grad_minus);

        end;//i,j,q

    end;//k

    for i:=1 to xmax  do
      for j:=1 to ymax  do
        for q :=1 to zmax do
          begin
            if(phi1[i,j,q]<=0) then graf[i,j,q]:=-1
            else graf[i,j,q] := 1;
          end;

  end;//procedure

end.


Добавлено через 4 минуты и 37 секунд
skyboy, я пока не знаю, как создавать объекты, к сожалению, только перешёл из MatLab'а в Delphi, потому что кроме Паскаля не знаю других языков, а MatLab на этой моей задаче совсем загулся smile А вы думаете, что это поможет работать с такими большими массивами? Ведь они больше 2 Гб, разрешённых в Windows? Если поможет, то попробую разобраться с объектами.
Массив не разреженный, к сожалению...

Автор: Alexeis 1.12.2010, 23:12
Цитата(Alemand @  1.12.2010,  22:59 Найти цитируемый пост)
Ведь они больше 2 Гб, разрешённых в Windows? Если поможет, то попробую разобраться с объектами.

  Тогда скорее всего нужно что из Fortran/C++ в 64х битной версии.

Автор: skyboy 2.12.2010, 00:03
Цитата(Alemand @  30.11.2010,  00:39 Найти цитируемый пост)
Кроме того, мне дальше придётся работать с трёхмерными массивами 1000x1000x1000

вот это я пропустил. да, проблемка.
простое решение - перейти к х64: чтоб и программа, и ОС поддерживала адресацию намного большую 2 миллиардов.

Автор: remax 2.12.2010, 17:12
Немного не патриотично, но! почему бы не сделать ту часть, что работает с большим массивом на MATLAB. Ну, а все остальное можно сделать в Delphi. Понимаете, MATLAB изначально  идеологически заточен под работу с матрицами. В принципе, можно и интерфейсную часть на нем сделать, хотя эта область в нем слабовата - и с точки зрения возможностей и с точки зрения разработки.  Т.е., я бы в такой ситуации или переработал бы алгоритм, с целью уменьшения размера массива или сделал бы прогу на Delphi, из которой вызывался бы скрипт на MATLAB. 

Автор: skyboy 2.12.2010, 17:34
а ещё можно в памяти обрабатывать небольшой кусок данных. а остальное держать в файле/файлах. страшно, зато просто.

Автор: remax 2.12.2010, 17:43
Да, я тоже про файлы думал, но, наверное, очень замедлится расчет... 
Скорее надо обратиться не к файлу, а к СУБД.  smile   Заодно, многие моменты (поиск максимальных значений, заполнение массива  graf и т.д.) смогут быть реализованы простыми запросами... ))))) smile 

Автор: Alemand 2.12.2010, 21:53
remax, я изначально делал программу в MatLab, но как раз из-за этих больших массивов и подался в Delphi, потому что подумал, что здесь больше возможностей по работе с теми же файлами и вообще считает быстрее.

Автор: remax 3.12.2010, 01:06
Цитата(Alemand @ 2.12.2010,  21:53)
remax, я изначально делал программу в MatLab, но как раз из-за этих больших массивов и подался в Delphi, потому что подумал, что здесь больше возможностей по работе с теми же файлами и вообще считает быстрее.

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

Matlab начинает работать медленно с большими массивами в 2х случаях:
1) Если не стоят в нужных местах ";" и поэтому не подавляется вывод на экран результатов по изменению каждой ячейки массива. Скорость при этом падает на 1-2 порядка и сопоставима с тормознутым MatCad. Исправляется легко и быстро.

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

В принципе, уже есть возможность сравнить скорость работы Matlab и Delphi в равных условиях. Я, так понимаю, что с двумерным массивом (1000*1000) Ваша программа уже работает? Сравните для этого случая. Если окажется, что Matlab медленнее (в чем я лично сомневаюсь), то тогда сделаем на Delphi. Вариантов реализации много....

П.С. А если быстрее Matlab, то версию (1000*1000*1000) сделаем тоже на нем...  smile 

Автор: remax 4.12.2010, 23:32
Вот, возможно, решение ваших проблем - http://matrix.kladovka.net.ru/?page=about

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)