Autor Beitrag
m4ko
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Mi 16.06.10 12:02 
Hallo C#Sharp Community!

Ich habe mich grade erst registriert und deshalb ein kurzes: Hallo!

Der Grund meiner Anmeldung ist folgender:
Ich möchte sehr große Bilddaten verarbeiten.

Umgebung:
Ich habe hier PCs zur Verfügung die mit 12 bis 24 GB RAM und Windows 7 64bit ausgestattet sind. Nun habe ich mir verschiedene C# Programme gebastelt um auszuloten wie viel Speicher ich in Form von Arrays allozieren kann. Leider kann ich den verfügbaren Arbeitsspeicher nicht mal ansatzweise ausnutzen. Hier ein Beispiel dazu:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
PerformanceCounter PC = new PerformanceCounter("Memory""Available Bytes");
Console.WriteLine("Available Memory: " + ToFuzzyByteString(PC.NextValue()));
Console.WriteLine("");

int[] ManyInts;
for (int i = 20; i < 30; i++)
{
  try
  {
    AmountInBytes = Math.Pow(2, i) * 4;
    Console.Write("Allocating 2^" + i + " ints (= " + ToFuzzyByteString(AmountInBytes) + ")...");
    ManyInts = null;
    System.Threading.Thread.Sleep(100);
    ManyInts = new int[Convert.ToInt32(Math.Pow(2, i))];
    for (int j = 0; j < ManyInts.Length; j++)
    {
      ManyInts[j] = 5;
    }
    Console.WriteLine(" OK");
  }
  catch (Exception exc)
  {
    Console.WriteLine(" Failed");
    Console.WriteLine("Exception: " + exc.Message);
    break;
  }
}


Ausgabe dazu:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
Available Memory: 6,61 GB

Allocating 2^20 ints (= 4 MB)... OK
Allocating 2^21 ints (= 8 MB)... OK
Allocating 2^22 ints (= 16 MB)... OK
Allocating 2^23 ints (= 32 MB)... OK
Allocating 2^24 ints (= 64 MB)... OK
Allocating 2^25 ints (= 128 MB)... OK
Allocating 2^26 ints (= 256 MB)... OK
Allocating 2^27 ints (= 512 MB)... OK
Allocating 2^28 ints (= 1 GB)... OK
Allocating 2^29 ints (= 2 GB)... Failed
Exception: Exception of type 'System.OutOfMemoryException' was thrown.


Dies ist auf einem 8GB Win7 Rechner erstellt worden. Nun habe ich gedacht "OK. 2GB am Stück gehen nicht... dann machen wir halt kleine Chunks."

C# Code:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
double AmountInBytes = Math.Pow(224) * 4;
Console.Write("Allocating lots of 2^24 ints (= " + ToFuzzyByteString(AmountInBytes) + ")...");
List<int[]> arrayList = new List<int[]>();
for (int i = 0; i < 10000; i++)
{
  try
  {
    Console.Write(i + "...");
    arrayList.Add(new int[Convert.ToInt32(Math.Pow(2, i))]);
    for (int j = 0; j < arrayList[i].Length; j++)
    {
      arrayList[i][j] = 5;
    }
    Console.WriteLine(" OK (=" + ToFuzzyByteString(AmountInBytes * i) + ")");
  }
  catch (Exception exc)
  {
    Console.WriteLine(" FAILED");
    break;
  }
}


Ausgabe:
ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
Allocating lots of 2^24 ints (= 64 MB)...0... OK (=0 bytes)
1... OK (=64 MB)
2... OK (=128 MB)
3... OK (=192 MB)
4... OK (=256 MB)
5... OK (=320 MB)
6... OK (=384 MB)
7... OK (=448 MB)
8... OK (=512 MB)
9... OK (=576 MB)
10... OK (=640 MB)
11... OK (=704 MB)
12... OK (=768 MB)
13... OK (=832 MB)
14... OK (=896 MB)
15... OK (=960 MB)
16... OK (=1 GB)
17... OK (=1,06 GB)
18... OK (=1,12 GB)
19... OK (=1,18 GB)
20... OK (=1,25 GB)
21... OK (=1,31 GB)
22... OK (=1,37 GB)
23... OK (=1,43 GB)
24... OK (=1,5 GB)
25... OK (=1,56 GB)
26... OK (=1,62 GB)
27... OK (=1,68 GB)
28... OK (=1,75 GB)
29... FAILED


Also habe ich nun ein Array mit 28 * 2 hoch 24 ints (~1,75GB). Das ist natürlich zu wenig bei 8GB RAM und 6,4GB freiem RAM.

Hat jemand eine Idee wodran das liegt? Oder einen Tip wie ich mehr Speicher bekomme? Oder gibt es vielleicht Abhilfe mit Visual Studio 2010?
danielf
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1012
Erhaltene Danke: 24

Windows XP
C#, Visual Studio
BeitragVerfasst: Mi 16.06.10 14:45 
Hallo und :welcome:,

ich hab zwar kein konrekte Lösung, aber ich erinnere mich daran, dass es noch eine Einschränkung pro Prozess gibt. Deshalb hab ich mal danach gegoogelt und bin auf Wikipedia auf folgende Aussage gestoßen:
Zitat:
Unter Windows kann ein einzelner 32bit-Prozess generell nicht mehr als 2 GB belegen, außer IMAGE_FILE_LARGE_ADDRESS_AWARE ist im Header der Anwendung aktiviert (dann sind bis zu 4 GB möglich)
.

Also musst du wohl mal schauen, wie du das umgehen kannst.

Was willst du den genau machen?

Vielleicht kannst du es auf mehrere Prozesse auslagern ...

Gruß
bakachan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 503
Erhaltene Danke: 34

