2010-11-03 5 views
4

Je dois allouer de très grands tableaux de structures simples (1 Go de RAM). Après quelques allocations/désallocations, la mémoire devient fragmentée et une exception OutOfMemory est levée.Tableau groupé en C#

Ceci est inférieur à 32 bits. Je préfère ne pas utiliser 64 bits en raison de la pénalité de performance que je reçois - la même application est 30% plus lente en mode 64 bits. Avez-vous connaissance de certaines implémentations de baies compatibles IList qui allouent de la mémoire en morceaux et pas tous en même temps? Cela permettrait d'éviter mon problème de fragmentation de la mémoire.

+0

Odd, ceci est vraiment la mauvaise question. Il aurait dû demander "pourquoi est par le programme 64 bits 30% plus lent?" Votre processus 32 bits va être un * lot * plus lent aussi après avoir découpé les tableaux. –

+0

A l'origine, l'application était en 64 bits, mais après avoir lu certains articles qui suggèrent que le JIT 64 bits n'est pas si bon à l'optimisation du code que celui de 32 bits (http: // stackoverflow.com/questions/14432/64bit-net-performance-tuning), je l'ai converti en 32 bits et j'ai trouvé que c'était vrai. Même si je perds de la vitesse ici, il démarrera toujours plus vite que la version 64 bits - j'utilise IronPython + C# + C++/CLI, et le démarrage de la version 64 bits prend 10 secondes de plus (à cause d'IronPython) – Meh

Répondre

3

Josh Williams a présenté une classe BigArray<T> sur son blog en utilisant un tableau chunked:

BigArray<T>, getting around the 2GB array size limit

Vous trouverez des informations plus utiles dans cette question connexe:

C# huge size 2-dim arrays

Une simple correction ad-hoc pourrait être d'activer le commutateur 3GB pour votre application. Cela permet à votre application d'utiliser plus que la limite de 2 Go par processus de Windows 32 bits. Cependant, sachez que la taille d'objet maximale autorisée par le CLR est toujours de 2 Go. Le commutateur peut être activé à l'aide d'une action post-construit pour votre exécutable principal:

call "$(DevEnvDir)..\tools\vsvars32.bat" 
editbin.exe /LARGEADDRESSAWARE "$(TargetPath)" 
+0

J'ai déjà fait le tour/LARGEADDRESSAWARE et cela m'a beaucoup aidé – Meh

1

Lors de l'instanciation un tableau, .Net essaie de trouver une partie contiguë de mémoire pour votre tableau. Puisque la limite de mémoire totale pour une application 32 bits est de 2 Go, vous pouvez voir qu'il sera difficile de trouver un tel bloc après plusieurs allocations.

  1. Vous pouvez essayer d'utiliser quelque chose comme un LinkedList<T>, afin d'éviter la nécessité d'une allocation contiguë, ou restructurer votre code pour ces petits morceaux (bien que vous ne serez pas complètement sûr cela ne se produira avec un tableau 500Mo aussi). D'autre part, une solution consisterait à instancier cette grande mémoire tampon une seule fois, au début de votre application, puis à implémenter un algorithme qui réutiliserait ce même espace pendant la durée de vie de votre application. Si vous pouvez utiliser IEnumerable au lieu de IList pour transmettre vos données au reste de votre programme, vous pouvez réduire cette liste à l'aide de la méthode LINQ SelectMany. Et à la fin, vous pouvez simplement implémenter l'interface IList dans une classe personnalisée et utiliser plusieurs tableaux plus petits sous le capot.

+0

+1 pour # 2, simple et parsimonius – smirkingman