IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Accès le plus rapide: Pointeur ou tableau?


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre émérite Avatar de homeostasie
    Homme Profil pro
    Inscrit en
    Mai 2005
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 939
    Par défaut Accès le plus rapide: Pointeur ou tableau?
    A chaque commuation de tâche, j'ai créé un hook afin de sauvegarder quelques informations concernant les x dernières taches dans un buffer circulaire.

    En terme de rapidité d'éxécution (pour rester le moins de temps possible dans ce hook), vaut il mieux faire cela:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    void PRF_SaveRegSwitchHook(WIND_TCB *oldTcbPtr, WIND_TCB *newTcbPtr)
    {
      	REG_SET regSet;			/*Task registers*/
    	TASK_DESC taskDesc;		/*information structure */
    	newTaskInfo newtaskInfo;
    	tracePostMortem *TaskInfoTemp = NULL;
     
       	/*Critical section: temporay storage pointer to optimize the speed.*/
       	TaskInfoTemp = &TaskInfoBuf[indexBuf];
     
       	TaskInfoTemp->taskId = taskNameToId(oldTcbPtr->name);
       	if (taskRegsGet (TaskInfoBuf[indexBuf].taskId, &regSet) != ERROR){
       		TaskInfoTemp->registers = regSet;
       		TaskInfoTemp->TaskSP = (int)GetSP();
    		TaskInfoTemp->TaskFP = (int)GetFP(); 
       	}
     
    	TaskInfoTemp->stackBase = (UInt32) oldTcbPtr->pStackBase;
    	TaskInfoTemp->stackLimit = (UInt32) oldTcbPtr->pStackLimit;
    	TaskInfoTemp->stackEnd = (UInt32) oldTcbPtr->pStackEnd;
    }
    à ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
     
    void PRF_SaveRegSwitchHook(WIND_TCB *oldTcbPtr, WIND_TCB *newTcbPtr)
    {
      	REG_SET regSet;			/*Task registers*/
    	TASK_DESC taskDesc;		/*information structure */
    	newTaskInfo newtaskInfo;
     
       	TaskInfoBuf[indexBuf].taskId = taskNameToId(oldTcbPtr->name);
       	if (taskRegsGet (TaskInfoBuf[indexBuf].taskId, &regSet) != ERROR){
       		TaskInfoBuf[indexBuf].registers = regSet;
       		TaskInfoBuf[indexBuf].TaskSP = (int)GetSP();
    		TaskInfoBuf[indexBuf].TaskFP = (int)GetFP(); 
       	}
     
    	TaskInfoBuf[indexBuf].stackBase = (UInt32) oldTcbPtr->pStackBase;
    	TaskInfoBuf[indexBuf].stackLimit = (UInt32) oldTcbPtr->pStackLimit;
    	TaskInfoBuf[indexBuf].stackEnd = (UInt32) oldTcbPtr->pStackEnd;
    }
    Si c'est bien le cas, pourrait on m'expliquer le pourquoi?

    Remarque: indexBuf est une variable globale au module déclaré comme suit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    static UInt16 indexBuf = 0;
    Merci

  2. #2
    Membre chevronné
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 464
    Par défaut
    A première vue je pencherais pour la 1ère version :
    indexBuf étant global, il doit à priori être réévalué à chaque accès à la structure dans la seconde version, ce qui n'est pas le cas dans la 1ère.

  3. #3
    Membre émérite Avatar de homeostasie
    Homme Profil pro
    Inscrit en
    Mai 2005
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 939
    Par défaut
    indexBuf étant global, il doit à priori être réévalué à chaque accès à la structure dans la seconde version, ce qui n'est pas le cas dans la 1ère.
    Je me suis dit qu'il y avait peut être un truc de ce genre qui se cachait derrière. En fait, en quoi consiste une réévaluation? Quels sont les étapes?

    Rq: J'ai supprimé des lignes dans ma fonction, d'où la déclaration de variables non utilisées. De même,il manque l'incrémention de indexBuf en fin de fonction selon un modulo.

  4. #4
    Membre chevronné
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 464
    Par défaut
    Citation Envoyé par fearyourself
    Faux, un compilateur bien réglé le fera seulement pour le premier accès au tableau et après fera des déplacements relatifs.
    Je ne vois pas trop comment.

    IndexBuf étant global (je me répète), sa valeur peut théoriquement changer à tout moment :
    donc je ne vois pas trop comment le compilateur pourrait faire l'économie de recharger à chaque accès à la structure sa valeur dans un registre (+ éventuellement un scale).

  5. #5
    Membre émérite Avatar de homeostasie
    Homme Profil pro
    Inscrit en
    Mai 2005
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 939
    Par défaut
    IndexBuf étant global (je me répète), sa valeur peut théoriquement changer à tout moment :
    donc je ne vois pas trop comment le compilateur pourrait faire l'économie de recharger à chaque accès à la structure sa valeur dans un registre (+ éventuellement un scale).
    Ceci me parait logique suite à ton explication.
    Faire ceci, serait donc une autre solution équivalente à la première (excepté que je déclare une variable locale en plus):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    void PRF_SaveRegSwitchHook(WIND_TCB *oldTcbPtr, WIND_TCB *newTcbPtr)
    {
      	REG_SET regSet;			/*Task registers*/
    	TASK_DESC taskDesc;		/*information structure */
    	newTaskInfo newtaskInfo;
            int index = indexBuf;
    
       	TaskInfoBuf[inde].taskId = taskNameToId(oldTcbPtr->name);
       	if (taskRegsGet (TaskInfoBuf[index].taskId, &regSet) != ERROR){
       		TaskInfoBuf[index].registers = regSet;
       		TaskInfoBuf[index].TaskSP = (int)GetSP();
    		TaskInfoBuf[index].TaskFP = (int)GetFP(); 
       	}
    	
    	TaskInfoBuf[index].stackBase = (UInt32) oldTcbPtr->pStackBase;
    	TaskInfoBuf[index].stackLimit = (UInt32) oldTcbPtr->pStackLimit;
    	TaskInfoBuf[index].stackEnd = (UInt32) oldTcbPtr->pStackEnd;
    
            indexBuf = (indexBuf+1) % SavedContextNum;
    }

  6. #6
    Membre chevronné
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 464
    Par défaut
    Citation Envoyé par homeostasie
    Faire ceci, serait donc une autre solution équivalente à la première (excepté que je déclare une variable locale en plus):
    En effet.

    Dans cette nouvelle version le code est beaucoup plus "optimizer friendly" !

    Et la variable locale supplémentaire ne changera pas grand chose par rapport à la toute 1ère version : ce qui compte c'est qu'il n'y ait plus qu'un seul accès à indexBuf.

  7. #7
    Expert confirmé

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Par défaut
    Citation Envoyé par rigobert
    Je ne vois pas trop comment.

    IndexBuf étant global (je me répète), sa valeur peut théoriquement changer à tout moment :
    donc je ne vois pas trop comment le compilateur pourrait faire l'économie de recharger à chaque accès à la structure sa valeur dans un registre (+ éventuellement un scale).
    Parce que dans l'exemple cité, il n'est pas mention de multi-thread. Un compilateur bien réglé considérera donc qu'on ne modifie pas cette variable globale sauf s'il y a des appels de fonctions ou des accès à des pointeurs...

    En supposant que le compilateur n'a pas fait de inline et que donc les appels seront encore là à la génération de code, on aura effectivement quelque chargement de plus mais si la valeur n'a pas changé elle sera vraisemblablement dans le cache donc on ne sentira pas vraiment de ralentissement (à mon avis)

    Voici tout de même les fois où la valeur sera normalement rechargée :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    void PRF_SaveRegSwitchHook(WIND_TCB *oldTcbPtr, WIND_TCB *newTcbPtr)
    {
      	REG_SET regSet;			/*Task registers*/
    	TASK_DESC taskDesc;		/*information structure */
    	newTaskInfo newtaskInfo;
    
       	TaskInfoBuf[indexBuf].taskId = taskNameToId(oldTcbPtr->name);
       	if (taskRegsGet (TaskInfoBuf[indexBuf].taskId, &regSet) != ERROR){
       		TaskInfoBuf[indexBuf].registers = regSet;
       		TaskInfoBuf[indexBuf].TaskSP = (int)GetSP();
    		TaskInfoBuf[indexBuf].TaskFP = (int)GetFP(); 
       	}
    	
    	TaskInfoBuf[indexBuf].stackBase = (UInt32) oldTcbPtr->pStackBase;
    	TaskInfoBuf[indexBuf].stackLimit = (UInt32) oldTcbPtr->pStackLimit;
    	TaskInfoBuf[indexBuf].stackEnd = (UInt32) oldTcbPtr->pStackEnd;
    }
    A savoir qu'il fusionnera sûrement les deux derniers chargements.

    Donc certes c'est plus qu'une fois dans le cas où les fonctions ne sont pas mises en inline mais l'impact sera moindre à mon avis.

    L'utilisation de la variable locale est bien sûr conseillé.

    Jc

  8. #8
    Membre émérite Avatar de homeostasie
    Homme Profil pro
    Inscrit en
    Mai 2005
    Messages
    939
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 939
    Par défaut
    Tu as essayé de faire des tests (simple chronométrage de la fonction ou en utilisant un outils plus évolué) ?
    Je vais tâcher de faire cela prochainement et j'en ferais part quand j'aurais le résultat.

    ça oblige tout de même le processeur à effectuer le calcul :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    &TaskInfoBuf[0] + index
    Cela signifie donc que c'est équivalent à:
    pour chaque utilisation de la structure. Si c'est réellement ansi, il vaut donc mieux utiliser un pointeur pointant sur l'adresse de TaskInfoBuf[indexBuf] comme fait dans la première solution...

    Donc à rechercher la valeur de index à chaque fois. Tu peux essayer de lui demander de stocker index dans un registre :
    mais si index est déjà en cash, pas besoin de stocker dans un registre, non?

    Un compilateur bien réglé considérera donc qu'on ne modifie pas cette variable globale sauf s'il y a des appels de fonctions ou des accès à des pointeurs...
    C'est donc à moi d'apprendre à bien régler le compilateur...Je suppose qu'il y a des cours généraux sur cela, car je me dis que chaque compilateur à ses particularités.

  9. #9
    Membre chevronné
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    464
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 464
    Par défaut
    Citation Envoyé par fearyourself
    Parce que dans l'exemple cité, il n'est pas mention de multi-thread. Un compilateur bien réglé considérera donc qu'on ne modifie pas cette variable globale sauf s'il y a des appels de fonctions ou des accès à des pointeurs...
    Il n'est pas fait mention non plus de mono-threading.

    A défaut de savoir, mieux vaut toujours envisager la pire hypothèse.

    En plus, si c'est d'un hook système dont il s'agit, l'hypothèse d'un environnement multi-threadé est assez plausible ... sauf si on est sous TOS !

  10. #10
    Expert confirmé

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Par défaut
    Citation Envoyé par homeostasie
    A chaque commuation de tâche, j'ai créé un hook afin de sauvegarder quelques informations concernant les x dernières taches dans un buffer circulaire.

    En terme de rapidité d'éxécution (pour rester le moins de temps possible dans ce hook), vaut il mieux faire cela:
    Pareil dans 90% des cas, le compilateur sortira le même code.

    A première vue je pencherais pour la 1ère version :
    indexBuf étant global, il doit à priori être réévalué à chaque accès à la structure dans la seconde version, ce qui n'est pas le cas dans la 1ère.
    Faux, un compilateur bien réglé le fera seulement pour le premier accès au tableau et après fera des déplacements relatifs.

    De toute facon, la seule réponse valable sera sûrement :

    A tester. Lance 10000 fois les deux versions, regarde le temps sur différentes architectures et fait une synthése.
    Jc

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. la Recherche la Plus Rapide dans un tableau
    Par linuxeur dans le forum C
    Réponses: 10
    Dernier message: 23/05/2008, 00h07
  2. Mode d'accès le plus rapide ?
    Par QAYS dans le forum Bases de données
    Réponses: 4
    Dernier message: 17/10/2007, 10h38
  3. Réponses: 15
    Dernier message: 05/09/2006, 16h10
  4. dans quels cas les pointeur sont plus rapides ?
    Par 180degrés dans le forum C++
    Réponses: 12
    Dernier message: 20/08/2005, 23h12
  5. Réponses: 8
    Dernier message: 31/10/2003, 16h21

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo