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 accès fichier (ifstream)


Sujet :

C++

  1. #1
    Membre du Club
    Inscrit en
    Mars 2007
    Messages
    127
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 127
    Points : 54
    Points
    54
    Par défaut Optimisation accès fichier (ifstream)
    Bonjour,

    j'ai développé une classe qui contient plusieurs fonctions qui vont lire des fichiers à un index particulier et en déduisent une valeur. Un exemple très simplifié :

    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
     
    #define SIZE_OF_DOUBLE (sizeof(double))
     
    class module {
     
       private:
           std::ifstream file;
     
       public:
           module() {
               file.open("path.bin, ios::in | ios::binary");
           }
     
           getValue(const double x, const double y) {
               double value[4][4];
               unsigned int index = calcul(x, y); // Transformation des paramètres d'entrée en index
               file.seekg(index*SIZE_OF_DOUBLE, ios::beg);
               file.read(reinterpret_cast<char *> (&value[0]), 4*SIZE_DOUBLE);
               file.seekg(ligne_suivante*SIZE_OF_DOUBLE, ios::cur);
               file.read(reinterpret_cast<char *> (&value[1]), 4*SIZE_DOUBLE);
               file.seekg(ligne_suivante*SIZE_OF_DOUBLE, ios::cur);
               file.read(reinterpret_cast<char *> (&value[2]), 4*SIZE_DOUBLE);
               file.seekg(ligne_suivante*SIZE_OF_DOUBLE, ios::cur);
               file.read(reinterpret_cast<char *> (&value[3]), 4*SIZE_DOUBLE);
               return bicubicInterpo(x, y, values);
         }
    }
    Ceci n'est qu'un exemple. J'ai une 20aine de fonctions similaires à getValue() et à peu près le même nombre d'ifstream qui pointent sur des fichiers qui font entre 5 et 10Mo (soit un total d'environ 150Mo).

    Auriez-vous un conseil pour d'une part l'optimiser car j'appelle plusieurs centaines de millions de fois chaque fonction et d'autre part, si je devais passer au multi-thread, que puis-je faire pour le rendre thread-safe car quand j'essaye de paralléliser avec openmp, j'ai un segfault (j'imagine que ce cela vient de l'accès au ifstream).

    Merci d'avance !

  2. #2
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    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 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Si tu veux être vraiment efficace, utilise un cache.
    C'est à dire mets en mémoire soit la totalité du fichier, soit des parties de ceux-ci (un système de pages, donc)
    mmap peut te donner une idée

    Dans l'idée, ton fichier ayant une forme particulière, tu dois pouvoir le représenter comme un vector<Forme>, Forme étant l'aspect d'un élément.

    150Mo, c'est assez petit pour la RAM (en Go pour un PC, et "beaucoup" pour un serveur)
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  3. #3
    Membre du Club
    Inscrit en
    Mars 2007
    Messages
    127
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 127
    Points : 54
    Points
    54
    Par défaut
    Merci Leternel pour cette réponse. En cherchant quelques infos sur google, je tombe sur mmap sous linux. Mon environnement est windows.

    Est-ce que mmap existe ou a un équivalent pour windows ?

  4. #4
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    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 189
    Points : 17 141
    Points
    17 141
    Par défaut
    "google mmap windows" m'a donné file mapping

    Mais tu n'en as pas forcément.
    Commence déjà par définir une struct/class, et fais en un vector.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  5. #5
    Membre du Club
    Inscrit en
    Mars 2007
    Messages
    127
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 127
    Points : 54
    Points
    54
    Par défaut
    Mon fichier, au départ, est une matrice indicée par une longitude terrestre [-180 à 180] et une latitude terrestre [-90 à 90] avec un pas fixe pour un fichier donné. Chaque valeur est un double. Ensuite, le tout est stocké en fichier binaire.

    L'intérêt de la fonction est d'aller lire les valeurs pour 4 longitudes consécutives et ceci sur 4 lignes consécutives (soit 16 points en carré de 4 par 4). Autrement dit, les 16 points autour de x et y dans ma fonction.

    Du coup, que veut dire vector<Forme> :
    * est-ce que "forme" serait une ligne donc plusieurs centaines de doubles ?
    * est-ce que "forme" serait un double ? Dans ce cas, quel est l'intérêt par rapport à ce que j'avais initialement ? Le vecteur serait stocké en mémoire ?

    J'ai aussi regardé un mmap ou équivalent. Je suis tombé sur la fonction map() de QFile. Maintenant, je ne me retrouve avec un 'uchar *' et je n'arrive pas à trouver d'exemple pour convertir cela en double et aller chercher la bonne valeur...

  6. #6
    Expert confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2012
    Messages
    1 711
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2012
    Messages : 1 711
    Points : 4 442
    Points
    4 442
    Par défaut
    Hello,

    Forme ici peut être une matrice (16 doubles).
    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
    #define SIZE_OF_DOUBLE (sizeof(double))
     
    class module {
    private:
    	struct Data {
    		double values[4][4];
    	};
     
    	std::unordered_map<unsigned int, Data> cache;
     
    public:
    	module() {
    		std::ifstream file("path.bin, ios::in | ios::binary");
    		pour tous les indices {
    			// lire tes 16 doubles
    			unsigned index = calcul(x, y);
    			Data d;
    			file.seekg(index*SIZE_OF_DOUBLE, ios::beg);
    			file.read(reinterpret_cast<char *> (&d.value[0]), 4*SIZE_DOUBLE);
    			file.seekg(ligne_suivante*SIZE_OF_DOUBLE, ios::cur);
    			file.read(reinterpret_cast<char *> (&d.value[1]), 4*SIZE_DOUBLE);
    			file.seekg(ligne_suivante*SIZE_OF_DOUBLE, ios::cur);
    			file.read(reinterpret_cast<char *> (&d.value[2]), 4*SIZE_DOUBLE);
    			file.seekg(ligne_suivante*SIZE_OF_DOUBLE, ios::cur);
    			file.read(reinterpret_cast<char *> (&d.value[3]), 4*SIZE_DOUBLE);
    			cache.insert(index, d);
    		}
    	}
     
    	double getValue(const double x, const double y) const {
    		unsigned int index = calcul(x, y);
    		auto const& d = cache[index];
     
    		// si ce calcul est long et fait plusieurs
    		// fois, il peut aussi est mis en cache
    		return bicubicInterpo(x, y, d.values);
    	}
    };

  7. #7
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    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 189
    Points : 17 141
    Points
    17 141
    Par défaut
    comme le dit iradrille, ton fichier contient une matrice de coordonnées.
    Il te faudrait deux types: coordonnées et matrice.
    Avec les fonctions de lectures associées.

    Une fois cela fait, tu pourras écrire assez facilement une map (ou autre type te plaisant) associant un point à ses voisins, ou un vecteur à parcourir directement par l'indice que calcule ta fonction indice.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  8. #8
    Membre du Club
    Inscrit en
    Mars 2007
    Messages
    127
    Détails du profil
    Informations forums :
    Inscription : Mars 2007
    Messages : 127
    Points : 54
    Points
    54
    Par défaut
    Merci Iradrille et leternel, je comprends bien l'approche ! Je m'y mets :-)

  9. #9
    Expert éminent sénior
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 074
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 074
    Points : 12 120
    Points
    12 120
    Par défaut
    Pour une optimisation plus fine, pour de très gros fichiers, le flag "FILE_FLAG_RANDOM_ACCESS" de CreateFile peut peut-être aider :

    https://msdn.microsoft.com/en-us/lib...or=-2147217396

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

Discussions similaires

  1. Optimisation de dossiers / accès fichiers
    Par Népomucène dans le forum Windows Serveur
    Réponses: 0
    Dernier message: 11/01/2010, 15h12
  2. [C#] Accès fichiers Internet
    Par joujou_le_fou dans le forum Windows Forms
    Réponses: 5
    Dernier message: 04/08/2004, 12h49
  3. [tomcat]acces fichier dans contexte
    Par krollette dans le forum Tomcat et TomEE
    Réponses: 2
    Dernier message: 23/01/2004, 14h17
  4. pb service NT / accès fichier
    Par gord's dans le forum API, COM et SDKs
    Réponses: 3
    Dernier message: 24/07/2003, 17h20
  5. [Kylix] accés fichiers
    Par sdoura dans le forum EDI
    Réponses: 4
    Dernier message: 08/10/2002, 19h33

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