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 :

Borner un tableau - Optimisation


Sujet :

C

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2014
    Messages
    5
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2014
    Messages : 5
    Points : 6
    Points
    6
    Par défaut Borner un tableau - Optimisation
    Bonjour à toutes et à tous,

    je viens vers vous pour une question d'optimisation de bornes de tableau.
    Le problème est extrêmement simple, nous avons un tableau, et on veut le borner (lui affecter un min et un max). Au lieu de la borne, on aurait pu faire n'importe quel traitement, peu importe.

    Je poste le code utilisé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for (j=0;j<WIDTH*HEIGHT;j++)
    {
            imagedata[j] = min(max(buffer[j],0),4095);
    }
    Peut-on faire plus rapide que ceci ?

    J'ai aussi remarqué qu'il y avait une grosse différence de temps d'exécution entre un memcpy et une affectation via une boucle. J'ai essayé de lire la doc de memcpy mais j'avoue ne pas comprendre comment ils gagnent autant de temps. Une explication serait la bienvenue

    Merci d'avance,

    Martin.

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 689
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 689
    Points : 30 983
    Points
    30 983
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par tinte Voir le message
    Peut-on faire plus rapide que ceci ?
    Bonjour

    Passer par un pointeur...

    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for (j=0, ptI=imagedata, ptB=buffer;j<WIDTH*HEIGHT;j++, ptI++, ptB++)
    {
            (*ptI) = min(max(*ptB, 0), 4095);
    }

    Citation Envoyé par tinte Voir le message
    J'ai aussi remarqué qu'il y avait une grosse différence de temps d'exécution entre un memcpy et une affectation via une boucle. J'ai essayé de lire la doc de memcpy mais j'avoue ne pas comprendre comment ils gagnent autant de temps. Une explication serait la bienvenue
    Probablement parce que memcpy travaille sur des octets et utilise lui-aussi des pointeurs pour se déplacer d'un octet à l'autre

    Exemple
    Code c : 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
    int main()
    {
        double tab[100]={...};
        double copie[100];
     
        copy1(copie, tab, 100);
        copy2(copie, tab, 100 * sizeof(double));
    }
     
    void copy1(double *c, double *o, size_t n)
    {
        size_t i;
        for (i=0; i < n; i++) c[i]=o[i];
    }
     
    void copy2(void *c, void *o, size_t n)
    {
        size_t i;
        char *ptC;
        char *ptO;
        for (i=0, ptC=c, ptO=o; i < n; i++, ptC++, ptO++) (*ptC)=(*ptO);
    }

    A chaque fois que tu accèdes à tab[i], le processus repart de tab pour lui appliquer un déplacement de "i * taille_element". Avec un pointeur déjà positionné, ce décalage ne se fait plus...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Membre éclairé
    Inscrit en
    Juillet 2012
    Messages
    231
    Détails du profil
    Informations forums :
    Inscription : Juillet 2012
    Messages : 231
    Points : 870
    Points
    870
    Par défaut
    Citation Envoyé par tinte
    Peut-on faire plus rapide que ceci ?
    Tu pourrais avoir un gain en utilisant des instructions SIMD (les compilateurs font des progrès en auto-vectorisation mais c’est pas encore le pied, il faut souvent les aider (préciser l’alignement de tes données par exemple) voire le faire soi-même).

    Citation Envoyé par Sve@r
    A chaque fois que tu accèdes à tab[i], le processus repart de tab pour lui appliquer un déplacement de "i * taille_element". Avec un pointeur déjà positionné, ce décalage ne se fait plus...
    Ça c’est vrai si tu compiles sans optimisation et/ou que ton compilateur est pourri…
    N’importe quel compilateur décent avec un minimum d’optimisation devrait fournir un code équivalent pour les deux versions. Il ne faut pas espérer de gain avec ça.

    Le vrai gain vient de copier par paquet de 4 ou 8 bytes (voir plus si tu utilises les instructions vectorielles) au lieu de byte par byte.

    Mais le vrai secret de memcpy c’est que, souvent, le compilateur possède sa propre implémentation (intrinsic) qu’il peut utiliser au lieu de la version fournit par la libc. Étant donné que le code fait partie du compilateur, il est connu et le compilateur peut donc présumer plus de choses et faire plus d’optimisation (voire choisir une version adapté à ton CPU).
    Enfin, même sans cela, les libc viennent avec une version optimisée (voir plusieurs versions*: pour certaines fonctions la GNU libc à une version C + des versions en assembleurs qui utilisent SSE2, SSE3, …).

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 630
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 630
    Points : 10 556
    Points
    10 556
    Par défaut
    Avec des unsigned tu peux supprimer le minimum

    Et apparemment le code le plus simple est assez rapide (pas d'appel de fonction) et surtout si tu es sûr que tes valeurs sont faiblement au delà du maximum:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    #define CLAMP(VAL, MAX) ((VAL <= MAX)? VAL: MAX);
     
     
         imagedata[j] = CLAMP(buffer[j], 4095)

Discussions similaires

  1. Mise en forme d'un tableau (optimisation)
    Par Madfrix dans le forum Langage
    Réponses: 2
    Dernier message: 27/02/2010, 11h28
  2. dessiner un très grand tableau + optimisation en temps
    Par identifiant_bidon dans le forum Balisage (X)HTML et validation W3C
    Réponses: 11
    Dernier message: 18/01/2008, 10h15
  3. Réponses: 10
    Dernier message: 06/07/2006, 21h57
  4. Réponses: 2
    Dernier message: 25/11/2005, 13h07
  5. Parcours de tableau et optimisation
    Par mik007 dans le forum Général JavaScript
    Réponses: 11
    Dernier message: 22/11/2005, 09h57

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