2008-10-03 7 views
5

Est-il plus performant d'avoir un tableau bidimensionnel (type[,]) ou un tableau de tableaux (type[][]) en C#?Quoi de mieux en matière de performance? tapez [,] ou tapez [] []?

en particulier pour l'allocation initiale et le point d'accès

+0

Voir également [Pourquoi les tableaux multidimensionnels sont-ils plus nets que les réseaux normaux?] (Http://stackoverflow.com/questions/468832/why-are-multi- dimension-arrays-in-net-lent-than-normal-arrays?) – nawfal

Répondre

5

Bien sûr, si tout le reste échoue ... Testez-le! Suivant donne (dans « Libération », à la console):

Size 1000, Repeat 1000 
    int[,] set: 3460 
    int[,] get: 4036 (chk=1304808064) 
    int[][] set: 2441 
    int[][] get: 1283 (chk=1304808064) 

donc un tableau en dents de scie est plus rapide, au moins dans ce test. Intéressant! Cependant, il s'agit d'un petit facteur, donc je voudrais toujours s'en tenir à ce qui décrit le mieux mes besoins. À l'exception de certains scénarios spécifiques (haute CPU/traitement), la lisibilité/maintenabilité devrait l'emporter sur un petit gain de performance. À vous, cependant. Notez que ce test suppose que vous accédez au tableau beaucoup plus souvent que vous ne le créez, donc je n'ai pas inclus les timings pour la création, où attendrait rectangulaire pour être légèrement plus rapide, sauf si la mémoire est très fragmentée.

using System; 
using System.Diagnostics; 
static class Program 
{ 
    static void Main() 
    { 
     Console.WriteLine("First is just for JIT..."); 
     Test(10,10); 
     Console.WriteLine("Real numbers..."); 
     Test(1000,1000); 

     Console.ReadLine(); 
    } 

    static void Test(int size, int repeat) 
    { 
     Console.WriteLine("Size {0}, Repeat {1}", size, repeat); 
     int[,] rect = new int[size, size]; 
     int[][] jagged = new int[size][]; 
     for (int i = 0; i < size; i++) 
     { // don't cound this in the metrics... 
      jagged[i] = new int[size]; 
     } 
     Stopwatch watch = Stopwatch.StartNew(); 
     for (int cycle = 0; cycle < repeat; cycle++) 
     { 
      for (int i = 0; i < size; i++) 
      { 
       for (int j = 0; j < size; j++) 
       { 
        rect[i, j] = i * j; 
       } 
      } 
     } 
     watch.Stop(); 
     Console.WriteLine("\tint[,] set: " + watch.ElapsedMilliseconds); 

     int sum = 0; 
     watch = Stopwatch.StartNew(); 
     for (int cycle = 0; cycle < repeat; cycle++) 
     { 
      for (int i = 0; i < size; i++) 
      { 
       for (int j = 0; j < size; j++) 
       { 
        sum += rect[i, j]; 
       } 
      } 
     } 
     watch.Stop(); 
     Console.WriteLine("\tint[,] get: {0} (chk={1})", watch.ElapsedMilliseconds, sum); 

     watch = Stopwatch.StartNew(); 
     for (int cycle = 0; cycle < repeat; cycle++) 
     { 
      for (int i = 0; i < size; i++) 
      { 
       for (int j = 0; j < size; j++) 
       { 
        jagged[i][j] = i * j; 
       } 
      } 
     } 
     watch.Stop(); 
     Console.WriteLine("\tint[][] set: " + watch.ElapsedMilliseconds); 

     sum = 0; 
     watch = Stopwatch.StartNew(); 
     for (int cycle = 0; cycle < repeat; cycle++) 
     { 
      for (int i = 0; i < size; i++) 
      { 
       for (int j = 0; j < size; j++) 
       { 
        sum += jagged[i][j]; 
       } 
      } 
     } 
     watch.Stop(); 
     Console.WriteLine("\tint[][] get: {0} (chk={1})", watch.ElapsedMilliseconds, sum); 
    } 
} 
+0

J'ai vu les mêmes résultats dans un blog d'optimisation .NET à msdn. – dalle

2

Je crois que [,] peut affecter un seul bloc contigu de mémoire, tandis que [] [] est N + 1 allocations de chunk où N est la taille de la première dimension. Donc je suppose que [,] est plus rapide lors de l'allocation initiale.

L'accès est probablement à peu près le même, sauf que [] [] impliquerait un déréférencement supplémentaire. Sauf si vous êtes dans une boucle exceptionnellement serré, c'est probablement un lavage. Maintenant, si vous faites quelque chose comme le traitement d'image où vous faites référence entre lignes plutôt que de traverser ligne par ligne, la localité de référence jouera un grand facteur et [,] sera probablement bord [] [] en fonction de votre cache Taille.

Comme Marc Gravell mentionné, l'utilisation est essentielle pour évaluer la performance ...

-1

de type [,] va travailler plus vite. Pas seulement à cause de calculs moins décalés. Principalement grâce à moins de vérification des contraintes, moins d'allocation de mémoire et une plus grande localisation en mémoire. type [] [] n'est pas un seul objet - c'est 1 + N objets qui doivent être alloués et peuvent être éloignés les uns des autres.

+0

Cette réponse commence par une déclaration absolue qui est (dans mon humble expérience) incorrecte ... Comme je le comprends (je ne sais pas tout) un multi -subscripted array fait en fait PLUS de calculs sur chaque accès car nous devons "aplatir" les indices dans l'index unique-entier réel ... Ex: var a = int [16,16] alors un [1,1] est en fait un [16 * 1 + 1] -> a [17] ... et que le calcul de la ligne * ROWS + col prend plus de temps (en moyenne) que les deux déréférences requises pour retourner la valeur de [1] [1] dans l'équivalent tableau déchiqueté ... C'est pourquoi j'ai downvoted cette réponse.Désolé pour cela, mais à mon humble avis, c'est trompeur. – corlettk

2

Cela dépend vraiment. L'article MSDN Magazine, Harness the Features of C# to Power Your Scientific Computing Projects, dit ceci:

Bien que les tableaux rectangulaires sont généralement supérieurs aux tableaux déchiquetés en termes de structure et de la performance, il pourrait y avoir certains cas où des réseaux déchiquetés fournissent une solution optimale. Si votre application ne nécessite pas que les tableaux soient triés, réorganisés, partitionnés, épars ou volumineux, vous risquez de trouver des tableaux dentelés assez performants.

Questions connexes