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

Programmation parallèle, calcul scientifique et de haute performance (HPC) Discussion :

Optimisation de lecture parallèle de plusieurs fichiers


Sujet :

Programmation parallèle, calcul scientifique et de haute performance (HPC)

  1. #1
    Membre à l'essai
    Inscrit en
    Juin 2009
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Juin 2009
    Messages : 49
    Points : 21
    Points
    21
    Par défaut Optimisation de lecture parallèle de plusieurs fichiers
    Bonjour tout le monde !

    Je vais la jouer succinte aujourd'hui, ca permettra de laisser le sujet libre a toute discussion.

    Contexte (simplifié) :
    J'ai quatre fichiers, 4 coeurs (donc 4 threads disponibles).

    Objectif : Lire le plus vite possible les 4 fichiers.

    Solution 1 :
    Chaque core s'occupe d'un fichier.

    Premiere conclusion et question ouverte : Mouais 4 threads ok mais il n'y a toujours qu'un seul disque dur alors ça doit revenir à la même chose que lire les fichiers un à un avec un seul core.... Est-ce que ça revient à la même chose ?

    Situation 2 :
    On complexifie un peu la situation. On suppose que les 4 fichiers peuvent être sur plusieurs disques durs en fait.

    Solution 2 :
    On regarde la racine des filepath et on attribue à chaque thread un disque dur et non un fichier.

    Exemple:
    2 fichiers sur C:, 1 fichier sur E et un sur G:

    Thread 1 va lire F1, puis F2
    Pendant que Thread 2 va lire F3
    Pendant que Thread 3 va lire F4
    Pendant que Thread 4 se la touche.

    Conclusion finale et question ouverte : On devrait gagner du temps. Correct ?

    Merci pour votre enthousiasme

  2. #2
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    réponse de normand: ca dépend

    Vous interagissez avec l'OS et les réactions de l'OS + des IOs + du CPUs c'est de nos jour tout sauf prévisible et calculable. Seules des mesures concretes et multiples des différentes techniques sur l'environnement ciblé vous répondront.

    aussi:

    Citation Envoyé par thebop Voir le message
    Premiere conclusion et question ouverte : Mouais 4 threads ok mais il n'y a toujours qu'un seul disque dur alors ça doit revenir à la même chose que lire les fichiers un à un avec un seul core.... Est-ce que ça revient à la même chose ?
    Si on ne fait qu'attendre les IOs d'un disque unique, le temps total sera similaire à quelques détails près:

    Souvent un disque est plus rapide à lire en continu un fichier qu'à sauter à gauche à droite (ce qu'on lui demande en lisant 4 fichiers en parallèle)
    Même si le temps total est le même, en lisant 1 à 1, le premier fichier sera déjà traité au bout de 1/4 du temps

  3. #3
    Membre à l'essai
    Inscrit en
    Juin 2009
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Juin 2009
    Messages : 49
    Points : 21
    Points
    21
    Par défaut
    Pour la premiere solution c'est bien ce que je pensais.

    Pour la deuxieme, meme si on ne peut pas prevoir si facilement selon l'environnement est-ce qu'au moins cela participe plus logiquement a de la lecture multi-threadee. Est-ce une solution intelligente ? Est-ce qu'au moins ca ne va pas empirer les choses ?

    Merci pour tes eclaircissements en tout cas.

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 309
    Points : 928
    Points
    928
    Par défaut
    Dans l'ensemble je dirais :
    • accéder de façons concurrente à un disque est un carnage. Un disque dur, ce sont des plateaux qui tournent et une tête qui se déplace. Lorsque la tête est en place et ne se décale que d'un cran à la fois (lecture de segments continus), le débit est maximal. Dès que la tête doit se déplacer, l'effondrement des performances est *catastrophique*. Moralité lire A puis B sur un disque ira beaucoup plus vite que de lire A et B en parallèle.
    • dans le cas où les fichiers sont sur des disques différent, je dirais qu'il est peu probable que tu perdes du temps à faire un accès concurrent. Il se pourrait qu'un bus quelque part sature, mais je pense qu'au pire on ne multipliera pas le débit par le nombre de coeur, mais qu'on ne perdra en tout cas pas en débit par rapport à une lecture séquentielle. Mais le seul moyen d'en être sûr, c'est évidement de tester !


    Tout ceci suppose bien évidement que les opérations faites sur les données lues sont simple et rapide. Genre compter les caractères, ou que sais-je. Dans ce genre de cas d'ailleurs (c'est à dire pour une application où la composante IO est majoritaire) avoir plusieurs coeur ne changera pas grand chose (on savait faire du multi-threads sur des mono coeurs )

    My 2c.

  5. #5
    Membre à l'essai
    Inscrit en
    Juin 2009
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Juin 2009
    Messages : 49
    Points : 21
    Points
    21
    Par défaut
    C'est vrai que le CPU va pas trop en demander dans ce cas la.

    Et oui justement l'aspect mecanique du disque me semblait aussi plus envenimer les choses. Donc cool je vais tester un peu ca, je pense aussi que dans le pire des cas resultera a un traitement sequentiel monothread usuel. Dans tous les cas je vais pas mettre trois heures a implementer ca.

    Je ne vais faire que lire les donneees, mon objectif maintenant et d'additionner toutes ces donnees dans un seul et meme tableau partage, le parallelisme va devenir ainsi concurrent.


    Merci pour tout

  6. #6
    Modérateur
    Avatar de gangsoleil
    Homme Profil pro
    Manager / Cyber Sécurité
    Inscrit en
    Mai 2004
    Messages
    10 149
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Manager / Cyber Sécurité

    Informations forums :
    Inscription : Mai 2004
    Messages : 10 149
    Points : 28 116
    Points
    28 116
    Par défaut
    Bonjour,

    Attention aussi : ce qui est vrai avec un disque dur classique (notamment les temps de mouvement de la tete de lecture) ne l'est plus avec un disque SSD.

    Il est donc important de connaitre le type de disque pour savoir quelles optimisations faire.
    "La route est longue, mais le chemin est libre" -- https://framasoft.org/
    Les règles du forum

  7. #7
    Membre à l'essai
    Inscrit en
    Juin 2009
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Juin 2009
    Messages : 49
    Points : 21
    Points
    21
    Par défaut
    Tout comme un autre forumeur sur un autre forum m'avait dit que "il ne fallait pas reinventer le RAID3". Je dois faire de la lecture streaming sur de tres gros fichiers (40-60 Mo) en parallele, il est vrai que finalement tous ses problemes sont aussi optimisees avec le RAID3 "fichiers dupliques sur plusieurs disques donc gain de temps de la lecture du disque proportionnel au nombre de disques".

    Donc est-ce que je devrais vraiment m'embeter avec tout ca ?

  8. #8
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    non, essaie une ou deux méthodes de travail et prend celle qui, après mesure, est la plus performante tout en restant maintenable. De toutes façons, il est inutile de vouloir optimiser trop tot

  9. #9
    Membre à l'essai
    Inscrit en
    Juin 2009
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Juin 2009
    Messages : 49
    Points : 21
    Points
    21
    Par défaut
    Oui mais justement j'en suis a l'opti

    Alors j'ai une petite question dans la meme lignee si vous le voulez bien qui concerne la metaphore des poupees russes transportable (ou non) au principe du parallelisme.
    En d'autre terme : a partir de quel moment devrait on arreter de paralleliser ? (on suppose que le tout est bien manage)

    Concretement voila comment je vais proceder.

    J'aurai un thread lisant une pile de fichiers pour chaque disque dur different detecte. Chaque fichier est compresse je vais donc ici proceder a un decodage en parallele (le format le permettant) donc je vais couper la decompression en n parties (pour n cores recenses par l'application) et donc lancer n threads.

    Mais c'est pas fini !

    Chacun de ces threads de decompression va finalement finir sa route en inscrivant les donnees decompressees (des float) une a une dans un tableau commun partage par tous les threads en faisant appel a sa fonction write(float* data), et la encore je veux decouper la boucle for qui additionne un a un tous les floats recu en n parties pour chaque appel effectue a la fonction write.

    Recapitulons, dans un programme devant lire sur deux disques differents tournant avec un 4-core on aura en gros au maximum du processus (c'est a dire lorsqu'on arrive a write()) :

    2 threads pour la lecture + 2 * 4 threads de decompression + 2* 4 * 4 threads d'addition de float dans un buffer partage = 42 threads dont 32 actifs (write) et 10 en attente (et dont 8 a deux doigts d'etre vraisemblablement killes).

    Auxquels s'ajouteront bien entendu tous les autres threads de l'application, evenementiel, gui, etc.

    42 threads soit environ 10 threads par coeur... quand meme. Est-ce cingles ? Moi je me dis que non car finalement ils ne font tous que des choses tres basiques et le tout realise de maniere tres interne : lecture, decodage sur place, ecriture. On n'a pas vraiment de thread ultra bloquants comme il peut intervenir avec des sockets ou attente d'intervention de la part de l'utilisateur.

    Suis-je correct ou deja dans la parallelomanie ?

  10. #10
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par thebop Voir le message
    42 threads soit environ 10 threads par coeur... quand meme. Est-ce cingles ?
    ..
    Suis-je correct ou deja dans la parallelomanie ?

    Euh.. Déjà 2 threads sur le même CPU, c'est un équivalent à 2 process : il y a un scheduler.... C'est donc du faux parallèlisme (les threads vont, eux, être concurrents sur l'accès au CPU)

    Le fond de l'histoire : on ne fait qu'une chose sur un processeur à un temps donné...



    Ou alors j'ai perdu quelque chose en route...
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  11. #11
    Membre à l'essai
    Inscrit en
    Juin 2009
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Juin 2009
    Messages : 49
    Points : 21
    Points
    21
    Par défaut
    Yep mais c'est justement le point enonce par ma question mal posee en fait j'imagine.

    Ma question est : a partir du moment ou l'on veut paralleliser un programme doit on se soucier du nombre de processeurs disponibles ou doit on simplement paralleliser tout ce qui est en notre devoir et s'en remettre a l'ordonnanceur qui se debrouillera pour agencer cela sur un nombre de coeurs inferieur si le cas se presente.

  12. #12
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    moi (mais je sais, j'ai un esprit bizarre) je poserais le problème en sens inverse...


    Comment créer un programme parallélisable, mais qui profite du nombre de processeurs à sa disposition ???

    Là, si jamais tu ne tournes que sur 1 coeur, tu vas saturer ton système...
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  13. #13
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 309
    Points : 928
    Points
    928
    Par défaut
    Citation Envoyé par souviron34 Voir le message
    Euh.. Déjà 2 threads sur le même CPU, c'est un équivalent à 2 process : il y a un scheduler.... C'est donc du faux parallèlisme (les threads vont, eux, être concurrents sur l'accès au CPU)
    Ce n'est pas toujours équivalent. Sous linux, un context switch entre deux threads d'un même programme est considérablement moins cher qu'entre deux process (j'ai entendu dire que les threads étaient beaucoup plus lourd sous windows, mais je suis très loin d'en être sûr et je ne veux pas me lancer dans un troll moisi)

    De plus, il y a dans un certain nombre de langage/framework des threads dit "léger" dont la gestion n'est pas donné à l'OS (contrairement aux threads "posix" par exemple) et où le changement de contexte peut être extrêmement peu cher (typiquement des threads coopératif et non préemptif)

    Et puisqu'on parle d'une application avec beaucoup d'IO (en plus sur disque) on peut gagner beaucoup à faire tourner plusieurs threads sur un même coeur (combien de threads par coeur reste une question dont la réponse dépend totalement de l'application, du processeur, de l'OS, du disque, des bus, de la RAM, de l'age du capitaine et de la phase de la lune)

  14. #14
    Membre à l'essai
    Inscrit en
    Juin 2009
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Juin 2009
    Messages : 49
    Points : 21
    Points
    21
    Par défaut
    Mon petit doigt commence serieusement a me dire "t'es pas un peu fou ?"

    Mais tout de meme. Dans notre cas n'oubliez pas que si le tout est pas trop mal fait les threads de lecture des disques attendent d'etre notifies par une condition_variable par les threads de decoding qui eux meme attendent d'etre notifies par les threads d'ecriture. Je ne vois pas comment optimiser plus l'attente autre que par notification entre condition_variable.

    Mais cela reste-il suffisant et pas du saturage massif pour 4 coeurs. Mais j'imagine que dans ce modele il faut garder en a l'esprit qu'il ne faut avoir au maximum que n threads veritablement actifs et "pas trop en attente", donc dans ce cas la on s'en arreter a decouper le decodage en deux threads distincts sur deux threads de lecture en parallele. Ce qui ferait 4 threads actifs de decodage/ecriture et 2 threads passifs de lecture en attente.

  15. #15
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par TropMDR Voir le message
    Ce n'est pas toujours équivalent. Sous linux, un context switch entre deux threads d'un même programme est considérablement moins cher qu'entre deux process (j'ai entendu dire que les threads étaient beaucoup plus lourd sous windows, mais je suis très loin d'en être sûr et je ne veux pas me lancer dans un troll moisi)

    De plus, il y a dans un certain nombre de langage/framework des threads dit "léger" dont la gestion n'est pas donné à l'OS (contrairement aux threads "posix" par exemple) et où le changement de contexte peut être extrêmement peu cher (typiquement des threads coopératif et non préemptif)

    Et puisqu'on parle d'une application avec beaucoup d'IO (en plus sur disque) on peut gagner beaucoup à faire tourner plusieurs threads sur un même coeur (combien de threads par coeur reste une question dont la réponse dépend totalement de l'application, du processeur, de l'OS, du disque, des bus, de la RAM, de l'age du capitaine et de la phase de la lune)
    J'admet tout à fait, je n'y connais que pouic en threads...

    Cependant, il suffit par exemple sur Linux de lancer un bon gros tar sur un très très gros répertoire (par exemple la partition windows) pour voir qu"on peut pas faire grand chose d'autre en //...




    Citation Envoyé par thebop Voir le message
    Mon petit doigt commence serieusement a me dire "t'es pas un peu fou ?"

    Mais tout de meme. Dans notre cas n'oubliez pas que si le tout est pas trop mal fait les threads de lecture des disques attendent d'etre notifies par une condition_variable par les threads de decoding qui eux meme attendent d'etre notifies par les threads d'ecriture. Je ne vois pas comment optimiser plus l'attente autre que par notification entre condition_variable.

    Mais cela reste-il suffisant et pas du saturage massif pour 4 coeurs. Mais j'imagine que dans ce modele il faut garder en a l'esprit qu'il ne faut avoir au maximum que n threads veritablement actifs et "pas trop en attente", donc dans ce cas la on s'en arreter a decouper le decodage en deux threads distincts sur deux threads de lecture en parallele. Ce qui ferait 4 threads actifs de decodage/ecriture et 2 threads passifs de lecture en attente.

    Ben disons qu'alors tu pourrais faire un paramètre modulo nbe de coeurs/2 ...
    ou ncoeurs/4 .. et programmer tous tes trucs en fonction de ce paramètre...
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  16. #16
    Membre à l'essai
    Inscrit en
    Juin 2009
    Messages
    49
    Détails du profil
    Informations forums :
    Inscription : Juin 2009
    Messages : 49
    Points : 21
    Points
    21
    Par défaut
    Ok

    Maintenant comme je suis chiant j'imagine que SI par contre la partie addition des donnees decompressees dans un tableau partagee est realisee en parallele cette fois avec openCL et donc par le GPU ca ne pose pas de probleme.

    En theorie.... mais j'ai remarque que la // c'est vraiment du theorique encore et je crois que tant qu'on se met vraiment pas sur des langages developpes pour le // (ce que le c++ n'est pas et ne sera vraisembablement jamais) on se met nous meme des batons dans les roues.

  17. #17
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 309
    Points : 928
    Points
    928
    Par défaut
    Citation Envoyé par souviron34 Voir le message
    Cependant, il suffit par exemple sur Linux de lancer un bon gros tar sur un très très gros répertoire (par exemple la partition windows) pour voir qu"on peut pas faire grand chose d'autre en //...
    Boarf, quand je fais
    tar -c ~ >/dev/null
    tar ne monte pas à plus de 30% CPU, ce qui laisse largement la place pour bosser à coté. Après bien sûr, le disque est à fond les manettes.

  18. #18
    Expert éminent sénior

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 603
    Détails du profil
    Informations personnelles :
    Âge : 66
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 603
    Points : 17 913
    Points
    17 913
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par TropMDR Voir le message
    Après bien sûr, le disque est à fond les manettes.
    voui, mais là on parlait d'accès disque justement
    "Un homme sage ne croit que la moitié de ce qu’il lit. Plus sage encore, il sait laquelle".

    Consultant indépendant.
    Architecture systèmes complexes. Programmation grosses applications critiques. Ergonomie.
    C, Fortran, XWindow/Motif, Java

    Je ne réponds pas aux MP techniques

  19. #19
    Membre éprouvé
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    309
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2010
    Messages : 309
    Points : 928
    Points
    928
    Par défaut
    Citation Envoyé par souviron34 Voir le message
    voui, mais là on parlait d'accès disque justement
    Non non ! Toute l'idée est de n'avoir qu'un seul thread de lecture par disque. En gros, pour chaque disque physique différent, tu aurais un thread qui lit les informations sur ce disque et les place en mémoire. Et tu aurais d'autres threads à coté qui s'occuperait de traiter les informations en questions. Et il est alors raisonnable d'avoir sur le même coeur un thread en lecture et un thread de traitement, parce que le thread de lecture passe en fait son temps à attendre des données des disques, temps pendant lequel le coeur ne fait rien, ce qui autorise le thread de traitement de faire son boulot. Et en plus, s'ils sont sur le même coeur, il peuvent partager leur cache de bas niveau, rendant le traitement d'autant plus rapide.

    Après, encore une fois, pour savoir combien de thread il faut faire tourner, je ne pense pas qu'il existe d'autre solution que le test. Il est beaucoup trop ardu (voir impossible) de modéliser l'ensemble du système et bien plus simple de juste l'utiliser.

  20. #20
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 360
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 360
    Points : 20 377
    Points
    20 377
    Par défaut
    Citation Envoyé par TropMDR Voir le message
    Dans l'ensemble je dirais :
    accéder de façons concurrente à un disque est un carnage. Un disque dur, ce sont des plateaux qui tournent et une tête qui se déplace. Lorsque la tête est en place et ne se décale que d'un cran à la fois (lecture de segments continus), le débit est maximal. Dès que la tête doit se déplacer, l'effondrement des performances est *catastrophique*. Moralité lire A puis B sur un disque ira beaucoup plus vite que de lire A et B en parallèle.
    tu as raison ; ceci dit je crois qu'il existe une mémoire tampon/cache pour lire les données ceci pour contrecarrer la lenteur d'un disque dur

Discussions similaires

  1. Réponses: 2
    Dernier message: 05/02/2011, 15h26
  2. [Perf] Optimiser la lecture d'un fichier de taille > 2 m
    Par sacofan dans le forum Entrée/Sortie
    Réponses: 7
    Dernier message: 22/07/2005, 13h25
  3. Optimisation de la lecture de tres gros fichiers
    Par Lydie dans le forum C++Builder
    Réponses: 4
    Dernier message: 12/07/2004, 14h09
  4. [langage] Optimiser la lecture d'un fichier
    Par And_the_problem_is dans le forum Langage
    Réponses: 4
    Dernier message: 05/02/2003, 08h54
  5. [langage] Optimiser la lecture d'un fichier
    Par And_the_problem_is dans le forum Langage
    Réponses: 2
    Dernier message: 11/06/2002, 10h24

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