große Datenmengen erzeugen ohne OutofMemoryException

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von Diversity.

    große Datenmengen erzeugen ohne OutofMemoryException

    Hallo,

    ich spiel gerade ein bisschen damit Primzahlen zu berechnen. Das klappt sehr flott, allerdings bekomme ich ab einer Obergrenze von 1.000.000.000 eine OutofMemoryException...

    Das Programm startet und verbraucht ca. 1GB RAM, nach ca 20 Sekunden fängt das Programm dann an sich immer mehr Arbeitsspeicher einzuverleiben bis zur Exception...(Bild2)

    Wenn ich nur 100.000.000 als Obergrenze nehme, läuft das Programm fix durch und benötigt maximal 0,6GB RAM (Bild1)

    Die Datenmenge bei 100Mio als Obergrenze ist (wenn man die gefundenen Primzahlen in eine txt-Datei schreibt) ca. 50 MB groß...

    woran liegt das, dass so viel RAM benötigt wird und wie kann ich das verhindern bzw. kann man dem PC sagen, dass er auf den RAM nicht achten soll bzw erst ab einer Obergrenze ne Exception wirft?

    Der Rechner hat 8 GB RAM zur Verfügung...

    C#-Quellcode

    1. ​static void Main(string[] args)
    2. {
    3. string ergebnis = null;
    4. List<string> ergebnisLst = new List<string>();
    5. long n = 0;
    6. n = 1000000000; // Obergrenze zur Berechnung von Primzahlen
    7. bool[] prime = new bool[n];
    8. for (long i = 2; i <= n - 1; i++)
    9. {
    10. prime[i] = true;
    11. }
    12. if (true)
    13. {
    14. long i = 2;
    15. while (i * i < n)
    16. {
    17. if (prime[i])
    18. {
    19. ergebnisLst.Add((i.ToString()));
    20. long j = i * i;
    21. while (j < n)
    22. {
    23. prime[j] = false;
    24. j = j + i;
    25. }
    26. }
    27. i += 1;
    28. }
    29. while (i < n)
    30. {
    31. if (prime[i])
    32. {
    33. ergebnisLst.Add((i.ToString()));
    34. }
    35. i += 1;
    36. }
    37. ergebnis = String.Join(" ", ergebnisLst);
    38. }
    Bilder
    • Ram1.png

      7,86 kB, 173×261, 117 mal angesehen
    • Ram2.png

      11,76 kB, 559×210, 120 mal angesehen
    hier fliegt die Exception, vermutlich ist der String irgendwann zu groß...wenn man mit dem Diagnosetool von Visual Studio die Garbage Collection manuell immer wieder anwirft, dann kann man das ganze ein wenig hinauszögern...
    Bilder
    • Outof.png

      39,77 kB, 1.070×580, 144 mal angesehen

    Mokki schrieb:

    Für was fliegt denn die Exception?
    Steht doch im Titel: Eine OutOfMemoryException.

    @TE: für was hast du da diese sinnlose if (true)-Abfrage?
    Und wegen deines Memory-Problemes: lass das string weg...das kostet nur Performance und Speicher, nimm lieber gleich ein List<int> oder List<long>
    Alternativ versuch mal ein einfaches long[] zu verwenden.

    Lg Radinator
    In general (across programming languages), a pointer is a number that represents a physical location in memory. A nullpointer is (almost always) one that points to 0, and is widely recognized as "not pointing to anything". Since systems have different amounts of supported memory, it doesn't always take the same number of bytes to hold that number, so we call a "native size integer" one that can hold a pointer on any particular system. - Sam Harwell
    Ja eben die Liste....

    stackoverflow.com/questions/39…data-into-liststring-in-c

    Versuchs mal mit nem Array und keinen Strings sondern Longs (dann is der Ram schon vorher reserviert und longs sind nicht so lang wie strings)

    Lg Mokki
    ​Smartnotr - ein intelligentes Notizprogramm
    zum Thread

    @Runshak So als Idee:
    Das ganze auf mehrere Prozesse verteilen, also 4x das selbe Programm, die sich per TCP unterhalten, das dauert natürlich viel länger.
    Warum packst Du die Zahlen in eine String-List? Nimm BigInteger.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Um noch weniger Speicher zu verbrauchen, könntest du auch die Tatsache ob die Zahl eine Primzahl ist oder nicht jeweils in ein bool (1Byte im RAM) sondern direkt in einem Bit eines Bytes speichern und würdest so schonmal die 8 Fache Menge bei selben Datenverbrauch speichern können. Siehe Bitwise-Operator: tutorialspoint.com/csharp/csharp_bitwise_operators.htm

    Zusätzlich könntest du mit dem Algorithm: "Sieb des Eratosthenes" einiges an Zeit einsparen.