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 :

Programme "lent" en c(lecture image)


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    211
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Avril 2007
    Messages : 211
    Par défaut Programme "lent" en c(lecture image)
    Bonjour,

    J'ai un petit programme qui lit un fichier image PGM de 720 x 560 que je met dans un tableau de 9 x 8.
    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    #include <stdio.h>
    #include <stdlib.h>
     
    int main(int argc, char *argv[])
    {
        FILE* fichier = NULL;
        int tableau9x8[9][8];
        int i = 0;
        int j = 0;
        int k = 0;
        int l = 0;
     
        fichier = fopen("1.pgm", "r");//ouverture du fichier
        fseek(fichier, 15, SEEK_SET); // placement du curseur après l'entête du fichier PGM
     
        if (fichier != NULL)
        {
          //remplir le PGM dans un tableau
           for (j = 0; j < 560 ; j++)
           {
               for (i = 0; i < 720 ; i++)
               {
                k=i/80;
                l=j/70;
                  tableau9x8[k][l]=tableau9x8[k][l]+ fgetc(fichier);
     
               }
           }
          // fermeture du fichier
            fclose(fichier);
     
        }
     
        return 0;
    }
    Or je trouve le programme assez lent. Est-ce du fait que je lise les caractère 1 par 1 (fgetc)?
    Voyez vous un moyen d'accélérer la manœuvre ?

    Merci

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    As-tu activé les optimisations sur ton compilateur?
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Expert confirmé
    Avatar de Kannagi
    Homme Profil pro
    cyber-paléontologue
    Inscrit en
    Mai 2010
    Messages
    3 226
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cyber-paléontologue

    Informations forums :
    Inscription : Mai 2010
    Messages : 3 226
    Par défaut
    optimisation ou pas du compilateur , la lecture du disque dur est très très lente.
    Tu peux augmenter un peu la lecture en faisant une lecture avec fread et donc de faire ta boucle sur le buffer de ton image.

  4. #4
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Mais de mémoire, fgetc() est déjà bufferisée.
    Personnellement je commencerais par sortir le calcul de l de la boucle intérieure, mais n'importe quel optimiseur doit déjà en être capable, pour peu qu'il soit activé.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Ton tableau n'est pas initialisé, tu vas avoir des résultats différents à chaque appel.
    Ensuite, qu'entends-tu par lent ? La lecture depuis disque est lente, la seule façon de l'améliorer est de posséder un SSD.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  6. #6
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Le résultat obtenu n'est qu'un tableau aléatoire car non initialisé.
    Avant d'optimiser, il est préférable de faire quelque chose qui ait un sens.
    Tel que tu le lis, le fichier serait un fichier texte d'au moins 430215 caractères est-ce bien le cas? Lire au delà de la taille max d'un fichier peut peut-être ajouter les longueurs, mais version debug ou optimisé, ça ne devrait être sous la milliseconde.
    Qu'entends-tu par lent ?

  7. #7
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 832
    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 832
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par Médinoc Voir le message
    Mais de mémoire, fgetc() est déjà bufferisée.
    C'est vrai que la lecture disque est toujours bufferisée. Mais même bufferisée, lire n fois 1 caractère sera toujours plus lent que lire 1 fois n caractères. Dans le premier cas, il y a n fois appel de fonction avec n fois tout ce qui va avec et ça, même si c'est invisible et transparent, ce n'est pas gratuit.
    De fait j'avais fait il y a quelques années des tests benchmark de ce type et globalement les fonctions style fgets ou fread donnaient de meilleurs résultats que fgetc. Bien sûr il y a aussi des effets liés à la taille de la zone lue qui peuvent parfois être contre intuitifs (par exemple ce n'est pas parce qu'on multiplie la taille de la zone à lire par 10 que ça va améliorer les performances x10 et parfois ça peut même les baisser) mais malgré tout ça reste préférable.

    Citation Envoyé par Médinoc Voir le message
    Personnellement je commencerais par sortir le calcul de l de la boucle intérieure, mais n'importe quel optimiseur doit déjà en être capable, pour peu qu'il soit activé.
    Personnellement je pense qu'aucun optimiseur ne peut remplacer la réflexion et l'analyse personnelle. Il vaut mieux d'abord réfléchir et (comme tu le dis) sortir les traitements lourds des boucles si le fait de calculer dans la boucle n'apporte rien au résultat.
    Une fois ce travail fait, si ensuite l'optimiseur peut faire des trucs en plus c'est cadeau.
    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]

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    118
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 118
    Par défaut
    Les buffers utilisé par les fichiers sont contrôlé (activation, taille) par les commandes setbuf() / setvbuf().

    Après, si la mémoire n'est pas un problème dans le programme, moi je lirais tous le fichier d'un seul coup dans un buffer temporaire et je travaillerait directement dessus. En plus de supprimer le morcellement des accès disque, ça éviterait également les quelques 720 x 560 appels/retour de fonctions de lecture (avec gestion de contexte, etc...).
    Et puis, suivant l'algorithme qu'on va écrire derrière, ça faciliterait les accès non séquentielle à ces données (vs les multiples "seek()", si on voulait faire la même chose directement sur le fichier).

    Par ailleur, il n'y a pas que le "l=j/70;" qui est redondant. On se rend bien compte que le "k=i/80;" aussi, aboutit 80% du temps au même résultat. Et celui-là, je suis pas certain que les optimiseurs savent en faire quelque chose.
    Or, parmi les opérateurs de bases sur les entiers, la division est de très loin la plus coûteuse. Ca va dépendre des architectures, et je ne suis pas sûr de ce qu'il en est sur x86, mais '+', '-', '*' se règles généralement en un seul cycle d'horloge, tandis que la division peut en demander une bonne vingtaine ou quarantaine, suivant la plateforme.


    Bon bien-sûr, sur PC, on n'a généralement pas besoin de se préoccuper de ce genre de détails et il est préférable de privilégier d'autres considération (réutilisation du code, lisibilité, maintenance, ...). Mais si un goulot d'étranglement critique a réellement été identifié, et en restant sur des boucles for, moi j'aurai proposé quelque chose comme ça:

    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
    char buf[720*560];
    int tableau9x8[9][8] = {{0}};
     
     
    size_t ret = fread(buf, 1, 720*560, fichier);
     
    if( ret == (720*560) ){
        char *bufPtr = buf;
        for(int row=0; row!=8; row++){
            for(int r=70; r!=0; r--){
                for(int col=0; col!=9; col++){
                    for(int c=80; c!=0; c--){
                        tableau9x8[col][row] += *bufPtr++;
                    }
                }
            }
        }
    }

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

Discussions similaires

  1. Programmation sur PDA: pb d'affichage d'image
    Par Arthur16s dans le forum AWT/Swing
    Réponses: 7
    Dernier message: 04/06/2007, 17h08
  2. programme pour réduire la résolution d'une image
    Par khokho dans le forum Multimédia
    Réponses: 6
    Dernier message: 16/11/2006, 19h44

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