Emplacement de la déclation des variables

Bonjour,
Je viens de faire une manip à la c*n dont le résultat m'a surpris.

Le décors : IDE Ard 1.05 Linux.
Dans le répertoire du croquis :

  • 1 fichier *.ino
  • 1 fichier *.h
    Je cherche à obtenir une image du temps d'exécution d'une boucle (While + traitement de la condition).
    Dans un premier temps la variable boucle est déclarée à l'intérieur de la fonction machin définie dans le fichier *.ino
void machin()
{
   uint8_t boucle = 0  ;
   While (condition)  {  boucle++; }
   /-* Traitement de la variable  boucle*/
}

J'obtiens pour boucle une valeur autour de 200. Pour moi cette valeur dépend principalement du temps de traitement dans (condition) . "boucle++" ne devant prendre qu'un seul cycle horloge.

Si je déplace la déclaration de la variable boucle en dehors de la fonction c'est à dire dans le fichier *.h elle devient globale (enfin c'est ce que je pense) et la valeur de boucle est grossièrement divisée par deux. Ce qui laisse à penser que l'accès à une variable globale est plus lent que celui à une variable locale. Il doit y avoir une explication mais laquelle ?

Salut

J'avais ouvert un topic sur la même chose (entre autres) ici :

Et obtenu une réponse éclairée sur le point que tu soulèves :

barbudor:
Une variable statique est 100% équivalente d'un point de vue stockage et accès mémoire à une variable globale. C'est juste la portée du nom qui est limitée à la fonction dans laquelle elle est définie.
Or l'accès aux variables globales se fait via une adresse sur 2 octets ce qui demande un accès indexé plus complexe.

Une variable locale est allouée dans la pile et son accès est effectué via un déplacement réduit (généralement 1 octet) par rapport au pointeur de pile. L'instruction d'accès est donc plus simple.
Résultat une performance supérieure.

Et bien merci.

A noter que j'avais simplifié ma présentation au maximum.
En fait au début j'avais :

  • 1 fichier *.ino
  • 1 librairie avec ses fichiers *.h et *.cpp

La dégradation s'est manifesté dès que que j'ai voulu rendre la variable "boucle" publique pour l'exploiter simplement à partir du fichier *.ino
Et cette façon de procéder je l'ai rencontré plusieurs fois, c'est donc à éviter.
La parade que j'ai trouvé est de laisser "boucle" défini dans sa fonction et d'utiliser une variable intermédiaire(publique) à laquelle j'affectais la valeur finale de "boucle" pour la gestion à partir du fichier *.ino

Intéressant, et instructif.
Ca me rappelle ma jeunesse quand je faisais de l'assembleur Z80 en rentrant du collège (j'étais en 4ieme à l'époque). :smiley:

1984, sur Sinclair ZX81. 1986, je connaissais tellement par coeur que je codais directement en hexa.

notez la subtilité d'incrementer avec
subi r28, 0xFF

par curiosité, j'ai été voir la DS pour difference sur l'influence des Flags:
SUBI Rd, K Subtract Constant from Register :Z,C,N,V,H
INC Rd :Z,N,V
DEC Rd :Z,N,V

sauf erreur, pour l'atmega328, une addition de constante sur char se fera en 2 cycles, a moins qu'a la compilation se ne soit transformé en une soustraction de son negatif.

Salut 68tjs,

L'accès à une variable globale (ou statique) est deux fois plus lent que l’accès à une variable locale.
Atmel en parle dans ses doc d'optimisation de code source pour AVR-GCC :wink:
http://www.atmel.com/images/doc8453.pdf

Le pire c'est que ce document j'ai du le lire plusieurs fois ........

Que l'accès à une globale soit plus lent je le conçois.

Ce que je n'avais pas vu, et c'est sans doute du à mon manque d'habitude de la programmation objet, c'est que les variables définies dans le fichier.h sont des globales pour les variables définies publiques mais aussi que celle qui sont définies privées mais en dehors des méthodes qui les utilisent sont globales en interne à la classe (vrai/faux ?). Mais effectivement cela n'a rien d'illogique.

68tjs:
Ce que je n'avais pas vu, et c'est sans doute du à mon manque d'habitude de la programmation objet, c'est que les variables définies dans le fichier.h sont des globales pour les variables définies publiques mais aussi que celle qui sont définies privées mais en dehors des méthodes qui les utilisent sont globales en interne à la classe (vrai/faux ?). Mais effectivement cela n'a rien d'illogique.

