1. #1
    Membre du Club
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    avril 2014
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : avril 2014
    Messages : 41
    Points : 51
    Points
    51

    Par défaut fopen vs open question rapidité

    Bonjour,

    Voila étant en dernière année de master informatique, on nous demande de coder des algorythmes de découverte de réseaux.

    On se sert donc d'un fichier de la forme :
    0 1
    0 2
    1 2
    ...

    Où chaque lignes représente un lien et chaque numéro représente un noeud du réseau.

    Les algos marchent bien pas de souci pour ça le seul souci c'est la rapidité : pour un réseau de 117 millions de liens (donc un fichier avec 117 millions de lignes), l'algo ci-dessous met 5 minutes et 20 secondes rien qu'à rentrer le fichier en mémoire RAM, la où mon prof met lui 26 secondes.

    J'ai un i5 avec 6 GO de RAM, un SSD et les 4 coeurs montent tous à 50% de charge quand l'algo ci-dessous tourne.La lecture disque semblerait se faire à 2 Mio/s.

    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
     
    void printSize(char* input){
    	FILE* f;
    	char c;
    	unsigned long n1,n2,nbVertices=0,nbEdges=0;
     
    	if((f = fopen(input,"r"))==NULL){
            	perror("File not found");
           	 exit(1);
        	}
     
    	while((c=fgetc(f))!=EOF){			//case where first two lines begin with %
    		if(c=='%')
    			while((c=fgetc(f))!='\n');
    		else
    			break;
    	}
    	fseek(f,-1,SEEK_CUR);				//one char has been read, got to go back
     
    	while(fscanf(f,"%ld %ld",&n1,&n2)!=EOF){
    		nbVertices = max(nbVertices,n1,n2);
    		nbEdges++;
    	}
     
    	nbVertices++;					//adding vertice 0
     
    	printf("\n%ld vertices %ld edges",nbVertices, nbEdges);
    }
    Voila ma question est donc :

    Remplacer fopen() par open() va-t il améliorer la rapidité ?

    Ou sinon si vous avez d'autres idées pour améliorer la rapidité de mise en mémoire principale...

    D'autres fonctions que open?()
    Création de threads ou processus pour essayer d'aller plus vite?
    gcc -09 change t-il quelque chose à la done?
    ...

    Merci beaucoup

  2. #2
    Membre du Club
    Homme Profil pro
    Technicien maintenance
    Inscrit en
    avril 2014
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Technicien maintenance
    Secteur : Industrie

    Informations forums :
    Inscription : avril 2014
    Messages : 41
    Points : 51
    Points
    51

    Par défaut

    Problème résolu.

    -O9 dans gcc et je met 20 secondes à lire le fichier de 117 millions de lignes.

    L'emploi de printf() semble vraiment très gourmand si j'en met un, je passe à plus d'une minute.

    Merci.

  3. #3
    Membre expert
    Inscrit en
    mars 2005
    Messages
    1 082
    Détails du profil
    Informations forums :
    Inscription : mars 2005
    Messages : 1 082
    Points : 3 165
    Points
    3 165

    Par défaut

    Tu peux probablement aller encore plus vite en :

    • chargeant tout le fichier en mémoire système (lecture d'une traite dans un gros buffer, sans analyse) ;
    • réalisant l'analyse de chaîne depuis la mémoire.


    Et si tu veux vraiment être à la pointe, tu confies l'opération d'entrée / sortie à libuv et tu réalises l'analyse dans la callback.

    Pour répondre à ta question initiale, il ne faut attendre aucune différence de performance entre fopen et open : la seconde est probablement wrappée par la première.


    Citation Envoyé par tabouret Voir le message
    L'emploi de printf() semble vraiment très gourmand si j'en met un, je passe à plus d'une minute.
    Oui, ça c'est sûr.. particulièrement si un flush a lieu (dû à la présence d'un '\n' dans la chaîne à imprimer).

  4. #4
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    février 2006
    Messages
    5 898
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    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 : 5 898
    Points : 16 287
    Points
    16 287
    Billets dans le blog
    1

    Par défaut

    Citation Envoyé par tabouret Voir le message
    Remplacer fopen() par open() va-t il améliorer la rapidité ?
    Bonjour
    Pas pour des lectures de lignes. J'ai réussi à aller plus vite avec open() mais je lisais des fichiers binaires et je jouais sur la quantité lue dans read.

    Citation Envoyé par tabouret Voir le message
    Ou sinon si vous avez d'autres idées pour améliorer la rapidité de mise en mémoire principale...
    Remplacer tes fgetc() par des fgets() (puisque tu dis lire des "lignes" c'est le plus approprié). Et bien entendu éliminer tes fseek() inutiles et tes printf()...
    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

  5. #5
    Membre expert
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    décembre 2015
    Messages
    597
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    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 : 597
    Points : 3 051
    Points
    3 051

    Par défaut

    Bonjour,

    La différence entre open() et fopen() est que le second est bufferisé. C'est pourquoi on utilise systématiquement open() pour accéder à un driver qui n'est pas un block-driver. Si on lit des blocs plus grands que la taille du buffer, les fread() de fopen() seront plus lents (car tout transite par le buffer). Si inversement on lit des données de petite taille, le système de cache de fopen() optimisera se seront les read() de open() qui seront plus lents.
    Le buffer de fopen() fait normalement 4K donc :
    * des blocs de moins de 1K sont normalement plus rapides avec fopen()
    * des blocs de plus de 4K sont plus rapides avec open() (si très grands on peut avoir un gain du simple au double)
    * des blocs de 1K à 4K, les deux sont équivalents.

  6. #6
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    septembre 2005
    Messages
    26 525
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France

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

    Informations forums :
    Inscription : septembre 2005
    Messages : 26 525
    Points : 38 366
    Points
    38 366

    Par défaut

    Si tu lis byte par byte comme dans le code actuel, alors il n'y a pas photo, fopen() + [f]getc() sera beaucoup plus rapide que open() + read(1).
    Mais si tu optimises plus la lecture, y compris — si le fichier est garanti tenir en mémoire — obtenir la taille du fichier puis le lire d'un bloc*... faut voir. S'il y a des copies de buffer lors de l'appel unique à fread() il y aura un overhead tangible par rapport à un read() nu, sinon il sera négligeable.

    *ce qui nécessite de l'ouvrir en mode binaire, pour être conforme à la norme
    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.

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

Discussions similaires

  1. fopen et open;fichiers bufférisés.
    Par yessine66 dans le forum Débuter
    Réponses: 7
    Dernier message: 11/11/2010, 13h08
  2. [OpenAL] Questions cons
    Par Harooold dans le forum OpenAL
    Réponses: 0
    Dernier message: 04/03/2009, 19h26
  3. Question de rapidité
    Par charlito dans le forum 2D
    Réponses: 4
    Dernier message: 14/03/2006, 15h09
  4. QUESTION RAPIDITE dans BASES TRES VOLUMINEUSES
    Par ias83 dans le forum Débuter
    Réponses: 3
    Dernier message: 17/08/2005, 10h07
  5. Différence open et fopen
    Par SteelBox dans le forum C
    Réponses: 6
    Dernier message: 01/07/2003, 22h32

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