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

Вниз

Поясните пожалуйста работу с AWE на примере?   Найти похожие ветки 

 
bodomic ©   (2005-11-17 21:55) [0]

Привет всем!

У меня есть необходимость выделить для своей программы (для двух её массивов) очень много памяти, больше стандартных 2 Гб, желательно вообще 20-40 :)
Насколько я понял, это реально, и для этого надо использовать технологию AWE.
Никак не могу разобраться, как именно надо использовать набор функций, что писать в качестве параметров, как определить handle моего процесса хотя бы...

Кто-нибудь может пояснить на *конкретном* примере от и до, как мне выделить под массив данных много Гб памяти? Допустим, 40Гб подкачки я задал в Windows, разрешил пользователю фиксировать страницы в памяти, дальше как? :)

А то у меня чушь одна получается, точнее ничего не получается, а толковых примеров тоже ещё не нашёл :(
Спасибо


 
Anatoly Podgoretsky ©   (2005-11-17 22:00) [1]

Дельфи поддердивает только 2 гб


 
bodomic ©   (2005-11-17 22:40) [2]

Спасибо за быстрый ответ.

Хммм... я что-то не понял значит
http://podgoretsky.com/ftp/Docs/Delphi/Memory/awe/02-about.html
"AWE решает эту проблему путем разрешения приложению непосредственно адресовать гигантскую память, в то время как оно может использовать и обычную 32-х битную адресацию. AWE предоставляет для приложений возможность иметь под кеш более чем 4 Гб (при условии, что существует соответствующая физическая память)."
Неужели под физической памятью имеется ввиду сама оперативка, без файла подкачки? (по моим данным Windows XP, а тем более 2000, не больше 3 Гб оперативы понимают).
И что такое тогда "гигантская память"? 2Гб я и так забиваю, без всяких мудростей с AWE :)


 
MBo ©   (2005-11-18 07:29) [3]

Поскольку при работе с AWE, насколько я понимаю,  все равно не обеспечивается одновременный доступ к офигенному адресному пространству, а придется по очереди переключать страницы, проще поступить по-другому - самому организовать на диске большой файл, и работать с его Memory-Mapped отображением.


 
bodomic ©   (2005-11-18 09:59) [4]

MBo, а можно тоже какой-нибудь пример?
Когда я читал про Memory-Mapping, я почему-то понял всё наоборот - что маппить файл можно только в объём доступной оперативы, а не добавлять к нему. Поэтому стал читать про AWE. А всё вон как оборачивается :)


 
MBo ©   (2005-11-18 10:05) [5]

>маппить файл можно только в объём доступной оперативы
Да, но это не большая проблема.
Вместо того, чтобы напрямую объявлять огромный массив, можно организовать доступ через свойство класса, а в методе доступа переключать MapViewOfFile на нужный кусок разумного размера, скажем, 64 мегабайта. Поскольку доступ к данным в большинстве случаев происходит более-менее последовательно, переключения не обязательно будут слишком частыми.


 
bodomic ©   (2005-11-18 10:27) [6]

Так. Если я что-то тут понял:
Если у меня массив NxN, то я мапплю единовременно только N элементов. Это разумно, я так пробовал писать/читать в файл, выходило дико медленно и объёмно, в оперативу те же типы почему-то компактнее умещаются. В пропорции 1:40 где-то Ж8-0.
Так тот же массив, который в оперативку отображается в 2Гб, на винт разложится этак на 80 Гб.

Т.е. мне нужно сделать класс, у которого будет метод, скажем MyArray.Get(i,j), который будет маппить MapViewofFile(i*N) в оперативку и доставать j-й элемент, сместившись на столько-то байт относительно текущей позиции? А заполнить этот массив я смогу аналогично через MyArray.Put?

P.S.
Очень хочется живого примера :)
Я обычно самообразовываюсь по пути "рабочий пример -> разжевывание его мной через хелп/доки -> рабочий как надо код" :)


 
Leonid Troyanovsky ©   (2005-11-18 10:41) [7]


> bodomic ©   (18.11.05 10:27) [6]

> Очень хочется живого примера :)
> Я обычно самообразовываюсь по пути "рабочий пример -> разжевывание
> его мной через хелп/доки -> рабочий как надо код" :)


У Джефа Рихтера есть пример. Как раз с массивом.
Поищи Windows для профессионалов.

--
Regards, LVT.


 
bodomic ©   (2005-11-18 11:03) [8]


> У Джефа Рихтера есть пример. Как раз с массивом.

Спасибо, качаю.


 
MBo ©   (2005-11-18 13:28) [9]


type
 TIntArr = array[Word] of Integer;
 PIntArr = ^TIntArr;
 TArr = class
   constructor Create(const N: DWord);
   destructor Destroy; override;
 private
   FPage: DWord;
   FPageSize: DWord;
   FileSize: Int64;
   FileSizeLow, FileSizeHigh: DWord;
   HMap: THandle;
   PMap: PIntArr;
   function GetElement(y, x: DWord): Integer;
   procedure SetElement(y, x: DWord; const Value: Integer);
   procedure SetPage(const APage: DWord);
 public
   property Element[y, x: DWord]: Integer read GetElement write SetElement;
     default;
 end;

