10
votes

Combien l'indirecte du pointeur affecte-t-elle l'efficacité?

La déséroférance est-elle un pointeur notable plus lentement que d'accéder directement à cette valeur? Je suppose que ma question est - quelle vitesse est l'opérateur de déférence?


5 commentaires

Est-ce la vitesse ou la mémoire que vous êtes préoccupé?


Votre question est-elle sur la vitesse ou la mémoire?


Impossible de répondre en général. Un accès à la mémoire qui frappe dans le cache L1 sera des centaines (éventuellement des milliers) de fois plus rapides que celui qui doit accéder à la RAM réelle. Ne spéculez pas; référence.


Si vous voulez dire avec "directement", comme matry [i] au lieu de * (PTR) , alors il n'y a pas de différence. tableau [i] est sténographique pour * (array + i) , et vous obtenez le + i gratuitement dans les CPU modernes


Non, je me demandais à quel point l'indirection du pointeur coûte réellement


5 Réponses :


2
votes

Cela nécessite un accès mémoire plus:

  1. Lire l'adresse stockée dans la variable du pointeur
  2. Lire la valeur à l'adresse lue

    Ceci n'a pas pu être égal à 2 opération simple, car elle peut nécessiter également plus de temps en raison d'une adresse non déjà chargée dans le cache.


1 commentaires

Il nécessite un Accès à la mémoire plus, qui peut être prohibitif dans une boucle serrée. Toutes les opérations de la CPU ne sont pas créées égales.



2
votes

ça fait. Cela coûte une extraction supplémentaire.
Accès à une variable par valeur, la variable est directement lue de son emplacement de mémoire.
L'accès au pare-pointeur ajoute une surcharge de récupération de l'adresse de la variable du pointeur puis de lire la valeur de cet emplacement de mémoire.

réussite, en supposant que la variable n'est pas placée dans un registre, ce qui serait dans certains scénarios comme des boucles serrées. Je crois que la question cherche une réponse d'une surcharge n'ayant aucun scénarios de ce type.


0 commentaires

4
votes

dépend de choses comme:

  • si la valeur "directement accessible" est déjà dans un registre ou sur la pile (c'est aussi une indirection du pointeur)
  • si l'adresse cible est déjà dans le cache
  • L'architecture de cache, l'architecture de bus, etc.

    C'est-à-dire, trop de variables pour spéculer utilement sans le rétrécir.

    Si vous voulez vraiment savoir, repenez-le sur votre matériel spécifique.


0 commentaires

2
votes

En supposant que vous traitez avec un vrai pointeur (pas un pointeur intelligent de quelque sorte), l'opération de désarférence ne consomme pas du tout (données) du tout. Il s'agit (potentiellement) impliquent une référence de mémoire supplémentaire cependant: une pour charger le pointeur lui-même, l'autre pour accéder aux données pointées par le pointeur.

Si vous utilisez un pointeur dans une boucle serrée, cependant, il sera normalement chargé dans un registre pour la durée. Dans ce cas, le coût est principalement en termes de pression d'enregistrement supplémentaire (c'est-à-dire si vous utilisez un registre pour stocker ce pointeur, vous ne pouvez pas l'utiliser pour stocker autre chose en même temps). Si vous avez un algorithme qui aurait sinon exactement remplir les registres, mais avec l'enregistrement d'un pointeur déborderait à la mémoire, cela peut faire la différence. À une époque, c'était une assez grande perte, mais avec la plupart des processeurs modernes (avec plus de registres et de cache à bord) qui est rarement un gros problème. L'exception évidente constituerait une CPU intégrée avec moins de registres et pas de cache (et sans mémoire sur puce).

Le résultat final est que c'est généralement assez négligeable, souvent en dessous du seuil où vous pouvez même le mesurer de manière fiable.


0 commentaires

23
votes

passer par une indirection de pointeur peut être beaucoup plus lente à cause de la façon dont une CPU moderne fonctionne. Mais cela n'a rien à voir avec la mémoire d'exécution.

Au lieu de cela, la vitesse est affectée par la prédiction et le cache.

La prédiction est facile lorsque le pointeur n'a pas été changé ou s'il est modifié de manière prévisible (par exemple, incrément ou décrément de quatre dans une boucle). Cela permet à la CPU d'exécuter essentiellement l'exécution de code réelle, de déterminer la valeur de la valeur du pointeur et de charger cette adresse dans le cache. La prédiction devient impossible lorsque la valeur du pointeur est construite par une expression complexe comme une fonction de hachage.

Cache entre en jeu car le pointeur pourrait indiquer la mémoire qui n'est pas dans le cache et il devra être récupéré. Ceci est minimisé si la prédiction fonctionne, mais si la prédiction est impossible, alors dans le pire des cas, vous pouvez avoir un double impact: le pointeur n'est pas dans le cache et la cible du pointeur n'est pas dans le cache non plus. Dans ce cas pire cas, le processeur étalait deux fois.

Si le pointeur est utilisé pour un pointeur de fonction, le prédicteur de la branche de la CPU entre en jeu. Dans les tables virtuelles C ++, les valeurs de fonction sont toutes constantes et le prédicteur l'a facile. La CPU aura le code prêt à exécuter et dans le pipeline lorsque l'exécution passe par le saut indirect. Mais, s'il s'agit d'un pointeur de fonction imprévisible, l'impact de la performance peut être lourd car le pipeline devra être rincé qui gaspille de 20 à 40 cycles CPU avec chaque saut.


3 commentaires

OK, donc si j'ai quelques boucles imbriquées qui utilisent un tampon (chaque fois qu'il utilise la mémoire tampon, il ne conteste un pointeur deux fois dans cette FNC), les valeurs du pointeur (Présumable) seront prévisibles? Et ce ne sera pas vraiment important dans l'ensemble?


Si le tampon est suffisamment petit pour s'adapter au cache, les accès à la mémoire seront très rapides, qu'ils soient prévisibles ou non.


@ user965369: faites de votre mieux pour vous assurer que le tampon s'inscrit dans le cache L1, si vous ne pouvez pas le faire, le permet au moins de s'insérer dans le cache L2. Pour un processus de vitesse maximum, des tampons plus grands dans des blocs de taille cache.