Den gesamten verfügbaren RAM in einem Haskell-Programm nutzen?

8

Ich habe 8 GB RAM, aber Haskell-Programme können scheinbar nur 1,3 GB verwenden.

Ich verwende dieses einfache Programm, um zu bestimmen, wie viel Speicher ein GHC-Programm zuordnen kann:

%Vor%

Hier ist was ich finde:

  • läuft ./mem.exe 40000000 +RTS -s erfolgreich und meldet 1113 MB total memory in use
  • das Ausführen von ./mem.exe 42000000 +RTS -s schlägt mit out of memory error fehl
  • Ausführen von ./mem.exe 42000000 +RTS -s -M4G Fehlern mit -M4G: size outside allowed range
  • das Ausführen von ./mem.exe 42000000 +RTS -s -M3.9G schlägt mit out of memory error fehl

Die Überwachung des Prozesses über den Windows Task-Manager zeigt, dass die maximale Speicherbelegung etwa 1,2 GB beträgt.

Mein System: Win7, 8 GB RAM, Haskell Platform 2011.04.0.0, ghc 7.0.4.

Ich kompiliere mit: ghc -O2 mem.hs -rtsopts

Wie kann ich all meinen verfügbaren Arbeitsspeicher nutzen? Fehle ich etwas Offensichtliches?

    
ErikR 24.05.2012, 18:12
quelle

2 Antworten

8

Derzeit ist GHC unter Windows ein 32-Bit-GHC - ich denke, dass ein 64-Bit-GHC für Windows verfügbar sein wird, wenn 7.6 kommt.

Eine Konsequenz davon ist, dass Sie unter Windows nicht mehr als 4G - 1BLOCK des Speichers verwenden können, da das Maximum als Größenparameter HS_WORD_MAX ist:

%Vor%

Mit 32-Bit-Wörtern, HS_WORD_MAX = 2^32-1 .

Das erklärt

  

running ./mem.exe 42000000 + RTS -s -M4G Fehler mit -M4G: Größe außerhalb des zulässigen Bereichs

seit decodeSize() dekodiert 4G als 2^32 .

Diese Einschränkung bleibt auch nach dem Upgrade Ihres GHC bestehen, bis endlich ein 64-Bit GHC für Windows veröffentlicht wird.

Bei einem 32-Bit-Prozess ist der virtuelle Adressraum im Benutzermodus auf 2 oder 4 GB begrenzt (abhängig vom Status des Flags IMAGE_FILE_LARGE_ADDRESS_AWARE ), siehe Speicherlimits für Windows-Versionen .

Nun versuchen Sie, ein Set mit 42 Millionen 4-Byte Int s zu erstellen. A Data.Set.Set hat fünf Overheadwörter pro Element (Konstruktor, Größe, linker und rechter Unterbaumzeiger, Zeiger auf Element), so dass Set etwa 0,94 GiB Speicher belegt (1.008 'Metrik' GB). Aber der Prozess verwendet etwa doppelt so viel oder mehr (es benötigt Platz für die Garbage-Collection, mindestens die Größe des Live-Heaps).

Ausführen des Programms auf meinem 64-Bit-Linux, mit Eingabe 21000000 (um die doppelt so große Int s und Zeiger zu ersetzen), bekomme ich

%Vor%

aber top meldet nur 1.1g der Speicherbelegung - top , und vermutlich meldet der Task-Manager nur den Live-Heap.

So scheint es, dass IMAGE_FILE_LARGE_ADDRESS_AWARE nicht gesetzt ist, Ihr Prozess ist auf einen Adressraum von 2 GB begrenzt und die 42 Mio. Set brauchen mehr als das - es sei denn, Sie geben eine maximale oder vorgeschlagene Heap-Größe an, die kleiner ist:

%Vor%

Wenn Sie die maximale Größe des Heapspeichers so einstellen, wie sie normalerweise verwendet wird, passt es tatsächlich kaum mehr als der Platzbedarf für Set , zum Preis einer etwas längeren GC-Zeit und schlägt eine Heapgröße von% co_de vor % lässt es nur mit

enden %Vor%

Wenn Sie also eine maximale Größe des Heapspeichers unter 2 GB angeben (aber groß genug, damit -H1800M passt), sollte es funktionieren.

    
Daniel Fischer 24.05.2012, 21:21
quelle
4

Die Standard-Heap-Größe ist unbegrenzt .

Mit GHC 7.2 auf einem 64-Bit-Windows XP-Rechner kann ich höhere Werte zuweisen, indem ich die Größe des Heapspeichers explizit festlege:

%Vor%

und

%Vor%

gerade:

%Vor%

Das heißt, ich kann dem Windows XP 2G-Prozesslimit zuweisen . Ich stelle mir vor, dass Sie auf Win 7 keine so niedrige Grenze haben werden - diese Tabelle schlägt entweder 4G oder 192G vor - fragen Sie einfach nach soviel Sie benötigen (und verwenden Sie einen neueren GHC).

    
Don Stewart 24.05.2012 18:26
quelle