Meilleur moyen d’allouer de la mémoire à un tableau à deux dimensions en C?

Quel est le meilleur moyen d’allouer de la mémoire à un two-d array à two-d array en C , des deux outlook: memory-management et speed ?

En outre, lequel est préférable d’utiliser un two-d array (et lui allouer de la mémoire) ou un double pointer ? Quelqu’un peut-il expliquer en détail, ce qui se passe à l’intérieur, pourquoi une méthode est meilleure que l’autre?

    Pour obtenir les meilleures performances et la meilleure lisibilité, ces tableaux doivent toujours être alloués sous forme de bloc de mémoire contigu:

     type (*array) [X][Y] = malloc( sizeof(type[X][Y]) ); 

    Vous devriez éviter ceci:

     // BAD METHOD, not a real array type** lookup_table = malloc( X*sizeof(type*) ); for(size_t i=0; i 

    Le premier est plus rapide pour plusieurs raisons. Il est alloué dans un bloc de mémoire contigu et n'est pas segmenté dans le tas. Les versions segmentées bloquent toutes les formes d'optimisation du code et l'utilisation efficace du cache de données sur puce, de même que l'allocation réelle est beaucoup plus lente.

    La "mauvaise" version ci-dessus présente cependant un avantage: vous souhaitez que les dimensions individuelles aient une longueur variable, par exemple lors de la création d'une table de conversion pour les chaînes. Ensuite, vous devez utiliser ce formulaire. Mais si vous voulez un vrai tableau 2D, il n’ya jamais de raison de ne pas utiliser le premier.


    Notez que la première version est généralement écrite en tant que

     type (*array) [Y] = malloc( sizeof(type[X][Y]) ); 

    pour permettre une utilisation plus pratique: array[i][j] , plutôt que le moins lisible (*array)[i][j] .

     data_type (*mat)[size_2] = malloc(size_1 * size_2 * sizeof(data_type)); 

    Cela allouera de la mémoire contiguë pour un tableau de tableaux (“tableau 2d”). Si vous n’avez pas besoin de quantités d’espace ridicules, c’est la voie à suivre. Vous réduirez la fragmentation de la mémoire, augmenterez la convivialité du cache et éviterez les frais généraux liés à l’utilisation de malloc .


    1 Pour certaines définitions (spécifiques à l’application) de ridicule

    Étant donné une taille fixe, vous pouvez simplement dire twoDimArray[100][100] , qui l’allouera sur la stack. Toutefois, lors de l’allocation sur le tas (que ce soit parce que la taille est très grande ou dynamic), vous avez plus d’options.

    Vous pouvez allouer un tableau de pointeurs, puis allouer de la mémoire pour chaque ligne. Ceci est problématique pour la localité du cache, mais très bon si la taille est très grande et que votre access est séquentiel; cela permet une fragmentation raisonnable sans impact majeur sur les performances, car le tableau de tableaux peut être séparé des tableaux eux-mêmes, qui peuvent être séparés les uns des autres. Dans un scénario d’access linéaire, la plupart du temps , vous ne sauterez pas entre des régions de mémoire. vous aurez plutôt access à toute une ligne avant même de vous déplacer dans une nouvelle région.

    La deuxième méthode consiste à linéariser l’access et à tout allouer en une fois. c’est-à-dire allouer suffisamment de mémoire pour sizex * sizey puis l’indexer avec (positiony * sizex) + positionx ; c’est-à-dire décompter quelques lignes puis à travers certaines colonnes. Ceci est idéal pour un access aléatoire et améliore la localisation du cache car la mémoire est contiguë, mais il peut échouer s’il n’ya pas assez de mémoire contiguë disponible (et l’avantage de la localisation de la cache n’est pas applicable si vous avez besoin de plus de mémoire que le cache).