|
|
|
|
||||||
![]() |
|
|
LinkBack | Outils de la discussion |
|
|
#1 |
|
Messages: n/a
Hébergeur: |
Bonjour,
j'ai un fichier du style : label 2.3 4.5 5.6 label2 1.2 1.0 -2. .... qui est assez gros (près d'1 Go). J'avais un programme C à base de fscanf. En passant de C (à base de fscanf) à c++ avec ifstream (voir le code en bas), je passe de 1min 40s en C à 3min 10s en c++. Je trouve que ca fait un gap quand même. Comme je n'ai pas trop d'expérience sur les fichiers en c++, je m'en remets à vous. Vous pouvez me dire si vous voyez des choses à améliorer pour avoir de meilleures performances (plus proches du C)? Je joins un bout de code avec uniquement la lecture du fichier et l'extraction des données. Le code C fait la même chose mais avec fscanf et feof. Je peux le donner si ca peut aider. #include <iostream> #include <fstream> using namespace std; int main(int argc, char ** argv) { ifstream ifs("fichier.toto"); float x,y,z; string lc; int count =0; int i; while (! ifs.eof()) { ifs >> lc>>x>>y>>z; if (!ifs.eof()) { count ++; } } cout <<"count = "<<count<<endl; return 0; } Merci d'avance. Ploc. |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
Ploc wrote:
> Bonjour, > > j'ai un fichier du style : > > label 2.3 4.5 5.6 > label2 1.2 1.0 -2. > ... > > > qui est assez gros (près d'1 Go). > > J'avais un programme C à base de fscanf. > En passant de C (à base de fscanf) à c++ avec ifstream (voir le code en > bas), je passe de 1min 40s en C à 3min 10s en c++. > > Je trouve que ca fait un gap quand même. > Comme je n'ai pas trop d'expérience sur les fichiers en c++, je m'en > remets à vous. > > Vous pouvez me dire si vous voyez des choses à améliorer pour avoir de > meilleures performances (plus proches du C)? > > Je joins un bout de code avec uniquement la lecture du fichier et > l'extraction des données. > Le code C fait la même chose mais avec fscanf et feof. Je peux le donner > si ca peut aider. > > > #include <iostream> > #include <fstream> > > using namespace std; > > int main(int argc, char ** argv) > { > ifstream ifs("fichier.toto"); > > float x,y,z; > string lc; > > int count =0; > int i; > while (! ifs.eof()) > { > ifs >> lc>>x>>y>>z; > if (!ifs.eof()) > { > count ++; > } > } > cout <<"count = "<<count<<endl; > > return 0; > } > > > Merci d'avance. > > Ploc. Précision importante - même machine, même charge - gcc et g++ v4.1.2 - mêmes options d'optimisation -O2 (même si ca ne semble pas beaucoup jouer ici). |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
On Sat, 03 May 2008 21:46:32 +0200, Ploc <ploc@clop.invalid>:
>Le code C fait la même chose mais avec fscanf et feof. Je peux le donner >si ca peut aider. Ce serait probablement une bonne idée, histoire d'avoir une référence pour la performance. |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
On Sat, 03 May 2008 21:46:32 +0200, Ploc <ploc@clop.invalid>:
>En passant de C (à base de fscanf) à c++ avec ifstream (voir le code en >bas), je passe de 1min 40s en C à 3min 10s en c++. As-tu fait les mesures avec time (et, accessoirement, un top dans une autre console) ? 10 Mo/s, ce n'est pas très loin de la vitesse effective de lecture d'un fichier sur disque ; time (la fonction de bash, pas celle de C ou C++) permet de savoir combien de temps le processeur met effectivement pour décoder le fichier. Tu t'apercevras peut-être que le programme en C++ est encore plus mauvais que tu le croyais. > while (! ifs.eof()) > { > ifs >> lc>>x>>y>>z; > if (!ifs.eof()) > { > count ++; > } > } Le code ci-dessus me paraît louche. D'une part, tu ne devrais pas être obligé d'appeler eof() deux fois dans la boucle. D'autre part, tu n'as aucun contrôle d'erreur. Si tu as l'assurance absolue que le fichier est écrit dans un format précis, et qu'aucune erreur ne peut s'y glisser (ou que, en cas d'erreur, un plantage ou un comportement erratique sont acceptables), tu peux certes zapper certains tests, mais il faut le dire explicitement. En particulier, l'assurance absolue que la longueur de chaque ligne est inférieure à une valeur fixée à l'avance, est indispensable pour lire une chaîne de caractères avec fscanf (ou scanf). Sinon, il faut utiliser fgets + sscanf. Si tu n'as pas besoin de la portabilité (ou si tu peux te permettre de faire une version spéciale pour Windows), mmap() peut s'avérer une piste à creuser pour améliorer les performances tout en réduisant les problèmes. Bien que j'utilise << avec plaisir, l'opérateur >> m'a toujours laissé dubitatif. Du coup, généralement, je lis un fichier ligne par ligne (avec std::getline()), puis j'analyse chaque ligne moi-même (y compris, dans certains cas, avec sscanf). Mais je m'intéresse plus au contrôle d'erreur qu'aux performances. |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
Fabien LE LEZ wrote on 03/05/2008 22:37:
> On Sat, 03 May 2008 21:46:32 +0200, Ploc <ploc@clop.invalid>: > >> En passant de C (à base de fscanf) à c++ avec ifstream (voir le code en >> bas), je passe de 1min 40s en C à 3min 10s en c++. > > As-tu fait les mesures avec time (et, accessoirement, un top dans une > autre console) ? 10 Mo/s, ce n'est pas très loin de la vitesse > effective de lecture d'un fichier sur disque pas vraiment, avec fread et un buffer de 64Ko, je lis 180Mo en 3 sec.! (à la première lecture d'un fichier non caché - les lectures suivantes prennent 172 ms), écart mesuré avec _ftime sur un binaire (fopen("rb")) le "temps de lecture effectif" a tout chance d'être négligeable par rapport au traitement de texte (scanf ou istream) qui est le problème ici. > [...] puis j'analyse chaque ligne moi-même (y compris, dans > certains cas, avec sscanf). Mais je m'intéresse plus au > contrôle d'erreur qu'aux performances. et tu as p.e. les 2. Sylvain. |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
On 3 mai, 21:46, Ploc <p...@clop.invalid> wrote:
> while (! ifs.eof()) une lecture ne se fait pas sur std::ios::eof() je verrais plutot la lecture comme ca (non testé) while(( ifs >> x >> y >> z )) {} cf FAQ C++ de developpez |
|
|
|
#7 |
|
Messages: n/a
Hébergeur: |
On Sun, 04 May 2008 00:17:55 +0200, "Sylvain SF" :
>pas vraiment, avec fread et un buffer de 64Ko, je lis 180Mo en 3 sec.! Ça m'étonnerait beaucoup que tu aies une telle vitesse sur toute la surface du disque. |
|
|
|
#8 |
|
Messages: n/a
Hébergeur: |
Fabien LE LEZ wrote on 04/05/2008 01:05:
> On Sun, 04 May 2008 00:17:55 +0200, "Sylvain SF" : > >> pas vraiment, avec fread et un buffer de 64Ko, je lis 180Mo en 3 sec.! > > Ça m'étonnerait beaucoup que tu aies une telle vitesse sur toute la > surface du disque. pour être honnête j'étais sous les 3 sec. (2.6); je ne pense pas qu'un fichier à la périphérie prendra 10 fois le temps d'un fichier près du centre - ce faisant je n'imagine pas que l'on parle d'un disk de +5 ans d'age. je répète le point qui me semble "time consuming" et qui donc devrait être imho le point d'intérêt : la conversion texte en float. la lecture binaire est rapide - ok sauf en PATA de base avec un disk poussif. Sylvain. |
|
![]() |
| Outils de la discussion | |
|
|