constructor TArr.Create(const N: DWord);
var
 FileHandle: THandle;
begin
 FPageSize := (N * SizeOf(Integer) + 65535) and $FFFF0000;
 FileSize := FPageSize * N;
 FileSizeLow := FileSize and $FFFFFFFF;
 FileSizeHigh := FileSize shr 32;
 FileHandle := CreateFile(PChar("C:\Test.dat"),
   GENERIC_READ + GENERIC_WRITE,
   FILE_SHARE_WRITE,
   nil, CREATE_ALWAYS,
   FILE_ATTRIBUTE_NORMAL, 0);
 if FileHandle = INVALID_HANDLE_VALUE then
   raise Exception.Create("Cannot create file ");
 HMap := CreateFileMapping(FileHandle, nil, PAGE_READWRITE,
   FileSizehigh, FileSizeLow, nil);

 CloseHandle(FileHandle);
 if HMap = 0 then
   raise Exception.Create("Cannot map file");
 SetPage(0);
end;

destructor TArr.Destroy;
begin
 UnMapViewOfFile(PMap);
 CloseHandle(HMap);
// to do: DeleteFile
  inherited Destroy;
end;

function TArr.GetElement(y, x: DWord): Integer;
begin
 if y <> FPage then
   SetPage(y);
 Result := PMap[x];
end;

procedure TArr.SetElement(y, x: DWord; const Value: Integer);
begin
 if y <> FPage then
   SetPage(y);
 PMap[x] := Value;
end;

procedure TArr.SetPage(const APage: DWord);
var
 FPos: Int64;
 FPosLow, FPosHigh: DWord;
begin
 FPage := APage;
 FPos := FPage * FPageSize;
 FPosLow := FPos and $FFFFFFFF;
 FPosHigh := FPos shr 32;
 PMap := MapViewOfFile(HMap, FILE_MAP_ALL_ACCESS, FPosHigh, FPosLow,
   FPageSize);
 if PMap = nil then
   raise Exception.Create("Cannot map view of file");
end;

//----------------------

procedure TForm1.Button1Click(Sender: TObject);
begin
 Arr := TArr.Create(1024);
 Arr[0, 0] := 4;
 Arr[1023, 1023] := 5;
 Caption := IntToStr(Arr[0, 0]) + " " + IntToStr(Arr[1023, 1023]);
 Arr.Free;
end;



 
bodomic ©   (2005-11-18 22:16) [10]


> MBo ©   (18.11.05 13:28) [9]


Вот это ничего себе :)
Спасибо большое, буду разбираться с примером и с Рихтером.
Всем спасибо.


 
bodomic ©   (2005-11-22 10:28) [11]


> MBo ©   (18.11.05 13:28) [9]

А вот такой вопрос странный выявился:
При использовании отображения файла в память страницы в файле подкачки после использования не освобождаются, и следовательно нарастает выделенная приложению память в файле подкачки (от чего и хотелось уйти :)) - когда дело доходит до 2 Гб, меня точно также выбрасывает с Out of Memory, как и при прямом использовании оперативы...
Вставка

if PMap <> nil then UnMapViewOfFile(PMap);
PMap:=nil; //это уже перестраховка бредовая :)

в начало TArr.SetPage не помогает.
Как грамотно освободить память?
Может быть на определённых этапах дестроить и создавать заново весь класс?
Или просто вместо PMap:=nil надо писать PMap.Free?


 
MBo ©   (2005-11-22 14:25) [12]

я при выделении SetPage в метод класса потерял вот что:

в SetPage надо вставить

UnMapViewOfFile(PMap);

Кроме того, в примере нерационально используется память при небольшой длине строк массива - под каждую строку отводится минимум 64К (гранулярность выделения памяти). СтОит модифицировать систему упаковки данных в зависимости от X-размерности.


 
bodomic ©   (2005-11-22 17:15) [13]

:)
Я пробовал UnMap..., не помогает, посмотрите мой пост.
Или надо UnMap делать сразу после Map? Это как-то выглядит нереально...

А про нерациональность я уже заметил, но меня пока это устраивает. Если припрёт, буду максимально рационализироваться, используя такие N, что N*sizeof(bla-bla)=64k.

Код у вас хороший, претензий нету :)
только вот память бы освободить :)


 
MBo ©   (2005-11-22 17:51) [14]

Очень странно. Вот в каком виде у меня сейчас SetPage. При запуске теста с закомментированным UnMap память (в диспетчере задач), естественно, программой отъедается, а с этой строкой - всего несколько десятков килобайт.


procedure TArr.SetPage(const APage: DWord);
var
 FPos: Int64;
 FPosLow, FPosHigh: DWord;
