Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2005.12.11;
Скачать: [xml.tar.bz2];

Вниз

Поясните пожалуйста работу с 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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.051 c
14-1132011027
ronyn
2005-11-15 02:30
2005.12.11
Как установить драйвер?...


4-1128497857
Rentgen
2005-10-05 11:37
2005.12.11
Каким способом проверить на замкнутость цепи?


1-1131624295
ASScef
2005-11-10 15:04
2005.12.11
Рисование на Canvas


1-1131704477
DelphiLexx
2005-11-11 13:21
2005.12.11
DosToWin


14-1132221764
Crazy_Diman
2005-11-17 13:02
2005.12.11
Графика





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский