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 :

[Performance] Image RGB et GrayScale


Sujet :

C++

  1. #1
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut [Performance] Image RGB et GrayScale
    Bonjour à tous,

    J'aurai voulu quantifier la perte de performance entre une image RGBA (3 channels + couche alpha) et une image GrayScale (un seul canal) dans des algorithmes.
    Est-ce 3 fois plus lent en RGB? 4 fois plus lent?
    Ou bien est-ce que ça dépend du processeur (mise en cache, alignement, etc...) ou de l'OS (32, 64 bits)

    J'avoue ne vraiment pas avoir d'idées sur le sujet. Merci d'éclairer ma lanterne !

  2. #2
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Ben es ce que les opération sur int (RGBA) est plus longue que sur char(GrayScale)???

    Tout depend de ce que tu fait.
    Pour additionner ce sera proche, pour gérer de l'alpha ça sera plus long.
    Quels type de traitement fait tu?

  3. #3
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut
    Mes traitements sont très différents d'une fonction à l'autre, mais globalement je touche pas trop à l'alpha.
    Quelques exemples:
    • Parcours d'images avec recherche de maximum/moyenne
    • Multiplication de l'image par une constante
    • Soustraction d'une image par rapport à une autre

    Les fonctions plus avancées se décomposant toujours en une somme d'opérations plus simple...

    Tu penses que pour des traitements simples comme soustraire une image à une autre les performances vont être quasi identique? Pourtant il faudra bien itérer sur les 3 composantes RGB, c'est plus long non?


  4. #4
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par poukill Voir le message
    Tu penses que pour des traitements simples comme soustraire une image à une autre les performances vont être quasi identique? Pourtant il faudra bien itérer sur les 3 composantes RGB, c'est plus long non?
    Je pense que ce ne sera pas 3 fois.
    De ce que je comprend, ce qui prend surtout du temps dans le traitement d'image ce sont les boucles (préférer une seul boucle pour parcourir tout les pixels) et les accès mémoire(préférer de la mémoire contigüe).
    Ceci sera très proche pour les deux types d'images.

    Donc ce qui reste est le temps de ton traitement par pixel. Je ne pense pas qu'une recherche de maximum ou moyenne pour du rgb soit 3 fois plus longue que pour GrayScale. Le compilo y ferra surement des optimisations.

    Tu devrais poser la question sur le forum de traitement d'image, tu auras surement de meilleur avis
    http://www.developpez.net/forums/f64...ement-dimages/

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    399
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 399
    Points : 413
    Points
    413
    Par défaut
    tout depend si tu fais tes opération au pixel sur les composantes couleurs (4 opérations sur 8 bits par pixels en RGBA) ou sur la couleur en elle même (1 opération sur 32 bits). Si c'est sur la couleur en elle même, les perf seront plus ou moins identiques car la boucle fera la même longueur (ce sera juste des opérations sur 32 bits au lieu de 8 bits -> a voir les différences de perfs niveau hardware). Par contre si c'est sur chaque composante couleur séparément, la ta boucle sera 4 fois plus longue avec des opérations sur 8 bits donc ton algo prendra 4 fois plus de temps.

    Après niveau rendu, une chose est sur la gestion de l'alpha le ralenti de facon significative car tu a les opérations de blending qui s'ajoute.
    SPARK
    Moteur de particule C++ opensource avec modules de rendu OpenGL, Irrlicht et SFML

  6. #6
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut
    Merci à vous pour vos réponses.
    On pourrait assimiler:
    • une image RGB à un std::vector <RGBValue> ( 3 * 8 bits)
    • une image GrayScale à un vector<unsigned short> (16 bits)

    Je pensais que du coup on est obligé d'itérer sur les 3 composantes au lieu d'une sur la greyscale et qu'on a une perte de temps assez importante...

    J'entends pas mal de gens autour de moi dire effectivement que un algo simple appliqué sur une image RGB sera à peine plus lent que sur une GrayScale.
    Je pense que je vais écrire quelques benchmarks dès que possible pour mettre un début à ce débat. Y'a rien de mieux que l'expérience non ?


  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    399
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 399
    Points : 413
    Points
    413
    Par défaut
    Citation Envoyé par poukill Voir le message
    Merci à vous pour vos réponses.
    On pourrait assimiler:
    • une image RGB à un std::vector <RGBValue> ( 3 * 8 bits)
    • une image GrayScale à un vector<unsigned short> (16 bits)
    Seulement si ton image RGB est en 8 bits par couches et ton gray scale en 16 bits. En regle général le grayscale sera plutot en 8 bits.

    Pour en revenir a la rapidité d'une opération entre grayscale et image RGB, ca depend vraiment de l'opération. Pour les opérations que tu cites tu devra travailler sur chacune des composantes indépendamment, ce sera donc 3 fois plus lent.

    Par exemple pour trouver la moyenne entre 2 couleurs, mettons en RGBA (FF,00,00,FF) et (00,00,FF,FF), la moyenne que tu cherche sera naturellement (7F,00,7F,FF). Si tu travailles sur la couleur en entier tu va te retrouver avec (0xFF0000FF + 0x0000FFFF) >> 1 = 0x7F08087F qui n'est pas le résultat recherché. Donc pour ce cas la, ca va te prendre plus de temps en effet.

    Par contre si tu travaille sur une composante uniquement. Par exemple rajouter du vert, la ca sera a peu pret identique en temps que de rajouter du gris dans un image grayscale.

    Ou un autre exemple passer une image en négatif, il suffit d'inverser les bits de toute la couleur (même sur toute l'image en fait). Donc la tu travaille sur la couleur et non plus sur la composante, donc performance plus ou moins équivalentes aussi. [EDIT]Mais dans ce cas tu peux optimisé en travaillant sur 32bits par exemple, donc le grayscale sera encore une fois plus rapide car moins de données a traiter. Donc c'est un mauvais exemple

    Donc, oui le traitement d'image RGB prend en général plus de temps que celui en grayscale. Ce qui est logique dans la mesure ou il y a 3 canaux. Mais encore une fois, tout dépend du format d'image et de l'opération
    SPARK
    Moteur de particule C++ opensource avec modules de rendu OpenGL, Irrlicht et SFML

  8. #8
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par Frifron Voir le message
    Pour en revenir a la rapidité d'une opération entre grayscale et image RGB, ca depend vraiment de l'opération. Pour les opérations que tu cites tu devra travailler sur chacune des composantes indépendamment, ce sera donc 3 fois plus lent.
    Perso, je ne périrai pas dessus. Le compilo peut certainement faire des chose pour optimiser.
    Y as plus qu'un petit bench a faire pour vérifier

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    399
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 399
    Points : 413
    Points
    413
    Par défaut
    D'accord, mais le compilo ne va pas te changer la complexité de l'algo. Une opération par pixel va être linéaire. Tu multiplies par 3 le nombre de données sur lesquelles réaliser l'opération, bah le temps de calcul sera multiplié par 3
    SPARK
    Moteur de particule C++ opensource avec modules de rendu OpenGL, Irrlicht et SFML

  10. #10
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    #include <iostream>
    #include <vector>
    #include <list>
    #include <deque>
    #include <set>
    #include <algorithm>
    #include <ctime>
    #include <cmath>
    using namespace std;
    const int num =1000;
    template<typename T>
    struct image
    {
        image(int hh,int ww)
        :h(hh),w(ww),buffer(hh*ww)
        {};
        int h;
        int w;
        vector<T> buffer;
    };
     
    struct pix
    {
        pix():r(0),g(0),b(0)
        {};
     
        pix(char rr,char gg,char bb)
        :r(rr),g(gg),b(bb)
        {}
     
        char r;
        char g;
        char b;
        pix& operator*=(int a)
        {
            r*=a;
            g*=a;
            b*=a;
               return *this;
        }
    };
     
    struct gen
    {
        char operator()()
        {
            return rand()%256+1;
        }
    };
     
    struct genpix
    {
        pix operator()()
        {
            pix p;
            p.r = rand()%256+1;
            p.g = rand()%256+1;
            p.b = rand()%256+1;
            return p;
        }
     
    };
    template <typename T>
    struct multiplie
    {
        multiplie(int aa):a(aa){};
        void operator()(T & pix)
        {
            pix*=a;
     
        }
        int a;
    };
     
     
    struct MIN
    {
        MIN():min(255){};
        void operator()(char pix)
        {
            if (pix<min) min = pix;
        }
        char min;
    };
     
    struct MINPIX
    {
        MINPIX()
        :min(255,255,255)
        {};
        void operator()(const pix & pix)
        {
            if (pix.r<min.r) min.r = pix.r;
            if (pix.g<min.g) min.g = pix.g;
            if (pix.b<min.b) min.b = pix.b;
        }
        pix min;
    };
    int main(int argc, char* argv[])
    {
    srand(clock());
       image<char> img(1000,1000);
       std::generate
           (
               img.buffer.begin(),
               img.buffer.end(),
               gen()
           );
       image<pix>  imgRGB(1000,1000);
        std::generate
           (
               imgRGB.buffer.begin(),
               imgRGB.buffer.end(),
               genpix()
           );
     
     
        while(1)
        {
        clock_t t0 = clock();
     
        for (int i =0;i<num;++i)
        {
            std::for_each
                (
                    img.buffer.begin(),
                    img.buffer.end(),
                    multiplie<char>(2)
                 );
        }
        double tempA = double(clock()-t0)/num;
        std::cout<<"************MULTIPLICATION**************" <<std::endl;
        std::cout<<"grayscale""  "<<tempA <<std::endl;
     
        t0 = clock();
        for (int i =0;i<num;++i)
        {
            std::for_each
                (
                    imgRGB.buffer.begin(),
                    imgRGB.buffer.end(),
                    multiplie<pix>(2)
                 );
        }
        double tempB = double(clock()-t0)/num;
        std::cout<<"rgb"<<"  "<<tempB <<std::endl;
     
        std::cout<<"rgb/grayscale"<<" "<<100*(tempB/tempA)<<"%"<<std::endl;
     
        t0 = clock();
        int min;
        for (int i =0;i<num;++i)
        {
            min = std::for_each
                (
                    img.buffer.begin(),
                    img.buffer.end(),
                    MIN()
                 ).min;
        }
        tempA = double(clock()-t0)/num;
        std::cout<<"************MIN**************" <<std::endl;
        std::cout<<"grayscale""  "<<tempA <<std::endl;
     
        t0 = clock();
        pix minpix;
        for (int i =0;i<num;++i)
        {
           minpix = std::for_each
                (
                    imgRGB.buffer.begin(),
                    imgRGB.buffer.end(),
                    MINPIX()
                 ).min;
        }
        tempB = double(clock()-t0)/num;
        std::cout<<"rgb "<<minpix.r<<"  "<<minpix.g<<"  "<<minpix.b<<"  "<<tempB <<std::endl;
     
        std::cout<<"B/A"<<" "<<100*(tempB/tempA)<<"%"<<std::endl;
        }
     
    	return 0;
    }
    sous visual :
    multiplication : rapport de 211%
    recherche du min : rapport de 450% (ca je m'y attendais pas)

    sous mingw :
    multiplication : identique
    recherche du min : rapport de 339%

    [edit]
    j'ai utilisé des char au lieu des unsigned char mais les résultat sont pareil.

  11. #11
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    Pour certains types d'opérateurs, il est possible de multithreadé par canaux les opérateurs. (chaque thread s'occupe d'un canal ce qui réduit donc en général bien le temps sur les quad-core)

    Maintenant, il faut voir aussi le type d'opération. Si ça prend 1ms pour du mono canal ou 3ms pour du RGB, c'est pas la fin du monde (sauf si tu fais l'opération 100 fois par seconde). Si c'est 10 sec pour du mono ou du 30 sec pour du RGB, là il faut se poser des questions.

    En Java, sur un quad-core, avec mes algorithmes, j'ai un temps équivalent pour du RGB ou du Gray.

    EDIT : J'avais également fait de tests dans le temps en C++ sur des Solaris quadri-processeur, ça réduisait bien le temps.
    Je ne répondrai à aucune question technique en privé

  12. #12
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    399
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 399
    Points : 413
    Points
    413
    Par défaut
    On arrive tout de même a des perf bien inferieure en RGB. De plus tu ne testes pas l'overflow sur la multiplication. Je l'ai rajouté et on passe à un ratio de 290% (VISUAL).

    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
     
    struct multiplie
    {
        multiplie(int aa):a(aa){};
        void operator()(unsigned char& pix)
        {
            pix = std::min(255,pix * a);
        }
        int a;
    };
     
    struct multipliePIX
    {
        multipliePIX(int aa):a(aa){};
        void operator()(pix& pix)
        {
            pix.r = std::min(255,pix.r * a);
            pix.g = std::min(255,pix.g * a);
            pix.b = std::min(255,pix.b * a);
        }
        int a;
    };
    Quand tu dis "identique" sous mingw ca veut dire identique a visual ou 100% ? Et ca donne quoi avec le seuil ?
    SPARK
    Moteur de particule C++ opensource avec modules de rendu OpenGL, Irrlicht et SFML

  13. #13
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 033
    Points : 13 968
    Points
    13 968
    Par défaut
    Citation Envoyé par Frifron Voir le message
    On arrive tout de même a des perf bien inferieure en RGB.
    Bien sur. Rien n'est magique. Je voulais juste dire que le compilo peut faire des chose qui réduise l'écart.

    Citation Envoyé par Frifron Voir le message
    De plus tu ne testes pas l'overflow sur la multiplication. Je l'ai rajouté et on arrive à un ratio de 308% (VISUAL)
    c'est pour cela que j'avais la multiplication et le min. Histoire de pas tout mélanger.

  14. #14
    Membre averti
    Profil pro
    Inscrit en
    Mai 2005
    Messages
    399
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France

    Informations forums :
    Inscription : Mai 2005
    Messages : 399
    Points : 413
    Points
    413
    Par défaut
    Enfin de toute facon un produit en traitement de l'image c'est plutot sur une echelle de 0 a 1 donc en fait ca donne plutot ca :

    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
     
    struct multiplie
    {
        multiplie(int aa):a(aa){};
        void operator()(unsigned char& pix)
        {
            pix = (pix * a) / 255;
        }
        int a;
    };
     
    struct multipliePIX
    {
        multipliePIX(int aa):a(aa){};
        void operator()(pix& pix)
        {
            pix.r = (pix.r * a) / 255;
            pix.g = (pix.g * a) / 255;
            pix.b = (pix.b * a) / 255;
        }
        int a;
    };
    Avec ca on a du 299%. Les opti ici sont négligeables. Mais en effet pour certaines opérations le compilo optimisera ce qui descendra en dessous des 3 fois plus lent. Par ailleurs pour d'autres (ton min par exemple) on se retrouve avec des opérations qui prennent plus de 3x le temps. Donc on peut tout de même affirmer que les opérations au pixel sur du RGB sont plus lentes en rêgles générale. Après la solutions du multithread peut en effet amoindrir considérablement le différence dans le cas de proc multi core.
    SPARK
    Moteur de particule C++ opensource avec modules de rendu OpenGL, Irrlicht et SFML

  15. #15
    Membre éclairé

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    717
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 717
    Points : 858
    Points
    858
    Par défaut
    Et si l'image en niveaux de gris rentre dans le cache mais pas l'image RGB, c'est pas un facteur 3 qu'il risque d'y avoir mais plutôt un facteur 10 ou 20.

  16. #16
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut
    Citation Envoyé par millie Voir le message
    Pour certains types d'opérateurs, il est possible de multithreadé par canaux les opérateurs. (chaque thread s'occupe d'un canal ce qui réduit donc en général bien le temps sur les quad-core)
    OK d'accord...
    Citation Envoyé par millie Voir le message
    Maintenant, il faut voir aussi le type d'opération. Si ça prend 1ms pour du mono canal ou 3ms pour du RGB, c'est pas la fin du monde (sauf si tu fais l'opération 100 fois par seconde). Si c'est 10 sec pour du mono ou du 30 sec pour du RGB, là il faut se poser des questions.
    La, pas d'accord... enfin du moins pour mon application. Je travaille sur du temps reel et donc 1ms et 3 ms pour moi il y a un monde...

    Citation Envoyé par Mongaulois Voir le message
    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    #include <iostream>
    #include <vector>
    #include <list>
    #include <deque>
    #include <set>
    #include <algorithm>
    #include <ctime>
    #include <cmath>
    using namespace std;
    const int num =1000;
    template<typename T>
    struct image
    {
        image(int hh,int ww)
        :h(hh),w(ww),buffer(hh*ww)
        {};
        int h;
        int w;
        vector<T> buffer;
    };
     
    struct pix
    {
        pix():r(0),g(0),b(0)
        {};
     
        pix(char rr,char gg,char bb)
        :r(rr),g(gg),b(bb)
        {}
     
        char r;
        char g;
        char b;
        pix& operator*=(int a)
        {
            r*=a;
            g*=a;
            b*=a;
               return *this;
        }
    };
     
    struct gen
    {
        char operator()()
        {
            return rand()%256+1;
        }
    };
     
    struct genpix
    {
        pix operator()()
        {
            pix p;
            p.r = rand()%256+1;
            p.g = rand()%256+1;
            p.b = rand()%256+1;
            return p;
        }
     
    };
    template <typename T>
    struct multiplie
    {
        multiplie(int aa):a(aa){};
        void operator()(T & pix)
        {
            pix*=a;
     
        }
        int a;
    };
     
     
    struct MIN
    {
        MIN():min(255){};
        void operator()(char pix)
        {
            if (pix<min) min = pix;
        }
        char min;
    };
     
    struct MINPIX
    {
        MINPIX()
        :min(255,255,255)
        {};
        void operator()(const pix & pix)
        {
            if (pix.r<min.r) min.r = pix.r;
            if (pix.g<min.g) min.g = pix.g;
            if (pix.b<min.b) min.b = pix.b;
        }
        pix min;
    };
    int main(int argc, char* argv[])
    {
    srand(clock());
       image<char> img(1000,1000);
       std::generate
           (
               img.buffer.begin(),
               img.buffer.end(),
               gen()
           );
       image<pix>  imgRGB(1000,1000);
        std::generate
           (
               imgRGB.buffer.begin(),
               imgRGB.buffer.end(),
               genpix()
           );
     
     
        while(1)
        {
        clock_t t0 = clock();
     
        for (int i =0;i<num;++i)
        {
            std::for_each
                (
                    img.buffer.begin(),
                    img.buffer.end(),
                    multiplie<char>(2)
                 );
        }
        double tempA = double(clock()-t0)/num;
        std::cout<<"************MULTIPLICATION**************" <<std::endl;
        std::cout<<"grayscale""  "<<tempA <<std::endl;
     
        t0 = clock();
        for (int i =0;i<num;++i)
        {
            std::for_each
                (
                    imgRGB.buffer.begin(),
                    imgRGB.buffer.end(),
                    multiplie<pix>(2)
                 );
        }
        double tempB = double(clock()-t0)/num;
        std::cout<<"rgb"<<"  "<<tempB <<std::endl;
     
        std::cout<<"rgb/grayscale"<<" "<<100*(tempB/tempA)<<"%"<<std::endl;
     
        t0 = clock();
        int min;
        for (int i =0;i<num;++i)
        {
            min = std::for_each
                (
                    img.buffer.begin(),
                    img.buffer.end(),
                    MIN()
                 ).min;
        }
        tempA = double(clock()-t0)/num;
        std::cout<<"************MIN**************" <<std::endl;
        std::cout<<"grayscale""  "<<tempA <<std::endl;
     
        t0 = clock();
        pix minpix;
        for (int i =0;i<num;++i)
        {
           minpix = std::for_each
                (
                    imgRGB.buffer.begin(),
                    imgRGB.buffer.end(),
                    MINPIX()
                 ).min;
        }
        tempB = double(clock()-t0)/num;
        std::cout<<"rgb "<<minpix.r<<"  "<<minpix.g<<"  "<<minpix.b<<"  "<<tempB <<std::endl;
     
        std::cout<<"B/A"<<" "<<100*(tempB/tempA)<<"%"<<std::endl;
        }
     
    	return 0;
    }
    sous visual :
    multiplication : rapport de 211%
    recherche du min : rapport de 450% (ca je m'y attendais pas)

    sous mingw :
    multiplication : identique
    recherche du min : rapport de 339%

    [edit]
    j'ai utilisé des char au lieu des unsigned char mais les résultat sont pareil.
    Merci Mongaulois pour ce bench. Je vais essayer de le tester la semaine prochaine avec mes algos. je vous tiens au courant..

    a tous !!!

  17. #17
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    Citation Envoyé par poukill Voir le message
    La, pas d'accord... enfin du moins pour mon application. Je travaille sur du temps reel et donc 1ms et 3 ms pour moi il y a un monde...
    Le problème pour des temps aussi court, c'est que tu perds bien quelques millisecondes à créer les threads, donc tu ne gagnes pas forcement de temps avec l'histoire des mes threads. Après, c'est quel genre de temps réel ? Est-ce qu'il est possible de mettre en cache des résultats ?
    Je ne répondrai à aucune question technique en privé

  18. #18
    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 : 61
    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
    Points : 50 367
    Points
    50 367
    Par défaut
    Citation Envoyé par millie Voir le message
    Le problème pour des temps aussi court, c'est que tu perds bien quelques millisecondes à créer les threads
    En général, en temps réel, les threads sont créés au début (lors de la phase d'allocation des ressources du programme) et ensuite, ils sont gérés par un pool de threads auquel on demande une tâche.

    Il n'y a plus de création supplémentaire de thread et il n'y a pas non plus de destruction des threads (à part peut être à la fin du programme pour autant qu'il ait une fin).
    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
    .

  19. #19
    Rédacteur

    Avatar de millie
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    7 015
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 7 015
    Points : 9 818
    Points
    9 818
    Par défaut
    Citation Envoyé par ram-0000 Voir le message
    En général, en temps réel, les threads sont créés au début (lors de la phase d'allocation des ressources du programme) et ensuite, ils sont gérés par un pool de threads auquel on demande une tâche.
    Par contre là, je ne sais pas trop le comportement que ça peut avoir car s'il y a trop de thread et qui sont déjà dans un pool (chaque thread est associé à un coeur du processeur une fois pour toute).

    Quand on recréait par exemple 3 threads pour les trois canaux, l'OS va essayer de répartir les threads sur les coeurs les moins occupés ce qui permet d'avoir en général les 3 threads sur des coeurs différents (donc là ça roule).
    Si tous les threads sont crées depuis le début, j'ai l'impression qu'il est plus probable de choisir des threads dans la pool qui sont associé à un même coeur (dans ce cas, il n'y a pas de gain de performance).

    Enfin, je dis ça, mais je ne sais pas trop quel va être le comportement dans un cas comme ça
    Je ne répondrai à aucune question technique en privé

  20. #20
    Membre chevronné
    Avatar de poukill
    Profil pro
    Inscrit en
    Février 2006
    Messages
    2 155
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 2 155
    Points : 2 107
    Points
    2 107
    Par défaut
    Bon je viens de passer deux trois heures à bencher... ET là c'est le drame...
    Autant en char ou unsigned char, le RGB est pas trop pénalisé.
    Autant en float le RGB est méchamment ralenti!!!

    Voici le code de Mongaulois que j'ai templaté pour pouvoir changer plus facilement dans le main le type de données à prendre : float, unsigned char, unsigned short...
    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
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
     
    #include <iostream>
    #include <vector>
    #include <list>
    #include <deque>
    #include <set>
    #include <algorithm>
    #include <ctime>
    #include <cmath>
    #include <limits>
    using namespace std;
    const int num =1000;
     
    template<typename T>
    struct Image
    {
    	typedef T value_type;
     
        Image(int hh,int ww)
        :h(hh),w(ww),buffer(hh*ww)
        {}
        int h;
        int w;
        vector<T> buffer;
    };
     
    template <typename T>
    struct RGB
    {
        RGB():r(0),g(0),b(0)
        {};
     
        RGB(T rr,T gg,T bb)
        :r(rr),g(gg),b(bb)
    	{}
     
        T r;
        T g;
        T b;
     
    	template <typename TYPE>
        RGB& operator*=(TYPE a)
        {
            r*=a;
            g*=a;
            b*=a;
            return *this;
        }
    };
     
    template <typename T>
    struct Gen
    {
    	T operator()()
        {
    		return static_cast<T> ((rand() * 1.0)/RAND_MAX * std::numeric_limits<T>::max() ) ;
        }
    };
     
    template <typename T>
    struct GenRGB
    {
        RGB<T> operator()()
        {
            RGB<T> p;
    		p.r = static_cast<T> ((rand() * 1.0)/RAND_MAX * std::numeric_limits<T>::max() ) ;
            p.g = static_cast<T> ((rand() * 1.0)/RAND_MAX * std::numeric_limits<T>::max() ) ;
    		p.b = static_cast<T> ((rand() * 1.0)/RAND_MAX * std::numeric_limits<T>::max() ) ;
            return p;
        }
     
    };
    template <typename T>
    struct Multiplie
    {
        Multiplie(T aa):a(aa){};
     
    	template <typename TYPE>
        void operator()(TYPE & RGB)
        {
            RGB *= a;
        }
        T a;
    };
     
     
    template <typename T>
    struct MIN
    {
    	typedef T value_type;
     
        MIN():min(255){};
        void operator()(T RGB)
        {
            if (RGB<min) min = RGB;
        }
        T min;
    };
     
    template <typename T>
    struct MINRGB
    {
        MINRGB()
        :min(255,255,255)
        {}
        void operator()(const RGB<T> & RGB)
        {
            if (RGB.r<min.r) min.r = RGB.r;
            if (RGB.g<min.g) min.g = RGB.g;
            if (RGB.b<min.b) min.b = RGB.b;
        }
        RGB<T> min;
    };
     
     
     
     
    int main(int argc, unsigned char* argv[])
    {	
    	typedef unsigned short  TYPE_GRAYSCALE;
    	typedef float			TYPE_RGB;
     
     
    	// GENERATION DES IMAGES ...
    	srand(clock());
    	Image<TYPE_GRAYSCALE> img(200,200);
    	std::generate
    	   (
    		   img.buffer.begin(),
    		   img.buffer.end(),
    		   Gen<TYPE_GRAYSCALE>()
    	   );
    	Image<RGB<TYPE_RGB>>  imgRGB(200,200);
    	std::generate
    	   (
    		   imgRGB.buffer.begin(),
    		   imgRGB.buffer.end(),
    		   GenRGB<TYPE_RGB>()
    	   );
     
    	// FIN GENERATION
     
     
        while(1)
        {
    		clock_t t0 = clock();
     
    		for (int i =0;i<num;++i)
    		{
    			std::for_each
    				(
    					img.buffer.begin(),
    					img.buffer.end(),
    					Multiplie<TYPE_GRAYSCALE>(2)
    				 );
    		}
    		double tempA = double(clock()-t0)/num;
    		std::cout<<"************MULTIPLICATION**************" <<std::endl;
    		std::cout<<"grayscale""  "<<tempA <<std::endl;
     
    		t0 = clock();
    		for (int i =0;i<num;++i)
    		{
    			//std::cout << i << endl;
    			std::for_each
    				(
    					imgRGB.buffer.begin(),
    					imgRGB.buffer.end(),
    					Multiplie<TYPE_RGB>(2)
    				 );
    		}
    		double tempB = double(clock()-t0)/num;
    		std::cout<<"rgb"<<"  "<<tempB <<std::endl;
     
    		std::cout<<"rgb/grayscale"<<" "<<100*(tempB/tempA)<<"%"<<std::endl;
     
    		t0 = clock();
    		int min;
    		for (int i =0;i<num;++i)
    		{
    			min = std::for_each
    				(
    					img.buffer.begin(),
    					img.buffer.end(),
    					MIN<TYPE_GRAYSCALE>()
    				 ).min;
    		}
    		tempA = double(clock()-t0)/num;
    		std::cout<<"************MIN**************" <<std::endl;
    		std::cout<<"grayscale""  "<<tempA <<std::endl;
     
    		t0 = clock();
    		RGB<TYPE_RGB> minRGB;
    		for (int i =0;i<num;++i)
    		{
    		   minRGB = std::for_each
    				(
    					imgRGB.buffer.begin(),
    					imgRGB.buffer.end(),
    					MINRGB<TYPE_RGB>()
    				 ).min;
    		}
    		tempB = double(clock()-t0)/num;
    		std::cout<<"rgb "<<minRGB.r<<"  "<<minRGB.g<<"  "<<minRGB.b<<"  "<<tempB <<std::endl;
     
    		std::cout<<"B/A"<<" "<<100*(tempB/tempA)<<"%"<<std::endl;
        }
     
    	return 0;
    }
    Mais tout de même, pourquoi cette performance nulle en float? Mise en cache pas suffisante???

Discussions similaires

  1. BUFFER D'IMAGE RGB
    Par aziatedu13 dans le forum Traitement d'images
    Réponses: 12
    Dernier message: 27/11/2007, 16h06
  2. Transposée d'une image RGB
    Par silainos dans le forum Images
    Réponses: 4
    Dernier message: 01/10/2007, 03h45
  3. convertir image RGB en HSV
    Par deb_Sous_Python dans le forum Calcul scientifique
    Réponses: 5
    Dernier message: 23/04/2007, 12h25
  4. Réponses: 10
    Dernier message: 18/04/2007, 09h39
  5. Conversion d'une image rgb en hsl
    Par ranell dans le forum Images
    Réponses: 13
    Dernier message: 01/03/2007, 22h03

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