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

Caml Discussion :

OCaml: comment accélérer lectures et écritures


Sujet :

Caml

  1. #1
    Nouveau membre du Club
    Inscrit en
    Avril 2007
    Messages
    31
    Détails du profil
    Informations personnelles :
    Âge : 55

    Informations forums :
    Inscription : Avril 2007
    Messages : 31
    Points : 29
    Points
    29
    Par défaut OCaml: comment accélérer lectures et écritures
    Bonjour,

    J'ai le petit bout de programme suivant qui lit un entier positif sur une ligne et imprime 91 s'il est inférieur ou égal à 100 et le résultat de la différence de ce nombre et de 10 s'il est supérieur ou égal à 101. Le programme s'arrête lorsqu'il lit le nombre 0.

    Ce programme est trop lent pour mes besoins actuels. Quelqu'un pourrait-il m'indiquer comment le modifier pour qu'il soit plus rapide?

    D'avance merci.

    David.
    --

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    let _ =
      try 
        while true do
          Scanf.bscanf Scanf.Scanning.stdib "%i\n" 
    	(function
    	     0 -> exit 0
    	   | n -> 
    	       Printf.fprintf stdout "f91(%i) = %i\n" n (if n <= 100 then 91 else n - 10)
    	)
        done
      with End_of_file -> exit 0

  2. #2
    Membre éclairé
    Avatar de GnuVince
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2004
    Messages
    679
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2004
    Messages : 679
    Points : 803
    Points
    803
    Par défaut
    T'as essayé sans scanf?

  3. #3
    Rédacteur/Modérateur

    Avatar de gorgonite
    Homme Profil pro
    Ingénieur d'études
    Inscrit en
    Décembre 2005
    Messages
    10 322
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur d'études
    Secteur : Transports

    Informations forums :
    Inscription : Décembre 2005
    Messages : 10 322
    Points : 18 679
    Points
    18 679
    Par défaut
    Citation Envoyé par GnuVince Voir le message
    T'as essayé sans scanf?
    +1

    read_line puis int_of_string... ça devrait être plus rapide


    et au passage, pourquoi ne pas déclarer la "fonction anonyme" avant
    Evitez les MP pour les questions techniques... il y a des forums
    Contributions sur DVP : Mes Tutos | Mon Blog

  4. #4
    Membre éclairé
    Avatar de GnuVince
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2004
    Messages
    679
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2004
    Messages : 679
    Points : 803
    Points
    803
    Par défaut
    Avec un fichier de 100,000 lignes (jamais 0):

    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
     
    $ time ./a.out data > /dev/null
     
    real    0m0.369s
    user    0m0.340s
    sys     0m0.020s
     
     
    $ cat f91.ml
    let _ =
        let f91 = fun n -> if n <= 100 then 91 else n - 10 in
        try
            let f = open_in Sys.argv.(1) in
            while true do
                let x = int_of_string (input_line f) in
                if x == 0 then
                    exit 0
                else
                    Printf.printf "f91(%i) = %i\n" x (f91 x)
            done
        with End_of_file -> exit 0
    Mon O'Caml est très rouillé, donc c'est probablement possible de faire plus joli.

  5. #5
    Membre éprouvé
    Avatar de InOCamlWeTrust
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    1 036
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 036
    Points : 1 284
    Points
    1 284
    Par défaut
    Citation Envoyé par GnuVince Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
                let x = int_of_string (input_line f) in
                if x == 0 then
    Mon O'Caml est très rouillé, donc c'est probablement possible de faire plus joli.
    Il ne faut pas utiliser l'égalité physique ; en tous cas, pas dans ce contexte-ci. C'est peut-être une erreur d'étourderie...
    When Colt produced the first practical repeating handgun, it gave rise to the saying God created men, but Colt made them equal.

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    832
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 832
    Points : 1 104
    Points
    1 104
    Par défaut
    Ton masque de scanf est bizarre : pourquoi " %d\n" alors que " %d" suffit ? (l'espace précédant le %d lui dit déjà d'ignorer les espaces et sauts divers, donc le \n est inutile).

    Sinon effectivement, essaie de virer scanf _et_ printf pour voir si ça change quelque chose. Sinon, es-tu sûr de faire les tests dans les conditions réelles ? Afficher une sortie dans un terminal est notablement plus lent que l'envoyer vers un programme ou /dev/null par exemple.

    Enfin, petite suggestion pour ton "91 si n <= 100 ..." :

  7. #7
    Nouveau membre du Club
    Inscrit en
    Avril 2007
    Messages
    31
    Détails du profil
    Informations personnelles :
    Âge : 55

    Informations forums :
    Inscription : Avril 2007
    Messages : 31
    Points : 29
    Points
    29
    Par défaut
    J'aimerai bien enlever scanf et printf en effet, puisque cela est trop lent. Mais que mettre à la place? Pour ce qui est du scanf, j'ai donc appris que input_line et int_of_string, en l'occurence, peuvent être utilisés. Et pour substituer printf, qu'y a-t-il de mieux? Un unique print_string du résultat de la concaténation des données que je veux imprimer? Ou une série combinant des appels à print_string et print_int? Y a-t-il une autre possibilité.

    Il m'a été aussi suggérer de remplacer la fonction anonyme par une fonction déclarée auparavant. À part une touche subjective de lisibilité, quel est l'avantage?

    David.
    --

  8. #8
    Membre éclairé
    Avatar de GnuVince
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2004
    Messages
    679
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2004
    Messages : 679
    Points : 803
    Points
    803
    Par défaut
    Citation Envoyé par DavidDeharbe Voir le message
    Il m'a été aussi suggérer de remplacer la fonction anonyme par une fonction déclarée auparavant. À part une touche subjective de lisibilité, quel est l'avantage?

    David.
    --
    La fonction va être compilée une seule fois.

    InOcamlWeTrust: Ouais, je me rappelais plus si == était identité ou égalité en O'Caml.

  9. #9
    Nouveau membre du Club
    Inscrit en
    Avril 2007
    Messages
    31
    Détails du profil
    Informations personnelles :
    Âge : 55

    Informations forums :
    Inscription : Avril 2007
    Messages : 31
    Points : 29
    Points
    29
    Par défaut Masque et max
    Citation Envoyé par bluestorm Voir le message
    Ton masque de scanf est bizarre : pourquoi " %d\n" alors que " %d" suffit ? (l'espace précédant le %d lui dit déjà d'ignorer les espaces et sauts divers, donc le \n est inutile).

    Sinon effectivement, essaie de virer scanf _et_ printf pour voir si ça change quelque chose. Sinon, es-tu sûr de faire les tests dans les conditions réelles ? Afficher une sortie dans un terminal est notablement plus lent que l'envoyer vers un programme ou /dev/null par exemple.

    Enfin, petite suggestion pour ton "91 si n <= 100 ..." :
    En fait mon masque était "%i\n". J'ai mis le '\n' parce qu'il y avait erreur d'exécution sans cette partie. Mais j'aurai appris le truc de précéder le "%i" d'un espace pour indiquer d'ignorer les blancs.

    Et bien vu pour le max, cela m'avait échappé.

    David.
    --

  10. #10
    Nouveau membre du Club
    Inscrit en
    Avril 2007
    Messages
    31
    Détails du profil
    Informations personnelles :
    Âge : 55

    Informations forums :
    Inscription : Avril 2007
    Messages : 31
    Points : 29
    Points
    29
    Par défaut
    Citation Envoyé par GnuVince Voir le message
    La fonction va être compilée une seule fois.
    Et comment sont compilées les fonctions anonymes?

    David.
    --

  11. #11
    Membre éprouvé
    Avatar de InOCamlWeTrust
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    1 036
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 036
    Points : 1 284
    Points
    1 284
    Par défaut
    == c'est bien l'égalité physique.

    Dans ton cas, il est même très probable que tu n'obtiennes pas du tout le même résultat, étant donné que tu compares une valeur très certainement présente dans le tas (mais pas garanti...) à une constante immédiate !

    Il faut vraiment faire gaffe à ==. Je conseille, personnellement, de ne l'utiliser qu'avec des données structurées, des enregistrements et des objets, en fait, et non des constructeurs, étant donné que les constructeurs constants sont transformés en entiers, et que les entiers ne sont pas garantis être toujours présents dans le tas. OCaml sait un tout petit peu optimiser ce genre de chose concernant les entiers, et ne crée pas toujours de case mémoire dans le tas pour les entiers.
    When Colt produced the first practical repeating handgun, it gave rise to the saying God created men, but Colt made them equal.

  12. #12
    Membre éprouvé
    Avatar de InOCamlWeTrust
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    1 036
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 036
    Points : 1 284
    Points
    1 284
    Par défaut
    Citation Envoyé par GnuVince Voir le message
    La fonction va être compilée une seule fois.
    Dans les deux cas, elle ne sera compilée qu'une seule fois !

    La seuls chose, c'est qu'en la déclarant à l'extérieur et en l'utilisant telle quelle, il n'y aura pas besoin d'allouer à chaque fois le petit bloc mémoire nécessaire à son utilisation (la fermeture), si je ne me trompe pas (je regarderai chez moi, dans la Bible)... mais là, on rentre dans de la micro-optimisation, pas follement intéressante en langage OCaml, à tous points de vue.

    Le C, c'est bien pour ce genre de choses, aussi...
    When Colt produced the first practical repeating handgun, it gave rise to the saying God created men, but Colt made them equal.

  13. #13
    alex_pi
    Invité(e)
    Par défaut
    Citation Envoyé par InOCamlWeTrust Voir le message
    == c'est bien l'égalité physique.

    Dans ton cas, il est même très probable que tu n'obtiennes pas du tout le même résultat, étant donné que tu compares une valeur très certainement présente dans le tas (mais pas garanti...) à une constante immédiate !

    Il faut vraiment faire gaffe à ==. Je conseille, personnellement, de ne l'utiliser qu'avec des données structurées, des enregistrements et des objets, en fait, et non des constructeurs, étant donné que les constructeurs constants sont transformés en entiers, et que les entiers ne sont pas garantis être toujours présents dans le tas. OCaml sait un tout petit peu optimiser ce genre de chose concernant les entiers, et ne crée pas toujours de case mémoire dans le tas pour les entiers.
    A ma connaissance :
    • L'égalité physique sur les entiers est équivalente à l'égalité structurelle (et ceci est du au point suivant)
    • un entier n'est pas boxé (mis sur le tas avec une référence dessus). C'est d'ailleurs pour ça que les entier Caml sont sur 31 bits (63 sur machine 64 bits), pour permettre au GC de les différencier d'un pointeur. En revanche, à part les booléens, les caractères, et les entiers (et les types unions à cardinal plus petit que les entiers), tout est boxé !


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    # let a = 1 and b = 1 in a ==b;;
    - : bool = true
    # let c = 1. and d = 1. in c == d;;
    - : bool = false

  14. #14
    Membre éprouvé
    Avatar de InOCamlWeTrust
    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    1 036
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 1 036
    Points : 1 284
    Points
    1 284
    Par défaut
    Citation Envoyé par alex_pi
    • un entier n'est pas boxé (mis sur le tas avec une référence dessus). C'est d'ailleurs pour ça que les entier Caml sont sur 31 bits (63 sur machine 64 bits), pour permettre au GC de les différencier d'un pointeur. En revanche, à part les booléens, les caractères, et les entiers (et les types unions à cardinal plus petit que les entiers), tout est boxé !
    Non : les entiers peuvent se retrouver sur le tas. Lorsque tu crées un vecteur d'entiers, les entiers sont effctivement dessus. Le bit manquant sert à la phase mark du garbage collector, afin de ne pas suivre les liens dont le premier bit est mis à 1.
    When Colt produced the first practical repeating handgun, it gave rise to the saying God created men, but Colt made them equal.

Discussions similaires

  1. Réponses: 4
    Dernier message: 07/04/2007, 01h05
  2. [VB6] lecture et écriture de fichier
    Par robert_trudel dans le forum VB 6 et antérieur
    Réponses: 7
    Dernier message: 12/06/2006, 14h06
  3. [VB.NET]Problème de lecture et écriture sur fichier texte
    Par zouhib dans le forum Windows Forms
    Réponses: 25
    Dernier message: 23/05/2006, 15h30
  4. [IB 6.0] Comment accélérer l'accès a la BD ?
    Par mafuku dans le forum InterBase
    Réponses: 2
    Dernier message: 20/12/2005, 10h48
  5. Ouvrir un fichier texte en lecture ET écriture
    Par Steph12 dans le forum C++
    Réponses: 12
    Dernier message: 17/06/2005, 08h08

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