begin
 FPage := APage;
 FPos := FPage * FPageSize;
 FPosLow := FPos and $FFFFFFFF;
 FPosHigh := FPos shr 32;
 UnMapViewOfFile(PMap);
 PMap := MapViewOfFile(HMap, FILE_MAP_ALL_ACCESS, FPosHigh, FPosLow,
   FPageSize);
 if PMap = nil then
   raise Exception.Create("Cannot map view of file");
end;

//test
procedure TForm1.Button1Click(Sender: TObject);
var
 x, y: Integer;
 t: DWord;
begin
 Arr := TArr.Create(2048);
 t := GetTickCount;
 for y := 0 to 2047 do
   for x := 0 to 511 do
     Arr[y, x] := x;
 Caption := IntToStr(Arr[0, 0]) + " " + IntToStr(Arr[511, 511]) + " " +
   IntToStr(GetTickCount - t);
 Arr.Free;
end;



 
bodomic ©   (2005-11-22 19:06) [15]

В диспетчере задач включена колонка Virtual memory? Он её поглощает.
Если без этой колонки смотреть, память тоже не особо расходуется, только пухнет и пухнет файл подкачки :)


 
Defunct ©   (2005-11-23 04:39) [16]

bodomic ©   (22.11.05 19:06) [15]

А почему бы вместо Map/UnMap не загружать блоки файла просто в статический массив? Фактически выполнять MemoryMapping самостоятельно.

подкреплю сказанное примером:

type
TIntArr = array[Word] of Integer;
// PIntArr = ^TIntArr;  <-- не требуется, т.к. предполагаем статический mapping

TArr = class
  constructor Create(const N: DWord);
  destructor Destroy; override;
private
  FPage: DWord;
  FPageSize: DWord;
{
  FileSize: Int64;
  FileSizeLow, FileSizeHigh: DWord;
}
  FMappedFile : TFileStream;
  FMap: TIntArr;  // <-- changed
  function GetElement(y, x: DWord): Integer;
  procedure SetElement(y, x: DWord; const Value: Integer);
  procedure SetPage(const APage: DWord);
public
  property Element[y, x: DWord]: Integer read GetElement write SetElement;
    default;
end;

constructor TArr.Create(const N: DWord);
begin
 FMappedFile := TFileStream.Create( "C:\Test.dat", fmOpenReadWrite + fmShareExclusive );
FPageSize := (N * SizeOf(Integer) + 65535) and $FFFF0000;
SetPage(0);
end;

destructor TArr.Destroy;
begin
 if Assigned( FMappedFile ) then
    SetPage( 0 );
 FMappedFile.Free;
 inherited Destroy;
end;

function TArr.GetElement(y, x: DWord): Integer;
begin
if y <> FPage then
  SetPage(y);
Result := FMap[x];
end;

procedure TArr.SetElement(y, x: DWord; const Value: Integer);
begin
if y <> FPage then
  SetPage(y);
FMap[x] := Value;
end;

procedure TArr.SetPage(const APage: DWord);
var
FPos: Int64;
FPosLow, FPosHigh: DWord;
begin
FMappedFile.Position := FPos;
FMappedFile.Write( FMap, FPageSize );  // <-- сохранение пред. страницы

FPage := APage;
FPos := FPage * FPageSize;
FMappedFile.Read( FMap, FPageSize );

end;

//----------------------

var
 Arr  : TArr;

procedure TForm1.Button1Click(Sender: TObject);
begin
Arr := TArr.Create(1024);
Arr[0, 0] := 4;
Arr[1023, 1023] := 5;
Caption := IntToStr(Arr[0, 0]) + " " + IntToStr(Arr[1023, 1023]);
Arr.Free;
end;



2 MBO, за основу был взят твой класс.. надеюсь не будешь пинать ногами..


 
Defunct ©   (2005-11-23 04:41) [17]

блин.. а форматирование куда пропало?


 
Джо ©   (2005-11-23 05:04) [18]


>  [17] Defunct ©   (23.11.05 04:41)
> блин.. а форматирование куда пропало?

При вставке двойные пробелы в начале строки заменяются на один, а одинарные - съедаются. Увы :(


 
bodomic ©   (2005-11-23 10:20) [19]

Спасибо за идею, Defunct
Я с этого начинал :) Писал/читал в/из TFileStream. Правда, это было довольно наколенно написано, надо попробовать стащить ваш код :)

Однако чертовски интересно, неужели никак нельзя освободить занятые страницы? :( Они ведь ну ваще совсем никак мне не нужны после разового использования... Нелогично, блин.



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

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

Наверх




Память: 0.53 MB
Время: 0.058 c
2-1132735366
yrbanchik
2005-11-23 11:42
2005.12.11
светомузыка


14-1132659449
Quadro
2005-11-22 14:37
2005.12.11
Требуется довести до ума небольшую программу на Дельфи 7


2-1132550552
Mamur
2005-11-21 08:22
2005.12.11
Обращение из папки которой запускается


1-1131936511
Razor
2005-11-14 05:48
2005.12.11
Как правильнее передавать строки в DLL?


14-1132330160
x.pro
2005-11-18 19:09
2005.12.11
С днем студента!