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 :

Boucle for paire


Sujet :

C

  1. #1
    Membre averti
    Inscrit en
    Janvier 2007
    Messages
    37
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 37
    Par défaut Boucle for paire
    Bonjour,

    Sur un système embarqué à base de µcontroleur, je veux écrire des données dans un buffer mais uniquement une données sur deux.
    Ces données proviennent d'un accéléromètre via le bus SPI. Je ne veux sauvegarder dans mon buffer qu'une donnée sur deux. Je me suis arrangé pour toujours avoir un nombre de données paires en provenance de l'accéléromètre.
    J'ai déja écrit un petit morceaux de code mais je me demandais s'il y avait une manière plus élégante et surtout plus rapide en temps processeur pour faire ceci.

    Voici le code:
    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
     
     
    for(i=0; i< NbrAcc; i++){	
    	X[i] = spi_transfer(0x00)<<8; 		//X_MSB byte
    	X[i] |= spi_transfer(0x00);			//X_LSB byte
    	Y[i] = spi_transfer(0x00)<<8; 		//Y_MSB byte
    	Y[i] |= spi_transfer(0x00);			//Y_LSB byte
    	Z[i] = spi_transfer(0x00)<<8; 		//Z_MSB byte
    	Z[i] |= spi_transfer(0x00);			//Z_LSB byte	
     
    	if(i%2==0){	
    	buffer_writeDouble(X[i]);		//Store data 1/2 to buffer
    	buffer_writeDouble(Y[i]);
    	buffer_writeDouble(Z[i]);
    	}	
    }
    Merci.

  2. #2
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    Je ne sais pas comment est implémentée l'opération modulo par ton compilateur mais normallement, le modulo est le reste de la division entière et donc dans le pire des cas, le compilateur fait une division pour évaluer le modulo.

    Pour y gagner (peut être ?) un peu et vu que seul le résultat pair/impair t'intéresse, tu pourrais aussi faire un test sur le bit de poid faible de ta variable et remplacer par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    if( (i & 1) == 0)
    {
       // le nombre i est pair
    }
    else
    {
       // le nombre i est impair
    }
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  3. #3
    Invité(e)
    Invité(e)
    Par défaut
    Bonjour,

    On peut aussi faire des boucles avec un incrément de 2 :

    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
    for(i = 1; i < NbrAcc; i += 2){	
    	/* i est toujours impair dans cette boucle */
    	X[i] = spi_transfer(0x00)<<8; 		
    	X[i] |= spi_transfer(0x00);			
    	Y[i] = spi_transfer(0x00)<<8; 		
    	Y[i] |= spi_transfer(0x00);			
    	Z[i] = spi_transfer(0x00)<<8; 		
    	Z[i] |= spi_transfer(0x00);			
    
    	X[i-1] = spi_transfer(0x00)<<8; 		
    	X[i-1] |= spi_transfer(0x00);			
    	Y[i-1] = spi_transfer(0x00)<<8; 		
    	Y[i-1] |= spi_transfer(0x00);			
    	Z[i-1] = spi_transfer(0x00)<<8; 		
    	Z[i-1] |= spi_transfer(0x00);			
    		
    
    	buffer_writeDouble(X[i-1]);		//Store data 1/2 to buffer
    	buffer_writeDouble(Y[i-1]);
    	buffer_writeDouble(Z[i-1]);
    
    }

  4. #4
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    952
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Par défaut
    Salut,

    Si le but est vraiment l'économie de cycles-machine, tu peux éviter les variables temporaires sur la pile. On gagne en vitesse, mais on perd en lisibilité et factorisation du code. On peut aussi remplacer la boucle for par un while(NbrAcc--), mais attention à la post décrémentation qui inverse la parité.

    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
    for(i=0; i< NbrAcc; i++)
    {
        if( (i & 1) == 0)
        {
            buffer_writeDouble((spi_transfer(0x00)<<8) + spi_transfer(0x00));//Store data 1/2 to buffer
            buffer_writeDouble((spi_transfer(0x00)<<8) + spi_transfer(0x00));
            buffer_writeDouble((spi_transfer(0x00)<<8) + spi_transfer(0x00));
        }
        else
        {
            spi_transfer(0x00);
            spi_transfer(0x00);
            spi_transfer(0x00);
            spi_transfer(0x00);
            spi_transfer(0x00);
            spi_transfer(0x00);
        }
    }
    A+

    Pfeuh

  5. #5
    Membre averti
    Inscrit en
    Janvier 2007
    Messages
    37
    Détails du profil
    Informations forums :
    Inscription : Janvier 2007
    Messages : 37
    Par défaut
    Merci à tous de vos solutions. J'ai essayé plusieurs d'entre elles mais cela ne change pas le temps. Je reste donc à 8ms pour ce traitement. Ce qui est encore tout à fait acceptable pour mon application.

  6. #6
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par pegase.90 Voir le message
    Merci à tous de vos solutions. J'ai essayé plusieurs d'entre elles mais cela ne change pas le temps. Je reste donc à 8ms pour ce traitement. Ce qui est encore tout à fait acceptable pour mon application.


    Là tu calcules et tu fais 3 shitfts, 3 OU, et 6 assignations plus un test inutiles)...

    Moi je ferais (si j'ai bien compris qu'il te faut lire à tout coup) :

    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
    for(i=0; i< NbrAcc; i=i+2){	
    	X[i] = spi_transfer(0x00)<<8; 		//X_MSB byte
    	X[i] |= spi_transfer(0x00);			//X_LSB byte
    	Y[i] = spi_transfer(0x00)<<8; 		//Y_MSB byte
    	Y[i] |= spi_transfer(0x00);			//Y_LSB byte
    	Z[i] = spi_transfer(0x00)<<8; 		//Z_MSB byte
    	Z[i] |= spi_transfer(0x00);			//Z_LSB byte	
     
    	buffer_writeDouble(X[i]);		//Store data 1/2 to buffer
    	buffer_writeDouble(Y[i]);
    	buffer_writeDouble(Z[i]);
     
    	j = spi_transfer(0x00);
    	j = spi_transfer(0x00);
    	j = spi_transfer(0x00);
    	j = spi_transfer(0x00);
    	j = spi_transfer(0x00);
    	j = spi_transfer(0x00);
    	}	
    }
    A moins que cel soit voulu et que tu veuilles tout stocker, mais à ce compte-là tu remets des X[i+1] directement en dessous.

    Cependant le plus important est ci-dessous :

    Une autre optimisation est de faire référence à des pointeurs sur X, Y, et Z.

    Là, tu fais calculer entre 2 et 3 fois l'adresse à chaque fois.. une pour la première assignation, une pour le OU ligne suivante, une pour l'écriture

    Soit xp = &X[0]
    etc etc

    tu feras à chaque tour de boucle xp++ (si c'est bien ça), et non &X[0] + i*sizeof(type-de-X) que fait X[i]..

    tu économises donc une multiplication à chaque fois, et au total pour une variable 3 multiplications et deux additions.


    Exemple :

    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    int *xp, *yp, *zp ;
     
    xp = &X[0] ;
    yp = &Y[0] ;
    zp = &Z[0] ;
     
    for(i=0; i< NbrAcc; i=i+2){	
    	*xp = spi_transfer(0x00)<<8; 		//X_MSB byte
    	*xp |= spi_transfer(0x00);			//X_LSB byte
    	*yp = spi_transfer(0x00)<<8; 		//Y_MSB byte
    	*yp |= spi_transfer(0x00);			//Y_LSB byte
    	*zp = spi_transfer(0x00)<<8; 		//Z_MSB byte
    	*zp |= spi_transfer(0x00);			//Z_LSB byte	
     
    	buffer_writeDouble(*xp);		//Store data 1/2 to buffer
    	buffer_writeDouble(*yp);
    	buffer_writeDouble(*zp);
     
                 xp++ ; yp++ ; zp++ ;
     
    	*xp = spi_transfer(0x00)<<8; 		//X_MSB byte
    	*xp |= spi_transfer(0x00);			//X_LSB byte
    	*yp = spi_transfer(0x00)<<8; 		//Y_MSB byte
    	*yp |= spi_transfer(0x00);			//Y_LSB byte
    	*zp = spi_transfer(0x00)<<8; 		//Z_MSB byte
    	*zp |= spi_transfer(0x00);			//Z_LSB byte	
     
                 xp++ ; yp++ ; zp++ ;
    	}	
    }
    là j'ai repris ton code (tout stocker), mais avec une boucle sur 2.

  7. #7
    Membre Expert
    Profil pro
    Développeur en systèmes embarqués retraité
    Inscrit en
    Mars 2006
    Messages
    952
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Mars 2006
    Messages : 952
    Par défaut
    Citation Envoyé par souviron34 Voir le message
    Moi je ferais (si j'ai bien compris qu'il te faut lire à tout coup)
    Bien vu, du coup le mien devient;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    NbrAcc >>= 1; /* division pas 2 */
    while(NbrAcc--)
    {
            buffer_writeDouble((spi_transfer(0x00)<<8) + spi_transfer(0x00));
            buffer_writeDouble((spi_transfer(0x00)<<8) + spi_transfer(0x00));
            buffer_writeDouble((spi_transfer(0x00)<<8) + spi_transfer(0x00));
            spi_transfer(0x00);
            spi_transfer(0x00);
            spi_transfer(0x00);
            spi_transfer(0x00);
            spi_transfer(0x00);
            spi_transfer(0x00);
    }
    Je crois que de toute façon, le truc qui limite la vitesse, c'est plus la transmission spi que le peu de soft qu'il y a autour.

    A+

    Pfeuh

Discussions similaires

  1. Boucle for dans un script cmd
    Par nicolas.ganache dans le forum Développement
    Réponses: 4
    Dernier message: 19/07/2004, 16h07
  2. Réponses: 3
    Dernier message: 06/07/2004, 10h21
  3. [Debutant] Batch et Boucle for
    Par ludovic.fernandez dans le forum Scripts/Batch
    Réponses: 8
    Dernier message: 06/05/2004, 19h21
  4. [Swing][boucles] for, do, if .....comment faire simple?
    Par chastel dans le forum AWT/Swing
    Réponses: 7
    Dernier message: 02/05/2004, 22h49
  5. [langage] boucle "for" modification du pas
    Par K-ZimiR dans le forum Langage
    Réponses: 4
    Dernier message: 29/04/2004, 11h54

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