Oula, j'ai rien compris :grin:

Je reprend :
Voila ce que j'ai compris : on a une classe donc deux fichiers "classe.h" et "classe.cpp", plus un fichier "utilisation.cpp" qui utilise la classe.

Variables définies dans le fichier "classe.h"

  • Variables Publiques :
    Elles se comportent comme des variables globales dans le fichier utilisation.cpp, ou bien ce comportement est limité au seul temps d'accès ?

  • Variables Privées
    Si elles sont déclarées dans le fichier classe.h, elles peuvent être utilisées directement par plusieurs méthodes privées donc elles ont le statut de variables globales limité à l'espace de la classe.cpp. Et donc un temps d'accès de variables globale.

Tu déclares la variables globale dans le .cpp et tu fait juste une déclaration en "extern" dans le .h si tu veux la rendre publique.
Si tu déclares directement la variable dans le .h tu vas avoir des soucis :wink:

Regarde dans les lib par défaut, Serial par exemple.
.cpp -> déclaration de la variable avec initialisation si besoin.
.h -> déclaration de la variable avec extern pour une utilisation globale publique.

J'ai comme l'impression que tu mélanges :

  • variables publiques : accessibles depuis n'importe quel fichier source moyennant une déclaration extern quelque par (déclaration dans .cpp sans static, avec re-déclaration extern dans .h).
  • variables globales limités à un fichier source : accessibles en tant que variable globale uniquement dans le fichier source courant (déclaration dans .cpp avec static, hors de toute fonction, rien dans .h).
  • variables privés : accessible uniquement dans le scope de la fonction ou du bloc courant
  • variables privés statiques : équivalent d'une variable globale limité mais avec une seconde limite qui permet son accès uniquement dans le bloc/fonction de la déclaration.

Je crois surtout que je n'arrive pas à exprimer clairement ce que je sens.

Prenons un exemple : la gestion des capteur DHxx.
Cet exemple n'est pas pris au hasard, je suis dessus et je ressens que la classe a été écrite par un "softeux" et non pas un "hardeux" comme disent les djeuns d'où ma préoccupation de "hardeux" sur l'adéquation vitesse du code/vitesse de réponse du matériel.

Extrait du fichier dht.h

class dht
{
public:
    // return values:
    // DHTLIB_OK
    // DHTLIB_ERROR_CHECKSUM
    // DHTLIB_ERROR_TIMEOUT
    int read11(uint8_t pin);
    int read(uint8_t pin);

    inline int read21(uint8_t pin) { return read(pin); };
    inline int read22(uint8_t pin) { return read(pin); };
    inline int read33(uint8_t pin) { return read(pin); };
    inline int read44(uint8_t pin) { return read(pin); };

    double humidity;
    double temperature;

private:
    uint8_t bits[5];  // buffer to receive data
    int _readSensor(uint8_t pin, uint8_t wakeupDelay);
};

Question d'après toi quel statut ont les variables publiques humidity et temperature ?

Et quel statut aurait une variable déclarée dans la partie private par rapport à la méthode private readSensor?

68tjs:
Extrait du fichier dht.h
(…)

Celui qui a écrit ce morceau de code ne devait pas être bien réveillé :grin:
5 fonctions, dont 4 inline, pour faire la même chose … mouai.
Et le principe d’encapsulation il devait pas connaitre, bref.

68tjs:
Question d’après toi quel statut ont les variables publiques humidity et temperature ?

Attention : ici on est dans le cadre d’une déclaration de membres de classe !

Ici humidity et temperature ne sont pas publiques au sens C, elles sont publiques au sens C++.
Sous entendu : ce sont des variables publiques DE LA CLASSE, il faut passer par l’instance d’un objet de type “dht” pour y accéder.

Pour faire simple : variables publiques de classe en C++ = équivalent des membres d’une structure en C.

68tjs:
Et quel statut aurait une variable déclarée dans la partie private par rapport à la méthode private readSensor?

Variable dans la partie “public” : accessible au travers de l’instance de l’objet par un code extérieur.
Variable dans la partie “private” : accessible uniquement pas le code de l’objet.
Dans les deux cas ce sont des variables de l’objet, pas des variables publiques au sens C.