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 :

Optimisation d'un code (lecture intensive de fichier binaire)


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre à l'essai
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Septembre 2014
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Septembre 2014
    Messages : 5
    Par défaut Optimisation d'un code (lecture intensive de fichier binaire)
    Bonjour,

    J’aimerais avoir votre avis pour optimiser le temps de calcul d’un code.

    Pour résumer grossièrement mon code :
    • J’ai une classe qui contient une méthode de calcul

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Class object {
    public:
        object(QString objectName = "Not set");
        double computeValue(const double param1, const double param2) {return lectureFichier(param1, param2);}
    }
    • Mon main

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    for(unsigned long long i=0 ; i<NOMBRE ; i++)
    	object->computeValue(valeur1, valeur2);
    avec NOMBRE qui peut être très très élevé (typiquement plusieurs millions) et valeur1 et valeur2 issus d’un calcul non « prévisible » (combinaison d’aléas).

    • Une bibliothèque de fonctions :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    // Le .h
    #ifndef BIBLIFUNCTIONS_H
    #define BIBLIFUNCTIONS _H
    #include <iostream>
    #include <fstream>
     
    double lectureFichier(const double param1, const double param2);
     
    #endif
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    // Le .cpp
    #include "bibliFunctions.h"
     
        double lectureFichier(const double param1, const double param2) {
            ifstream file(PATH_FILE, ios::in | ios::binary);
    	Index = FUNCTION(param1, param2);
            file.seekg(index*SIZE_OF_DOUBLE);
            file.read(reinterpret_cast<char *>(&values), 4*SIZE_OF_DOUBLE);
            file.close();
     
    	return FONCTION(values) ; // Calcule 1 valeur en utilisant les 4 valeurs lues dans le fichier
    }
    Le fichier est une série de 260000 doubles (implicitement organisés en un tableau de 720 par 360). C’est un binaire de 2Mo. Ces fonctions se trouvent dans une bibliothèque à part car elles sont appelées à plusieurs endroits. Je précise également que je ne fais que lire le fichier (je ne fais jamais d’écriture).

    Mon problème est que j’ouvre et ferme de très nombreuses fois le ficher, ce qui me pénalise en temps de calcul.

    J’ai d’abord pensé à faire ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    // Le .h
    #ifndef BIBLIFUNCTIONS_H
    #define BIBLIFUNCTIONS _H
    #include <iostream>
    #include <fstream>
     
    static std::ifstream file(PATH_FILE, std::ios::in | std::ios::binary);
     
    double lectureFichier(const double param1, const double param2);
     
    #endif
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    // Le .cpp
    #include "bibliFunctions.h"
     
        double lectureFichier(const double param1, const double param2) {
    	Index = FUNCTION(param1, param2);
            file.seekg(index*SIZE_OF_DOUBLE, ios::beg);
            file.read(reinterpret_cast<char *>(&values), SIZE_OF_DOUBLE);
    	return value ;
    }
    C’est bien plus rapide (je n’ouvre le fichier plus qu’une fois) mais je ne sais pas comment faire pour appeler le file.close().

    Je pensais aussi stocker le fichier (2Mo) en mémoire pour y accéder encore plus vite (pour éviter de lire sur le disque dur). Cependant, je ne sais pas trop sous quel format/quelles méthodes je dois utiliser car c’est un fichier binaire :
    • un istream avec les fonctions seekg et read ?
    • un stringsteam (mais il faut convertir les string en double, c’est peut-être pas le plus rapide) ?
    • autre format plus performant que je ne connais pas ?

    Donc j’aimerais un petit conseil pour optimiser au mieux ce code. Merci d’avance !

  2. #2
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    C'est le moment de faire intervenir une classe RAII, voire de se souvenir que fstream en est une.

    imagine une classe DataHolder ainsi faite:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class DataHolder {
    private:
    	ifstream & stream;
    public:
    	DataHolder(ifstream& source) : stream(source) {}
     
    	double computeValue(const double param1, const double param2) {
    		Index = FUNCTION(param1, param2);
    	        file.seekg(index*SIZE_OF_DOUBLE);
            	file.read(reinterpret_cast<char *>(&values), 4*SIZE_OF_DOUBLE);
    		return FONCTION(values)
    	}
    };
    Du coup, le main crée le stream, le donne à un DataHolder, et boucle sur celui-ci.
    En étant plus attentionné, je m'aperçois que Object pourrait fort bien contenir ce stream, ou en avoir une référence.


    Autre solution, changer la fonction pour lui donner la référence au stream.
    le main deviendrai:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ifstream & file(...);
    for(unsigned long long i=0 ; i<NOMBRE ; i++)
    	object->computeValue(file, valeur1, valeur2);
    PS: j'espère que le nom Object est seulement pour l'exemple, et que ton code n'est pas basé sur un GodObject

  3. #3
    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
    Pourquoi tu rajouterais pas juste le fichier en question en paramètre de la méthode de lecture ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    // ouvrir fichier
    // deadly loop
    {// calcul}
    // fermer fichier
    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.

  4. #4
    Membre à l'essai
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Septembre 2014
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Septembre 2014
    Messages : 5
    Par défaut
    Bonjour, merci pour vos réponses.

    Leternel, j'ai plusieurs questions :

    Dans la solution 1:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    class DataHolder {
    private:
    	ifstream & stream;
    public:
    	DataHolder(ifstream& source) : stream(source) {}
     
    	double computeValue(const double param1, const double param2) {
    		Index = FUNCTION(param1, param2);
    	        file.seekg(index*SIZE_OF_DOUBLE);
            	file.read(reinterpret_cast<char *>(&values), 4*SIZE_OF_DOUBLE);
    		return FONCTION(values)
    	}
    };
    Est-ce que ce ne devrait pas être stream.seekg() et stream.read() au lieu de file.seekg() et file.read() ?

    J'ai cru comprendre que ifstream crée un "pointer" vers le fichier ? Est-ce que je dois comprendre de tes propositions que créer un ifstream est aussi efficace que de stocker le fichier en mémoire ?

    Pour la solution 2, j'aurai au final une trentaine de fichiers qui seront tous utilisés par toutes mes classes donc la solution 1 me semble plus adaptée.

    Oui, "object" est un nom que j'ai donné pour l'exemple.


    Bousk,

    ton approche me demande de réorganiser pas mal de choses dans ce programme.

  5. #5
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Effectivement, c'est un copié collé malencontreux.
    fstream est un peu mieux qu'un fichier, mais gère ça proprement.

    créer un ifstream, c'est exactement ce que tu faisais.
    Ma solution permet de garder cette variable le temps nécessaire.

    La solution de Boosk revient sensiblement au même, sauf qu'il se passe de créer un Bidule™ pour garder la variable.
    C'est encore meilleur.

  6. #6
    Membre à l'essai
    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Septembre 2014
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Eure (Haute Normandie)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Septembre 2014
    Messages : 5
    Par défaut
    Ok. Merci pour toutes ces réponses !

  7. #7
    Membre chevronné
    Profil pro
    Consultant en technologies
    Inscrit en
    Octobre 2013
    Messages
    158
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Consultant en technologies

    Informations forums :
    Inscription : Octobre 2013
    Messages : 158
    Par défaut
    Un fichier de 2MB sur une machine ordinaire avec des Gigas de RAM, ca vaut le coup de le stocker en RAM

    - Soit tu écrit un parser pour ton fichier binaire qui te le ré-écrit comme une suite d'objets/structures, c'est un peu de travail, mais ca te permet d'avoir quelques-chose bien propre

    - Soit tu sais exactement où tu dois tapper dans le fichier, tu n'as pas peur de compter les bits (ce que tu fais déjà à coup de seek) bref que tu es un bad boy of programming dans ce cas là tu te contente de mettre ton fichier dans un vector<char> (en fait un vectorr<int8_t> histoire d'être sur de la taille) voire (because STL containers are for pussies :p ) un tableau dynamque à l'ancienne (a tes risques et périls)

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

Discussions similaires

  1. Réponses: 1
    Dernier message: 21/12/2006, 13h06
  2. lecture d'un fichier binaire
    Par booby dans le forum C
    Réponses: 17
    Dernier message: 20/09/2006, 16h11
  3. lecture d'un fichier binaire
    Par Tonta dans le forum C++
    Réponses: 1
    Dernier message: 14/04/2006, 06h53
  4. lecture d'un fichier binaire en VB
    Par olivier] dans le forum VB 6 et antérieur
    Réponses: 7
    Dernier message: 28/12/2005, 11h17
  5. Lecture d'un fichier binaire
    Par Gloubie dans le forum Langage
    Réponses: 9
    Dernier message: 05/12/2005, 12h51

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