Anthony Jaguenaud a écrit 1941 commentaires

  • [^] # Re: Haskel

    Posté par  . En réponse au journal résoudre "trouve 24". Évalué à 4.

    Voilà la solution, j’ai changé les Int en Ratio Int, enlevé les vérifications de la division et de la soustraction (mais là, je n’en vois pas l’intérêt ;-) )

    À chaque modification, j’ai laissé l’ancienne ligne en commentaire pour voir les différences.

    import Data.List
    -- new line
    import Data.Ratio
    
    -- A value is an Int or an operation with two arguments and a result.
    --data Value = V Int | Op Operation Value Value Int
    data Value = V (Ratio Int) | Op Operation Value Value (Ratio Int)
    data Operation = Plus | Min | Mult | Div | Error
    
    -- Instance of Show class to be able to display Operation type
    instance Show Operation where
      show Plus = "+"
      show Min  = "-"
      show Mult = "×"
      show Div  = "÷"
      show _    = "Error"
    
    -- Instance of Show class for Value.
    instance Show Value where
    --  show (V a) = show a
      show (V a) = show $ numerator a  -- The value is a % 1
      show (Op o a b _) = " (" ++ (show a) ++ (show o) ++ (show b) ++ ") "
    
    -- Take an Operation and a list of 2 minimal Values. Generate a new value with the first two terms.
    doOp :: Operation -> [Value] -> [Value]
    doOp Plus (a:b:xs) = (Op Plus a b (va+vb):xs)
                          where va = getV a
                                vb = getV b
    -- We don't want to have negative values, so check if a >= b
    -- We work in ℚ
    doOp Min (a:b:xs) = (Op Min a b ((getV a)-(getV b)):xs)
    --                   | otherwise = (Op Error a b (-1)):xs
    doOp Mult (a:b:xs) = (Op Mult a b (va*vb)):xs
                          where va = getV a
                                vb = getV b
    -- First check that divisor is not 0, then check if b can divide a without rest.
    doOp Div (a:b:xs) | vb == 0 = (Op Error a b (-1)):xs
    --                  | va `mod` vb == 0 = (Op Div a b (va `div` vb)):xs
    --                  | otherwise = (Op Error a b (-1)):xs
                      | otherwise = (Op Div a b (va / vb)):xs
                       where va = getV a
                             vb = getV b
    
    -- Create a Ratio
    --setV a = V a
    setV a = V (a % 1)
    getV (V a) = a
    getV (Op _ _ _ a) = a
    
    
    -- Do operations, take a list of Values and do all operations, drop error if a computation is not possible
    doOps :: [Value] -> [[Value]]
    doOps a = filter (dropError.head) $ map (\x -> doOp x a) [Plus, Min, Mult, Div] 
    
    -- Check for error filter, return True if it's valid.
    dropError :: Value -> Bool
    dropError (Op Error _ _ _) = False
    dropError _ = True
    
    -- En entrée une liste de values, en sortie une liste d'opérations filtrée.
    -- Check we have 4 numbers.
    -- From right to left
    --    - map setV x  => generate a Value list with only V values.
    --    - compute all permutations
    --    - For each list of values apply all operations on first two values, we get list of list of list so concat to obtain list of list Values
    --    - We have 3 elements
    --    - For each element, we perform permutations and concat to get a list of list of Values.
    --    - loop twice to get list of list of Value with length == 1.
    --    - Then filter to check if result is 24.
    get24 :: [Int] -> [[Value]]
    get24 x | length x == 4 = filter (\x -> (getV (head x))==24) $ concat.map doOps $ concat.map permutations $ concat.map doOps $ concat.map permutations $ concat.map doOps $ permutations $ map setV x
            | otherwise = []

    Et le résultat :

    *Main Data.Ratio> get24 [7,7,2,1]
    [[ ( ( (7×7) -1) ÷2) ],[ ( ( (7×7) -1) ÷2) ],[ ( ( (7×7) -1) ÷2) ],[ ( ( (7×7) -1) ÷2) ]]
    *Main Data.Ratio> get24 [ 1,4,5,6]
    [[ (6÷ ( (5÷4) -1) ) ],[ (4÷ (1- (5÷6) ) ) ],[ (6÷ ( (5÷4) -1) ) ],[ (4÷ (1- (5÷6) ) ) ]]
    *Main Data.Ratio> get24 [7,7,2,1]
    [[ ( ( (7×7) -1) ÷2) ],[ ( ( (7×7) -1) ÷2) ],[ ( ( (7×7) -1) ÷2) ],[ ( ( (7×7) -1) ÷2) ]]
    *Main Data.Ratio> get24 [ 1,4,5,6]
    [[ (6÷ ( (5÷4) -1) ) ],[ (4÷ (1- (5÷6) ) ) ],[ (6÷ ( (5÷4) -1) ) ],[ (4÷ (1- (5÷6) ) ) ]]
  • [^] # Re: Haskel

    Posté par  . En réponse au journal résoudre "trouve 24". Évalué à 2.

    Oui, remplacer div par % et adapter les tests dans doOp Div (a:b:xs) :-)

    Non, ça ne marchera pas.

    :t (/)
    (/) :: Fractional a => a -> a -> a
    :t div
    div :: Integral a => a -> a -> a
    Prelude Data.Ratio> 1% 4
    1 % 4
    Prelude Data.Ratio> (1%4) `div` (4%5)
    
    <interactive>:28:1: error:
         Non type-variable argument in the constraint: Integral (Ratio a)
          (Use FlexibleContexts to permit this)
         When checking the inferred type
            it :: forall a. (Integral a, Integral (Ratio a)) => Ratio a

    La division entière à besoin d’un type integral ce que n'est pas Ratio. On ne peut pas mélanger les types dans les divisions.

  • [^] # Re: Haskel

    Posté par  . En réponse au journal résoudre "trouve 24". Évalué à 2. Dernière modification le 04 mars 2022 à 23:38.

    Oui, mais j'ai volontairement omis les nombres à virgules…

    I’ll be back with Rational soon ;-)

  • [^] # Re: Haskel

    Posté par  . En réponse au journal résoudre "trouve 24". Évalué à 2. Dernière modification le 04 mars 2022 à 20:27.

    Non, je n'avait pas testé…

    *Main> get24 [ 1,4,5,6] 
    []
    *Main> 
    

    Il retourne une liste vide, donc sans solution du point de vue de mon programme… c'est le résultat attendu ?

  • [^] # Haskell

    Posté par  . En réponse au journal résoudre "trouve 24". Évalué à 3. Dernière modification le 04 mars 2022 à 19:37.

    J’y ai pensé aussi, je l’ai fait. Je ne suis pas un pro du haskell, soyez bienveillant avec vos remarques ;-)

    import Data.List
    
    -- A value is an Int or an operation with two arguments and a result.
    data Value = V Int | Op Operation Value Value Int
    data Operation = Plus | Min | Mult | Div | Error
    
    -- Instance of Show class to be able to display Operation type
    instance Show Operation where
      show Plus = "+"
      show Min  = "-"
      show Mult = "×"
      show Div  = "÷"
      show _    = "Error"
    
    -- Instance of Show class for Value.
    instance Show Value where
      show (V a) = show a
      show (Op o a b _) = " (" ++ (show a) ++ (show o) ++ (show b) ++ ") "
    
    -- Take an Operation and a list of 2 minimal Values. Generate a new value with the first two terms.
    doOp :: Operation -> [Value] -> [Value]
    doOp Plus (a:b:xs) = (Op Plus a b (va+vb):xs)
                          where va = getV a
                                vb = getV b
    -- We don't want to have negative values, so check if a >= b
    doOp Min (a:b:xs) | (getV a) >= (getV b) = (Op Min a b ((getV a)-(getV b)):xs)
                       | otherwise = (Op Error a b (-1)):xs
    doOp Mult (a:b:xs) = (Op Mult a b (va*vb)):xs
                          where va = getV a
                                vb = getV b
    -- First check that divisor is not 0, then check if b can divide a without rest.
    doOp Div (a:b:xs) | vb == 0 = (Op Error a b (-1)):xs
                      | va `mod` vb == 0 = (Op Div a b (va `div` vb)):xs
                      | otherwise = (Op Error a b (-1)):xs
                       where va = getV a
                             vb = getV b
    
    setV a = V a
    getV (V a) = a
    getV (Op _ _ _ a) = a
    
    
    -- Do operations, take a list of Values and do all operations, drop error if a computation is not possible
    doOps :: [Value] -> [[Value]]
    doOps a = filter (dropError.head) $ map (\x -> doOp x a) [Plus, Min, Mult, Div] 
    
    -- Check for error filter, return True if it's valid.
    dropError :: Value -> Bool
    dropError (Op Error _ _ _) = False
    dropError _ = True
    
    -- En entrée une liste de values, en sortie une liste d'opérations filtrée.
    -- Check we have 4 numbers.
    -- From right to left
    --    - map setV x  => generate a Value list with only V values.
    --    - compute all permutations
    --    - For each list of values apply all operations on first two values, we get list of list of list so concat to obtain list of list Values
    --    - We have 3 elements
    --    - For each element, we perform permutations and concat to get a list of list of Values.
    --    - loop twice to get list of list of Value with length == 1.
    --    - Then filter to check if result is 24.
    get24 :: [Int] -> [[Value]]
    get24 x | length x == 4 = filter (\x -> (getV (head x))==24) $ concat.map doOps $ concat.map permutations $ concat.map doOps $ concat.map permutations $ concat.map doOps $ permutations $ map setV x
            | otherwise = []

    Et les résultats :

    *Main Data.List> :l try24.hs
    [1 of 1] Compiling Main             ( try24.hs, interpreted )
    Ok, one module loaded.
    *Main Data.List> get24 [ 7,7,1,2]
    [[ ( ( (7×7) -1) ÷2) ],[ ( ( (7×7) -1) ÷2) ],[ ( ( (7×7) -1) ÷2) ],[ ( ( (7×7) -1) ÷2) ]]
    *Main Data.List> get24 [ 1,2,3,8]
    [[ ( ( (2-1) ×3) ×8) ],[ (8× ( (2-1) ×3) ) ],[ ( (3× (2-1) ) ×8) ],[ (8× (3× (2-1) ) ) ],[ ( (3÷ (2-1) ) ×8) ],[ (8× (3÷ (2-1) ) ) ],[ ( (8×3) × (2-1) ) ],[ ( (8×3) ÷ (2-1) ) ],[ ( (2-1) × (8×3) ) ],[ ( (3×8) × (2-1) ) ],[ ( (3×8) ÷ (2-1) ) ],[ ( (2-1) × (3×8) ) ],[ ( (8× (2-1) ) ×3) ],[ (3× (8× (2-1) ) ) ],[ ( (8÷ (2-1) ) ×3) ],[ (3× (8÷ (2-1) ) ) ],[ ( ( (2-1) ×8) ×3) ],[ (3× ( (2-1) ×8) ) ],[ ( (8-2) × (3+1) ) ],[ ( (3+1) × (8-2) ) ],[ ( (8+ (3+1) ) ×2) ],[ (2× (8+ (3+1) ) ) ],[ ( ( (3+1) +8) ×2) ],[ (2× ( (3+1) +8) ) ],[ ( (8-2) × (1+3) ) ],[ ( (1+3) × (8-2) ) ],[ ( (8+ (1+3) ) ×2) ],[ (2× (8+ (1+3) ) ) ],[ ( ( (1+3) +8) ×2) ],[ (2× ( (1+3) +8) ) ],[ ( (1+ (8+3) ) ×2) ],[ (2× (1+ (8+3) ) ) ],[ ( ( (8+3) +1) ×2) ],[ (2× ( (8+3) +1) ) ],[ ( (2-1) × (8×3) ) ],[ ( (8×3) × (2-1) ) ],[ ( (8×3) ÷ (2-1) ) ],[ ( (1+ (3+8) ) ×2) ],[ (2× (1+ (3+8) ) ) ],[ ( ( (3+8) +1) ×2) ],[ (2× ( (3+8) +1) ) ],[ ( (2-1) × (3×8) ) ],[ ( (3×8) × (2-1) ) ],[ ( (3×8) ÷ (2-1) ) ],[ ( (1+3) × (8-2) ) ],[ ( (8-2) × (1+3) ) ],[ ( (3+1) × (8-2) ) ],[ ( (8-2) × (3+1) ) ],[ ( (3+ (8+1) ) ×2) ],[ (2× (3+ (8+1) ) ) ],[ ( ( (8+1) +3) ×2) ],[ (2× ( (8+1) +3) ) ],[ ( (3+ (1+8) ) ×2) ],[ (2× (3+ (1+8) ) ) ],[ ( ( (1+8) +3) ×2) ],[ (2× ( (1+8) +3) ) ],[ ( (3+1) × (8-2) ) ],[ ( (8-2) × (3+1) ) ],[ ( (1+3) × (8-2) ) ],[ ( (8-2) × (1+3) ) ],[ ( ( (2-1) ×8) ×3) ],[ (3× ( (2-1) ×8) ) ],[ ( (8× (2-1) ) ×3) ],[ (3× (8× (2-1) ) ) ],[ ( (8÷ (2-1) ) ×3) ],[ (3× (8÷ (2-1) ) ) ],[ ( (3×8) × (2-1) ) ],[ ( (3×8) ÷ (2-1) ) ],[ ( (2-1) × (3×8) ) ],[ ( (8×3) × (2-1) ) ],[ ( (8×3) ÷ (2-1) ) ],[ ( (2-1) × (8×3) ) ],[ ( (3× (2-1) ) ×8) ],[ (8× (3× (2-1) ) ) ],[ ( (3÷ (2-1) ) ×8) ],[ (8× (3÷ (2-1) ) ) ],[ ( ( (2-1) ×3) ×8) ],[ (8× ( (2-1) ×3) ) ],[ ( ( (8+1) +3) ×2) ],[ (2× ( (8+1) +3) ) ],[ ( (3+ (8+1) ) ×2) ],[ (2× (3+ (8+1) ) ) ],[ ( ( (1+8) +3) ×2) ],[ (2× ( (1+8) +3) ) ],[ ( (3+ (1+8) ) ×2) ],[ (2× (3+ (1+8) ) ) ],[ ( ( (1+3) +8) ×2) ],[ (2× ( (1+3) +8) ) ],[ ( (8+ (1+3) ) ×2) ],[ (2× (8+ (1+3) ) ) ],[ ( (8-2) × (1+3) ) ],[ ( (1+3) × (8-2) ) ],[ ( ( (8+3) +1) ×2) ],[ (2× ( (8+3) +1) ) ],[ ( (1+ (8+3) ) ×2) ],[ (2× (1+ (8+3) ) ) ],[ ( (2-1) × (8×3) ) ],[ ( (8×3) × (2-1) ) ],[ ( (8×3) ÷ (2-1) ) ],[ ( ( (3+8) +1) ×2) ],[ (2× ( (3+8) +1) ) ],[ ( (1+ (3+8) ) ×2) ],[ (2× (1+ (3+8) ) ) ],[ ( (2-1) × (3×8) ) ],[ ( (3×8) × (2-1) ) ],[ ( (3×8) ÷ (2-1) ) ],[ ( ( (3+1) +8) ×2) ],[ (2× ( (3+1) +8) ) ],[ ( (8+ (3+1) ) ×2) ],[ (2× (8+ (3+1) ) ) ],[ ( (8-2) × (3+1) ) ],[ ( (3+1) × (8-2) ) ]]
    
    

    Évidemment, on prend toute les permutations d’une même solution.

  • [^] # Re: Survivor

    Posté par  . En réponse au journal C, un âge remarquable. Évalué à 2.

    En vérifiant le retour de snprintf, tu peux savoir s’il y avait assez de place… Obligatoire, dès que tu as en entrée des données que tu ne maitrises pas.

  • [^] # Re: En Prolog

    Posté par  . En réponse au journal résoudre "trouve 24". Évalué à 3.

    (6×4)÷(5-1) et il n’y a que des divisions entières.

  • [^] # Re: Survivor

    Posté par  . En réponse au journal C, un âge remarquable. Évalué à 8.

    Ce qui est dommage avec le C c'est juste la gestion de la mémoire très difficile et sa propension a permettre les buffer overflow par exemple.

    Il faut juste apprendre à programmer…
    J’ai appris à mes enfants, quand ils prennent le jouet d’un copain, à le rendre. Il faut juste faire pareil ;-)

    --->[]

  • [^] # Re: une solution ?

    Posté par  . En réponse au message renommage de fichiers en masse. Évalué à 3.

    Tu as oublié de traiter le cas :

    int ret = iconv(conv, &pin, &ol, &pout, &dl);
    $ man 3 iconv
    ICONV(3)                                                                                                                       Linux Programmer's Manual                                                                                                                      ICONV(3)
    
    NAME
           iconv - perform character set conversion
    
    SYNOPSIS
           #include <iconv.h>
    
           size_t iconv(iconv_t cd,
                        char **inbuf, size_t *inbytesleft,
                        char **outbuf, size_t *outbytesleft);
    
    DESCRIPTION
           The  iconv()  function converts a sequence of characters in one character encoding to a sequence of characters in another character encoding.  The cd argument is a conversion descriptor, previously created by a call to iconv_open(3); the conversion descriptor defines the
           character encodings that iconv() uses for the conversion.  The inbuf argument is the address of a variable that points to the first character of the input sequence; inbytesleft indicates the number of bytes in that buffer.  The outbuf argument is the address of  a  vari‐
           able that points to the first byte available in the output buffer; outbytesleft indicates the number of bytes available in the output buffer.
    
           The  main  case  is  when inbuf is not NULL and *inbuf is not NULL.  In this case, the iconv() function converts the multibyte sequence starting at *inbuf to a multibyte sequence starting at *outbuf.  At most *inbytesleft bytes, starting at *inbuf, will be read.  At most
           *outbytesleft bytes, starting at *outbuf, will be written.
    
           The iconv() function converts one multibyte character at a time, and for each character conversion it increments *inbuf and decrements *inbytesleft by the number of converted input bytes, it increments *outbuf and decrements *outbytesleft by the number of converted  out‐
           put  bytes,  and  it  updates the conversion state contained in cd.  If the character encoding of the input is stateful, the iconv() function can also convert a sequence of input bytes to an update to the conversion state without producing any output bytes; such input is
           called a shift sequence.  The conversion can stop for four reasons:
    
           1. An invalid multibyte sequence is encountered in the input.  In this case, it sets errno to EILSEQ and returns (size_t) -1.  *inbuf is left pointing to the beginning of the invalid multibyte sequence.
    
           2. The input byte sequence has been entirely converted, that is, *inbytesleft has gone down to 0.  In this case, iconv() returns the number of nonreversible conversions performed during this call.
    
           3. An incomplete multibyte sequence is encountered in the input, and the input byte sequence terminates after it.  In this case, it sets errno to EINVAL and returns (size_t) -1.  *inbuf is left pointing to the beginning of the incomplete multibyte sequence.
    
           4. The output buffer has no more room for the next converted character.  In this case, it sets errno to E2BIG and returns (size_t) -1.
    
           A different case is when inbuf is NULL or *inbuf is NULL, but outbuf is not NULL and *outbuf is not NULL.  In this case, the iconv() function attempts to set cd's conversion state to the initial state and store a corresponding shift sequence at *outbuf.   At  most  *out‐
           bytesleft bytes, starting at *outbuf, will be written.  If the output buffer has no more room for this reset sequence, it sets errno to E2BIG and returns (size_t) -1.  Otherwise, it increments *outbuf and decrements *outbytesleft by the number of bytes written.
    
           A third case is when inbuf is NULL or *inbuf is NULL, and outbuf is NULL or *outbuf is NULL.  In this case, the iconv() function sets cd's conversion state to the initial state.
    
    RETURN VALUE
           The iconv() function returns the number of characters converted in a nonreversible way during this call; reversible conversions are not counted.  In case of error, it sets errno and returns (size_t) -1.
    
    ERRORS
           The following errors can occur, among others:
    
           E2BIG  There is not sufficient room at *outbuf.
    
           EILSEQ An invalid multibyte sequence has been encountered in the input.
    
           EINVAL An incomplete multibyte sequence has been encountered in the input.
    
    VERSIONS
           This function is available in glibc since version 2.1.
    
    ATTRIBUTES
           For an explanation of the terms used in this section, see attributes(7).
    
           ┌──────────┬───────────────┬─────────────────┐
           │Interface │ Attribute     │ Value           │
           ├──────────┼───────────────┼─────────────────┤
           │iconv()   │ Thread safety │ MT-Safe race:cd │
           └──────────┴───────────────┴─────────────────┘
           The iconv() function is MT-Safe, as long as callers arrange for mutual exclusion on the cd argument.
    
    CONFORMING TO
           POSIX.1-2001, POSIX.1-2008.
    
    NOTES
           In each series of calls to iconv(), the last should be one with inbuf or *inbuf equal to NULL, in order to flush out any partially converted input.
    
           Although  inbuf  and  outbuf are typed as char **, this does not mean that the objects they point can be interpreted as C strings or as arrays of characters: the interpretation of character byte sequences is handled internally by the conversion functions.  In some encod‐
           ings, a zero byte may be a valid part of a multibyte character.
    
           The caller of iconv() must ensure that the pointers passed to the function are suitable for accessing characters in the appropriate character set.  This includes ensuring correct alignment on platforms that have tight restrictions on alignment.
    
    SEE ALSO
           iconv_close(3), iconv_open(3), iconvconfig(8)
    
    COLOPHON
           This page is part of release 5.10 of the Linux man-pages project.  A description of the project, information about reporting bugs, and the latest version of this page, can be found at https://www.kernel.org/doc/man-pages/.
  • [^] # Re: Presque le même parcours…

    Posté par  . En réponse au journal Comparaison entre Manjaro et Debian Sid. Évalué à 2.

    Il y a vingt ans, je ne me souviens plus trop…
    RedHat -> Mandrake -> Suze -> debian (stable -> sid)(2003) -> gentoo (±14 ans) -> debian stable.

    Maintenant, debian stable est suffisant pour moi, sauf peut-être pour avoir des versions récentes de blender… Mais pour ça, j’utilise la version dans steam :-p

  • [^] # Re: Retour d'erreur ?

    Posté par  . En réponse au message renommage de fichiers en masse. Évalué à 4. Dernière modification le 23 février 2022 à 10:32.

    Quand j’ai testé le code chez moi hier soir, j’avais un retour d’erreur sur iconv. Après, c’est peut-être lié à mon terminal qui n’était peut-être pas en UTF8, mais ton programme doit toujours vérifier tous les codes de retour qui peuvent échouer.

    Quand je ne vérifie pas un code de retour volontairement, par exemple printf, je le cast :

    void exemple(char * str)
    {
        (void) printf("Str : %s\n",str);
    }

    Je sais que printf n’est pas c++, mais c’est l’exemple qui m’est venu immédiatement en tête. ;-)

  • # Retour d'erreur ?

    Posté par  . En réponse au message renommage de fichiers en masse. Évalué à 6. Dernière modification le 22 février 2022 à 22:53.

    Salut,
    Tu ne teste pas les retours de tes fonctions, c’est mal.

    man 3 iconv
    
    RETURN VALUE
    … -1 on error.
    

    Même chose pour iconv_open.
    Rajoute la gestion des erreurs, ça t’aidera à trouver ce qui cloche.

  • # Le code ?

    Posté par  . En réponse au message renommage de fichiers en masse. Évalué à 2.

    Salut,
    Tu devrais mettre le code tel que tu l’as écrit jusque là, on pourra peut-être t’aider à adapter, debugguer.

  • # Aucune option

    Posté par  . En réponse au sondage Développeur Libristes, oui ! mais macOS, Visual Studio et Azure ?. Évalué à 3.

    Salut,
    Dans mon cas, pour le boulot, le PC est sous Windows, je ne développe pas d’application libre. On m’impose Visual.

    Pour le perso, mon ordi à la maison est 100% sous Linux depuis 2003 (c’est là que je n’ai joué qu’avec une compatibilité wine), donc j’utilise emacs, vim, kdevelop ou qtcreator.

  • # S’il pouvait tenir parole…

    Posté par  . En réponse au journal Grosse déception cette semaine. Évalué à 4.

    Ce ne serait pas si mal, on pourrait créer toi-et-tes-amis.fr, ou même retrouver ses anciens copains, les copains d’avant quoi :-p

    Hélas, ils menacent, mais l’argent récolté grâce à la pub les empêchera de mettre leurs menaces à exécution.

  • [^] # Re: Le RGPD ne t'aidera pas

    Posté par  . En réponse au journal RGPD et adresse mail. Évalué à 4.

    En quoi cette complexité est elle inutile ?

  • [^] # Re: OpenCL, portabilité et performance en général

    Posté par  . En réponse à la dépêche OpenCL sous Linux : l’état des pilotes AMD est désormais pire que ce qu’il était à l’époque de fglrx. Évalué à 2.

    Ah, après vérification, je n'ai pas d'APU… </me sifflote en prenant la porte>

  • [^] # Re: OpenCL, portabilité et performance en général

    Posté par  . En réponse à la dépêche OpenCL sous Linux : l’état des pilotes AMD est désormais pire que ce qu’il était à l’époque de fglrx. Évalué à 2.

    Merci, bon il ne me détecte que ma Mi1080… il y a quelque chose à installer pour activer l'APU ?

  • [^] # Re: OpenCL, portabilité et performance en général

    Posté par  . En réponse à la dépêche OpenCL sous Linux : l’état des pilotes AMD est désormais pire que ce qu’il était à l’époque de fglrx. Évalué à 2.

    en fait personne n'utilise des GPU AMD dans mon entourage !

    Ça me fait penser à une question… sur mon ordi, j’ai un Ryzen avec un APU (sans écran), et une carte graphique Nvidia, peut-on faire de l’openCL sur l’APU ?
    Peut-on utiliser le back-end amdgpu de llvm ?

  • # Il y a une limite de temps

    Posté par  . En réponse au message Répondre à une discussion ; Aide ?. Évalué à 6.

    Pour les très vieux contenus (3 mois ?) on ne peut plus poster de commentaire.

  • # Heu…

    Posté par  . En réponse au lien How not to learn TypeScript. Évalué à 2.

    Hello,
    Si je comprends bien, c’est une ode au non-typage… Je trouve l’exemple « mistake 2 » particulièrement laid.
    Avoir trois structures avec des champs ayant le même nom et que ça marche… je comprends pourquoi certains préfère le typescript pour avoir un meilleur système de typage.

  • # setitimer

    Posté par  . En réponse au message probleme pour faire un timer précis de l'ordre de la milliseconde. Évalué à 6.

    Salut,
    Je me suis tenté une implémentation avec setitimer…

    #define _POSIX_C_SOURCE 199309L
    
    #include <stdio.h>
    //    #include <sys/timerfd.h>
        #include <errno.h>
        #include <string.h>
        #include <stdlib.h>
    //  #include <unistd.h>
        #include <sys/mman.h>
    
    //#include <time.h>
    #include <unistd.h>
    #include <threads.h>
    #include <signal.h>
    #include <sys/time.h>
    
    
        #define COUNT 10001
        #define PERIODE 1000000 //1ms (in ns)
    
    mtx_t myLock;
    void (*old_handler)(int); // sighandler_t don't work !!! :-(
    
    void alarm_callback(int sig)
    {
      // Unlock du mutex pour continuer la boucle.
      (void) mtx_unlock(&myLock);
         if ((old_handler = signal(SIGALRM, alarm_callback)) == SIG_ERR)
        {
          fprintf(stderr,"Error setting SIGALARM in alarm_callback\n");
          return ;
        }
    
    
    }
    
        int main(int argc, char const *argv[])
        {
          if (mtx_init(&myLock, mtx_plain ) ==  thrd_error)
        {
          fprintf(stderr,"Error creating mutex\n");
          return -1;
        }
    
          // Lock one time to init locked. First loop must unlock
          if (mtx_lock(&myLock) == thrd_error)
        {
          fprintf(stderr,"Error locking mutex first time\n");
          return -1;
        }
    
          if ((old_handler = signal(SIGALRM, alarm_callback)) == SIG_ERR)
        {
          fprintf(stderr,"Error setting SIGALARM\n");
          return -1;
        }
    
    
    
           struct itimerval setTimer, oldTimer;
    
           setTimer.it_interval.tv_sec = 0;
           // Warning, c’est des us.
           setTimer.it_interval.tv_usec = PERIODE / 1000;
           // First period start in 1s
           setTimer.it_value.tv_sec = 1;
           setTimer.it_value.tv_usec = 0;
           //       Timer values are defined by the following structures:
           //
           //           struct itimerval {
           //               struct timeval it_interval; /* Interval for periodic timer */
           //               struct timeval it_value;    /* Time until next expiration */
           //           };
           //
           //           struct timeval {
           //               time_t      tv_sec;         /* seconds */
           //               suseconds_t tv_usec;        /* microseconds */
           //           };
    
    
           if (setitimer(ITIMER_REAL,&setTimer, &oldTimer) == -1)
         {
           fprintf(stderr,"Setitimer initialization failed\n");
           return -1;
         }
            struct timespec now, previous;
            long somme = 0;
            long peak = PERIODE, base = PERIODE;
            long tabTimer[COUNT];
            __uint64_t ret;
    
    
            if (clock_gettime(CLOCK_MONOTONIC,&previous ) < 0 )
            {
                printf("error clock_gettime : %s\n", strerror(errno));
                return -1;
            }
    
            for (size_t i = 0; i < COUNT; i++)
          {
          // Wait for sync
            if (mtx_lock(&myLock) == thrd_error)
              {
            fprintf(stderr,"Error lock in loop number %d\n",i);
            return -1;
              }
          clock_gettime(CLOCK_MONOTONIC,&now );
                tabTimer[i] = (now.tv_sec - previous.tv_sec) * 1000000000 + now.tv_nsec - previous.tv_nsec;
                previous = now;
    
            }
    
        const long high_10 = PERIODE + PERIODE / 10;
        const long low_10 = PERIODE - PERIODE / 10;
        int higher = 0;
        int lower = 0;
        int normal = 0;
            //we write results
            for (size_t i = 1; i < COUNT; i++)
            {
          //      printf("[%2d] = %ld\n",i,tabTimer[i]);
                somme += tabTimer[i];
                if( tabTimer[i] > peak)
                {
                    peak = tabTimer[i];
                }
                if( tabTimer[i] < base)
                {
                    base = tabTimer[i];
                }
            if (tabTimer[i] > high_10)
              {
            higher++;
              }
            else if (tabTimer[i] < low_10)
              {
            lower++;
              }
            else
              {
            normal++;
              }
            }
    
        int total = lower + higher + normal;
            printf("average en ns = %ld, peak = %ld(+%2.2f%%), base = %ld(-%2.2f%%)\n", somme/(COUNT - 1), peak, (((float)peak/PERIODE) - 1) * 100, base, (1. - ((float)base)/PERIODE)*100);
        printf(" Total : %d,\n"
               "\t- lower : %6d (%2.2f%%)\n"
               "\t- normal: %6d (%2.2f%%)\n"
               "\t- higher: %6d (%2.2f%%)\n",
               total,
               lower, 100. * ((float) lower)/total,
               normal, 100.* ((float)normal)/total,
               higher, 100.* ((float)higher)/total);
    
            return 0;
        }

    Pour le sigalarm, il faut le recabler à chaque fois.
    Voici quelques stats, j’y ai ajouté le nombre de fois ou on a un écart de plus de 10%. De plus, si on déborde sur un cycle, la différence entre les deux sera forcément très inférieur sur le cycle suivant. D’où la relative symétrie (+ou- 1) entre les higher et les lower.

    $ ./a.out 
    average en ns = 999998, peak = 1057467(+5.75%), base = 944193(-5.58%)
     Total : 10000,
            - lower :      0 (0.00%)
            - normal:  10000 (100.00%)
            - higher:      0 (0.00%)
    $ ./a.out 
    average en ns = 1000098, peak = 2083044(+108.30%), base = 603560(-39.64%)
     Total : 10000,
            - lower :      1 (0.01%)
            - normal:   9997 (99.97%)
            - higher:      2 (0.02%)
    $ ./a.out 
    average en ns = 999998, peak = 1206658(+20.67%), base = 796835(-20.32%)
     Total : 10000,
            - lower :      2 (0.02%)
            - normal:   9997 (99.97%)
            - higher:      1 (0.01%)
    $ ./a.out 
    average en ns = 999997, peak = 1107952(+10.80%), base = 894580(-10.54%)
     Total : 10000,
            - lower :      1 (0.01%)
            - normal:   9998 (99.98%)
            - higher:      1 (0.01%)
    $ su 
    Mot de passe : 
    ####################
    # En Temps Réel
    ####################
    .../Linuxfr/TR# chrt 50 ./a.out 
    average en ns = 999997, peak = 1009857(+0.99%), base = 978338(-2.17%)
     Total : 10000,
            - lower :      0 (0.00%)
            - normal:  10000 (100.00%)
            - higher:      0 (0.00%)
    .../Linuxfr/TR# chrt 50 ./a.out 
    average en ns = 999997, peak = 1011019(+1.10%), base = 979650(-2.03%)
     Total : 10000,
            - lower :      0 (0.00%)
            - normal:  10000 (100.00%)
            - higher:      0 (0.00%)
    .../Linuxfr/TR# chrt 50 ./a.out 
    average en ns = 999997, peak = 1009547(+0.95%), base = 976955(-2.30%)
     Total : 10000,
            - lower :      0 (0.00%)
            - normal:  10000 (100.00%)
            - higher:      0 (0.00%)
    .../Linuxfr/TR# chrt 50 ./a.out 
    average en ns = 999997, peak = 1015868(+1.59%), base = 979951(-2.00%)
     Total : 10000,
            - lower :      0 (0.00%)
            - normal:  10000 (100.00%)
            - higher:      0 (0.00%)
    .../SSD/C++/Linuxfr/TR#

    Un essai supplémentaire sur 2 minutes (2 × 60 × 1000 = 120 000ms)

    $ ./a.out 
    average en ns = 999999, peak = 1425844(+42.58%), base = 585376(-41.46%)
     Total : 120000,
            - lower :     22 (0.02%)
            - normal: 119955 (99.96%)
            - higher:     23 (0.02%)
    $ su 
    Mot de passe : 
    .../Linuxfr/TR# chrt 50 ./a.out 
    average en ns = 999999, peak = 1030337(+3.03%), base = 968720(-3.13%)
     Total : 120000,
            - lower :      0 (0.00%)
            - normal: 120000 (100.00%)
            - higher:      0 (0.00%)
    # Ajout d'une affinité CPU
    .../Linuxfr/TR# taskset 1 chrt 50 ./a.out 
    average en ns = 999999, peak = 1272574(+27.26%), base = 727705(-27.23%)
     Total : 120000,
            - lower :     10 (0.01%)
            - normal: 119981 (99.98%)
            - higher:      9 (0.01%)
    .../C++/Linuxfr/TR#

    En forçant l’affinité sur un CPU, on augmente l’erreur… ça ma surpris. Il faudrait voir si on peut interdire un CPU à tout le monde sauf un processus ;-)
    Après, j'avais choisi le CPU 0, peut-être que en prenant le 3…

    Linuxfr/TR# taskset 4 chrt 50 ./a.out 
    average en ns = 999999, peak = 1018414(+1.84%), base = 971595(-2.84%)
     Total : 120000,
            - lower :      0 (0.00%)
            - normal: 120000 (100.00%)
            - higher:      0 (0.00%)
    .../Linuxfr/TR#

    C’est mieux… est-ce le hazard, ou les IT sont cablé sur le premier CPU sous Linux ?

    Voilà pour mes tests du soir.

    Bonne nuit

  • [^] # Re: Paramètre de timerfd_create

    Posté par  . En réponse au message probleme pour faire un timer précis de l'ordre de la milliseconde. Évalué à 2.

    Le get_clocktime aussi a le paramètre CLOCK_REALTIME.

    Sinon, tu peux utiliser la fonction setitimer. Par contre, c'est un peu plus complexe, il faut intercepter le signal SIGALARM, dans la fonction callback, tu libères un sémaphore (mutex). Et dans ton code, tu bloques le sémaphores.

    Autre chose, le temps réel, ça veut dire arrivé à temps… donc si malgré les erreurs tu arrives à finir ton algo avant la deadline, pourquoi chercher à réagir plus vite ? Néanmoins j’avoue que l’écart type d’erreur laisse songeur. ;-)

  • # Paramètre de timerfd_create

    Posté par  . En réponse au message probleme pour faire un timer précis de l'ordre de la milliseconde. Évalué à 4.

    Re,
    Dans le man timerfd_create,
    il y a ce passage :

           CLOCK_REALTIME
                  A settable system-wide real-time clock.
    
           CLOCK_MONOTONIC
                  A nonsettable monotonically increasing clock that measures time from some unspecified point in the past that does not change after system startup.
    
    

    As-tu essayé avec REALTIME ?

  • # Set affinity ?

    Posté par  . En réponse au message probleme pour faire un timer précis de l'ordre de la milliseconde. Évalué à 3.

    Hello,
    Tu n’indiques pas comment tu lances ton programme.
    En mode temps réel sur un noyau standard, la seule chose plus prioritaire, c’est le noyau.

    Une solution pourrait-être de forcer ton processus sur un cœur, et d’interdire ce cœur au noyau.

    Sinon, le réveil un peu plus tôt puis boucle active peut-être viable, et vraiment précis.