W7 (x64) Ultimate
C# / VB.NET (VS2010 Ultimate)
BeitragVerfasst: Mi 16.06.10 14:49 
Oder als 64Bit-Programm kompilieren :wink:
Ich gehe mal davon aus das die PCs bei den Speichergrößen (8/12/24 GB) sowieso mit 64Bit-Systemen laufen um den Speicher überhaupt nutzen zu können.


Zuletzt bearbeitet von bakachan am Mi 16.06.10 14:51, insgesamt 1-mal bearbeitet
danielf
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1012
Erhaltene Danke: 24

Windows XP
C#, Visual Studio
BeitragVerfasst: Mi 16.06.10 14:50 
Ach... da hätte ich mal mein Zitat genauer lesen sollen, bzw den Wiki-Artikel bis zum Ende :D

Aber schön, dass es sich so schnell klärt :)
m4ko Threadstarter
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Mi 16.06.10 15:29 
Der Prozess ist natürlich 64bit ;).

Ich habe es auch mittlerweile hinbekommen mehr Speicher zu allozieren.

Hintergrund:
Auch wenn das Programm 64bit kompiliert ist und die Pointer im die im Hintergrund werkeln 64bit Pointer so sind die Array-Index-Dinger immer noch nur 32bit fähig. Das bedeutet: Man kann kein Array > 32bit anlegen. Man kann aber mehrere Arrays anlegen! Allerdings dürfen die nicht in einer Liste stehen.

Beispiel: GEHT NICHT ÜBER ~1,7GB!
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
List<int[]> arrayList = new List<int[]>();
for (int i = 0; i < 10000; i++)
{
    arrayList.Add(new int[Convert.ToInt32(Math.Pow(224))]); //64MB Arrays
    for (int j = 0; j < arrayList[i].Length; j++)
    {
      arrayList[i][j] = 5;
    }
}



Beispiel: GEHT UNENDLICH (bisher) :)
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
int arrayLength = (int)(1024*1024*1024/4);  //= 1GB / 4-byte-int
int[] arrONE = new int[arrayLength]; //erster GB
int[] arrTWO = new int[arrayLength]; //zweiter GB
int[] arrTHREE = new int[arrayLength]; //dritter GB
...



Da ich aber ein mega riesen Array haben möchte werde ich mir wohl einen Index dafür basteln müssen der einen int64 Offset auf mehrere int32 Arrays verteilt. Hm. jemand dazu schicke Ideen?
gfoidl
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 157
Erhaltene Danke: 19

Win XP
C#, Fortran 95 - Visual Studio
BeitragVerfasst: Mi 16.06.10 15:35 
Hallo,

weiters wurde die CLR auch so designed dass die maximale Objektgröße 1GB ist. Ob das in .net 4.0 geändert wurde weiß ich nicht. D.h. aber nicht dass mehrer 1GB-Objekte existieren dürfen ;-)


mfG Gü

_________________
Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Mi 16.06.10 19:23 
Ebenfalls :welcome: !

user profile iconm4ko hat folgendes geschrieben Zum zitierten Posting springen:
Auch wenn das Programm 64bit kompiliert ist und die Pointer im die im Hintergrund werkeln 64bit Pointer so sind die Array-Index-Dinger immer noch nur 32bit fähig.
Stimmt. Nur, wo soll das in deinem Programm mit den maximalen Indizes 10000 und 5 eine Rolle spielen ;) ?

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
      Console.Write("Allocating lots of 2^24 ints (= 64 MB)...");
      List<int[]> arrayList = new List<int[]>();
      for (int i = 0; i < 10000; i++)
      {
        try
        {
          Console.Write(i + "...");
          arrayList.Add(new int[1 << 24]);
          Console.WriteLine(" OK (= " + 64 * i + " MB)");
        }
        catch (OutOfMemoryException)
        {
          Console.WriteLine(" FAILED");
          break;
        }
      }

ausblenden Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
...
171... OK (= 10944 MB)
172... OK (= 11008 MB)
173... OK (= 11072 MB)
174... OK (= 11136 MB)
175... OK (= 11200 MB)
176... OK (= 11264 MB)
177... OK (= 11328 MB)
178... OK (= 11392 MB)
179... OK (= 11456 MB)
180... OK (= 11520 MB)
181... OK (= 11584 MB)
182... OK (= 11648 MB)
183... FAILED


Ganz sicher, dass du für x64 oder AnyCPU kompiliert hast :nixweiss: ?

user profile icongfoidl hat folgendes geschrieben Zum zitierten Posting springen:
weiters wurde die CLR auch so designed dass die maximale Objektgröße 1GB ist.
Soweit ich weiß, sind es 2.

user profile icongfoidl hat folgendes geschrieben Zum zitierten Posting springen:
D.h. aber nicht dass mehrer 1GB-Objekte existieren dürfen ;-)
Ich nehme mal an, das darf man zu einer doppelten Verneinung ergänzen :D ?

_________________
>λ=
gfoidl
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 157
Erhaltene Danke: 19

Win XP
C#, Fortran 95 - Visual Studio
BeitragVerfasst: Mi 16.06.10 22:17 
Hallo Kha,

danke für die Berichtung auf 2GB - stimmt natürlich.


mfG Gü

_________________
Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!
m4ko Threadstarter
Hält's aus hier
Beiträge: 3



BeitragVerfasst: Do 17.06.10 15:05 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Nur, wo soll das in deinem Programm mit den maximalen Indizes 10000 und 5 eine Rolle spielen ;) ?


Hmmmmmm. Da muss ich wohl tatsächlich 32bit kompiliert haben. Ich kann den Fehler @ 1,7GB nicht mehr reproduzieren. Danke für den Hinweis!