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

Julia Discussion :

L'équipe de développement de Julia a publié la première version admissible de Julia 1.7


Sujet :

Julia

  1. #1
    Chroniqueur Actualités

    Homme Profil pro
    Dirigeant
    Inscrit en
    Juin 2016
    Messages
    3 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Bénin

    Informations professionnelles :
    Activité : Dirigeant
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juin 2016
    Messages : 3 160
    Points : 66 257
    Points
    66 257
    Par défaut L'équipe de développement de Julia a publié la première version admissible de Julia 1.7
    L'équipe de développement de Julia a publié la première version admissible de Julia 1.7
    mais elle n'est pas prête pour la production comme c'était le cas avec les précédentes RC

    Julia est un langage de programmation open source et un écosystème pour le calcul scientifique de haute performance (High performance computing). Il est mis à jour régulièrement et la publication de la version 1.6 remonte à mars dernier. La première version candidate (Release candidate - RC) de Julia 1.7 est désormais disponible pour les tests sur Linux, BSD, macOS et Windows. Elle est livrée avec plusieurs nouvelles fonctionnalités et quelques améliorations.

    Traditionnellement, les versions candidates de Julia sont proches du produit fini, et la plupart des utilisateurs qui souhaitent travailler avec les nouvelles fonctionnalités peuvent télécharger sans risque les binaires de Julia 1.7rc1 depuis le site de Julia dans la section "upcoming release". Cependant, l'équipe a déclaré que cette RC n'est pas "prête pour la production", ajoutant qu'elle accueille volontiers les rapports de bogues sur le traqueur de problèmes GitHub. Cet article décrit certains des changements et des nouvelles fonctionnalités du langage et de ses bibliothèques qui arrivent dans la version 1.7.

    Modifications de la syntaxe

    Comme pour toutes les modifications apportées au langage depuis la version 1.0, rien dans la version 1.7 ne devrait créer de rupture, sauf dans de rares cas. Cela dit, une nouvelle forme de concaténation de tableaux constitue l'un de ces rares cas. Auparavant, le point-virgule était utilisé pour la concaténation le long de la première dimension, et il conserve cette signification.

    Nom : ddfc1e00-6638-11e9-9b80-0fe7b9aedd72.png
Affichages : 2402
Taille : 725,0 Ko

    Mais les points-virgules répétés étaient traités comme un seul point-virgule, et ils ont désormais une nouvelle signification. Cela ne devrait casser que les programmes où un point-virgule répété est présent en tant que faute de frappe. Actuellement, l'opérateur point-virgule fonctionne comme suit :

    Code Julia : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    v1 = [1, 2, 3]
    v2 = [4, 5, 6]
    [v1; v2]   # results in [1, 2, 3, 4, 5, 6]

    Cependant, l'opérateur est étendu dans la version 1.7 : n points-virgules concatène maintenant le long de la nième dimension. De nouvelles dimensions sont créées si nécessaire. Par exemple, le résultat de [v1;; v2] est de créer une nouvelle deuxième dimension et de la joindre le long de celle-ci, produisant la matrice 3×2 :

    Code Julia : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
        1 4
        2 5
        3 6

    La nouvelle syntaxe des opérateurs nous permet de créer une troisième dimension de manière concise : [v1;;; v2] donne un tableau 3×1×2, avec :


    comme premier plan et :


    comme deuxième plan.

    Raffinements d'Unicode

    Julia continue à affiner son acceptation d'Unicode comme partie de la syntaxe. Depuis le début, Julia a permis à la juxtaposition de signifier la multiplication dans les cas où elle n'était pas ambiguë, donc si y = 7, alors 2y était 14. Elle a également permis aux symboles Unicode de racine carrée et cubique d'avoir leur signification mathématique familière. Vous pouvez maintenant combiner la juxtaposition avec ces symboles, comme l'illustre cette session REPL (read-execute-print-loop) :

    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
     
        julia> x = 64
        64
     
        julia> √x
        8.0
     
        julia> 3√x
        24.0
     
        julia> ∛x
        4.0
     
        julia> 3∛x
        12.0
    Les opérateurs infixes dans Julia sont simplement des fonctions qui peuvent être utilisées avec une syntaxe alternative. Par exemple, l'opérateur plus est en réalité une fonction : 3 + 4 est la même chose que +(3, 4). Le programmeur peut utiliser une grande variété de symboles Unicode comme noms de fonctions, mais en général ces noms ne peuvent pas être utilisés comme opérateurs infixes à moins que le langage ne leur accorde un traitement spécial. Julia 1.7 définit deux nouveaux symboles qui peuvent être utilisés de cette façon : et , qui peuvent être entrés dans le REPL en utilisant \Top et \Bot suivis par TAB.

    Ils ont la même précédence que les opérateurs de comparaison tels que >. Comme petit exemple de ce que l'on pourrait faire avec cela, la session REPL suivante définit une fonction qui teste si la valeur absolue de son premier argument est plus grande que la valeur absolue de son second :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
        julia> function(a, b)
                   return abs(a) > abs(b)
               end(generic function with 1 method)
     
        julia> ⫪(-8, 3)
        true
     
        julia> ⫪(-9, -12)
        false
     
        julia> -9-12
        false
    La dernière entrée montre que ce nouveau symbole peut être utilisé comme un opérateur infixe. En outre, la possibilité d'utiliser l'Unicode pour les noms et les opérateurs aide à faire en sorte que les programmes Julia ressemblent plus aux mathématiques. Cependant, Unicode est connu pour contenir des caractères distincts qui semblent identiques, une circonstance qui a conduit directement à une classe de vulnérabilités de noms de domaine. Avoir des caractères différents qui sont visuellement indiscernables peut évidemment être une source de bogues sérieux.

    Une façon pour Julia de prévenir ce problème est de s'assurer que de tels caractères visuellement identiques ont une sémantique identique. La version 1.7 définit trois points centrés Unicode, avec les points de code U+00b7, U+0387, et U+22c5 (ils ressemblent tous à ceci : -) comme fonctionnellement identiques. Ils peuvent être utilisés comme opérateurs infixes. La nouvelle version introduit également le signe moins Unicode (U+2212, ou \minus dans le REPL) pour signifier la même chose que le trait d'union ASCII que nous utilisons généralement pour la soustraction.

    Nouvelles fonctionnalités du REPL

    Selon l'équipe, le REPL dispose depuis longtemps d'une fonctionnalité appelée "mode collage", qui permet à l'utilisateur de coller une session d'exemple directement dans le REPL. Celui-ci élimine automatiquement les invites, reconnaît les entrées de l'utilisateur et fait généralement ce qu'il faut. Ce système a été étendu à tous les modes du REPL (pkg, shell et help) en plus du mode normal ; il change même de mode automatiquement en fonction de la chaîne d'invite dans le texte collé.

    Le mode help présente la documentation principalement en formatant les doctrines fournies par le programmeur au niveau de la fonction ou du module. Maintenant, dans le cas où un module n'a pas de docstring (ce qui n'est pas rare, surtout avec les petits paquets), help cherchera dans le répertoire du paquet un fichier README et imprimera celui qui est le plus proche du module en question. Dans tous les cas, il affichera la liste des noms exportés. Une fonctionnalité similaire existait dans certaines versions de Julia antérieures à la version 1.0, il s'agit donc plus d'une renaissance que de quelque chose de nouveau.

    Si l'utilisateur du REPL fait quelque chose qui retourne un grand tableau, le REPL imprimera une forme abrégée, en utilisant des ellipses pour indiquer les éléments sautés. Cependant, jusqu'à présent, le REPL affichait implacablement toute chaîne énorme qu'on lui demandait d'afficher. Dans la version 1.7 de Julia, les longues chaînes de caractères sont élidées de la même manière que les longs tableaux. Le REPL imprimera les trois premières lignes et demie environ, suivies d'une notation comme ⋯ 13554 bytes ⋯, puis les trois dernières lignes et demie. La fonction show() peut être utilisée pour voir la chaîne entière.

    Si l'utilisateur tente d'importer un paquet non installé, le REPL offre maintenant quelques conseils :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
        julia> using Example
        │ Le paquet Example n'a pas été trouvé, mais un paquet nommé Example est disponible dans un registre.
        │ registre. 
        │ Installer le paquet ?
        │ (@v1.7) pkg> add Example 
        └ (y/n) [y] :
    Répondre "y" suffit, alors qu'auparavant les utilisateurs devaient savoir entrer en mode paquetage et utiliser la commande add. Selon l'équipe, cela devrait être particulièrement utile pour les débutants.

    Changements dans la bibliothèque standard

    La fonction bien établie [C=Julia]deleteat!(v, i)[/B] mute le vecteur v en supprimant les éléments aux indices de la liste i. La nouvelle version de Julia ajoute sa jumelle, keepat!(v, i), qui est aussi une fonction mutante comme indiqué par la convention "!". Elle supprime effectivement les éléments pour tous les indices non présents dans i.

    Selon l'équipe, auparavant, rediriger à la fois l'erreur standard et la sortie standard dans une session Julia était un exercice de verbosité nécessitant quatre niveaux d'imbrication. Maintenant, il y a une nouvelle fonction de la bibliothèque qui rend cela beaucoup plus facile :

    Code Julia : Sélectionner tout - Visualiser dans une fenêtre à part
    redirect_stdio(p, stdout="stdout.txt", stderr="stderr.txt")

    Cette fonction appelle la fonction p() et redirige ses instructions d'impression vers les chemins fournis. Cette nouvelle fonction devrait être plus pratique lorsqu'elle est utilisée avec un bloc do, qui crée une fonction anonyme et la passe comme premier argument à un appel de fonction. De cette façon, vous pouvez inclure tout ce que vous voulez dans la fonction redirect_stdio() :

    Code Julia : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
        redirect_stdio(stdout="stdout.txt", stderr="stderr.txt") do
                   println("Julia a des nombres rationnels :")
                   println(1//5 + 2//5)
        end

    Ensuite, l'équipe note que la fonction replace() existante peut effectuer une seule substitution sur une chaîne de caractères. Elle a été améliorée pour accepter un nombre quelconque de motifs de remplacement, qui sont appliqués de gauche à droite et "simultanément". Les notes de version utilisent le terme "simultanément", ce qui signifie simplement que les sous-chaînes remplacées ne sont pas soumises à d'autres remplacements. Voici un exemple :

    Code Julia : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
         julia> s = "abc"
        "abc"
     
        julia> replace(s, "b" => "XX", "c" => "Z")
        "aXXZ"
     
        julia> replace(s, "c" => "Z", "Z" => "WWW")
        "abZ"
     
        julia> replace(s, "ab" => "x", "bc" => "y")
        "xc"

    Selon l'équipe, cette nouvelle fonction est à la fois pratique et nettement plus rapide que les techniques d'expression régulière auxquelles les gens ont généralement recours. Les deux derniers exemples montrent comment la fonction fonctionne en présence de plusieurs correspondances possibles.

    Par ailleurs, des améliorations significatives liées à la génération de nombres pseudo-aléatoires arrivent avec la version 1.7. Le générateur par défaut a été remplacé par un générateur plus performant en matière de temps, de consommation de mémoire et de propriétés statistiques. Le nouveau générateur rend également plus facile l'exécution de calculs parallèles reproductibles. Julia supporte plusieurs types de calculs parallèles et concurrents. La plupart des calculs parallèles dans Julia sont organisés autour de tâches, qui sont similaires aux coroutines dans d'autres langages.

    Le nouveau générateur de nombres aléatoires est "task local", ce qui signifie que, pendant un calcul parallèle, chaque tâche obtient sa propre instance du générateur. La même séquence de nombres pseudo-aléatoires sera générée sur chaque tâche, indépendamment de l'allocation aux threads. Cela permet de réaliser des simulations reproductibles à l'aide de nombres aléatoires, même avec des algorithmes qui créent dynamiquement des tâches pendant l'exécution.

    Selon l'équipe, cela introduit l'une des avancées les plus significatives arrivant avec la nouvelle version. Auparavant, dans un calcul multithread, une fois qu'une tâche était assignée à un thread, elle était bloquée sur ce thread pour toujours. La version 1.7 de Julia introduit la migration des tâches. Maintenant, le planificateur peut déplacer les tâches entre tous les threads disponibles, ce qui peut aider à équilibrer la charge et l'efficacité parallèle.

    Source : Julia 1.7rc1

    Et vous ?

    Que pensez-vous des nouveautés introduites par Julia 1.7rc1 ?

    Voir aussi

    La version 1.6 du langage Julia est disponible, elle apporte une réduction de la latence des compilateurs et supprime les recompilations inutiles

    Le langage de programmation Julia serait capable de lire les fichiers CSV dix à vingt fois plus vite que Python et R, selon une étude

    Le langage de programmation Julia gagne de plus en plus en popularité au sein de la communauté scientifique depuis janvier 2018

    Les raisons de l'adoption accélérée du langage Julia : un langage polyvalent, mais plus scientifique, supporte l'introspection et la métaprogrammation, selon Lee Phillips
    Contribuez au club : corrections, suggestions, critiques, ... Contactez le service news et Rédigez des actualités

  2. #2
    Chroniqueur Actualités
    Avatar de Bruno
    Homme Profil pro
    Rédacteur technique
    Inscrit en
    Mai 2019
    Messages
    1 850
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Cameroun

    Informations professionnelles :
    Activité : Rédacteur technique
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Mai 2019
    Messages : 1 850
    Points : 36 371
    Points
    36 371
    Par défaut La version 1.7 du langage Julia est disponible, elle apporte l’installation automatique de paquets
    La version 1.7 du langage Julia est disponible, elle apporte l’installation automatique de paquets,
    un nouveau format du manifeste et l’ajout des atomiques comme caractéristique du langage

    L'équipe de développement de Julia a publié la première version admissible de Julia 1.7 en octobre de cette année. Un mois plus tard, les responsables du langage Julia ont annoncé la disponibilité de Julia 1.7. « Après 4 betas et 3 release candidates, la version 1.7 de Julia est enfin disponible. Nous voudrions remercier tous les contributeurs à cette version (plus de 79 personnes) et tous les testeurs qui ont aidé à trouver les régressions et les problèmes dans les préversions », a déclaré l’équipe de développement du langage. Cette version corrige les erreurs de synchronisation, affine le support de l'ordonnancement des charges de travail sur plusieurs threads, rend le générateur de nombres aléatoires par défaut plus convivial pour les threads, et ajouté les atomiques comme caractéristique du langage primitif.

    Julia est un langage de programmation open source et un écosystème pour le calcul scientifique de haute performance. Conçu par des chercheurs du MIT en 2009 et dévoilé pour la première fois au grand public en 2012, il est doté d’une syntaxe familière aux utilisateurs d'autres environnements de développement similaires. Julia connaît une croissance fulgurante depuis sa sortie et certains vont même jusqu’à dire qu’il s’agit du langage idéal pour le calcul scientifique, la science des données et les projets de recherche. Le langage s'est popularisé lorsque le projet est devenu open source en 2012. Il est actuellement disponible sous licence MIT.

    Nom : julia.jpg
Affichages : 6919
Taille : 2,5 Ko

    À la base, ses concepteurs voulaient un langage avec une licence libre et renfermant de nombreux avantages surtout pour la communauté scientifique. « Nous voulons un langage open source, avec une licence libre. Nous voulons un langage qui associe la rapidité de C et le dynamisme de Ruby. En fait, nous voulons un langage homoïconique, avec de vraies macros comme Lisp et avec une notation mathématique évidente et familière comme MATLAB. Nous voulons quelque chose d’aussi utilisable pour la programmation générale que Python, aussi facile pour les statistiques que R, aussi naturel pour la gestion de chaîne de caractères que Perl, aussi puissant pour l’algèbre linéaire que Matlab et aussi bien pour lier des programmes que le shell. Nous voulons qu’il soit à la fois interactif et compilé », avaient-ils déclaré en 2012.

    La plupart des versions de Julia sont programmées dans le temps et ne sont donc pas planifiées autour de fonctionnalités spécifiques. Voici, ci-dessous, quelques améliorations apportées à Julia dans la version 1.7 :

    Générateur de nombres aléatoires par défaut

    Depuis sa toute première version, Julia utilisait le populaire algorithme Mersenne Twister comme générateur de nombres aléatoires par défaut. « Nous savions que nous devions réévaluer ce choix à un moment donné, mais cela ne semblait pas particulièrement urgent jusqu'à ce que le programmeur Chet Hega nous fasse remarquer qu'en changeant d'algorithme nous pouvions non seulement obtenir une accélération significative, mais aussi rendre les flux de nombres aléatoires reproductibles dans les programmes multithreads », révèle l’équipe de développement de Julia.

    Développé par Makoto Matsumoto et Takuji Nishimura en 1997, l’algorithme Mersenne Twister (MT) est basé sur un twisted generalised shift feedback register (TGSFR), un type particulier de registre à décalage et rétroaction et tient son nom d’un nombre premier de Mersenne. Il existe au moins deux variantes majeures, la plus répandue étant MT 19937, utilisant le nombre premier de Mersenne 219937-1 et présente les propriétés suivantes :

    • sa période est de 219937-1 ;
    • il est plus rapide que la plupart des autres générateurs ;
    • il est uniformément distribué sur un grand nombre de dimensions (623 pour les nombres de 32 bits) ;
    • il est aléatoire quel que soit le poids du bit considéré, suivant les tests Diehard, mais échoue systématiquement sur deux des tests BigCrush de TestU01.

    Mersenne Twister est célèbre pour avoir une période exceptionnellement longue (219937-1), mais cela nécessite un état de taille correspondante, et n'est pas vraiment nécessaire pour toute application pratique. L’équipe Julia a également utilisé des états de générateur de nombres aléatoires locaux pour la sécurité des threads, ce qui apporte un peu de surcharge et rend les flux aléatoires dépendants de la planification des tâches.

    La proposition de Chet a profité de l'état beaucoup plus petit de la famille Xoshiro256 des de générateurs de nombres aléatoires pour mettre un état dans chaque tâche, et le forker à chaque création de tâche. Ainsi, les nombres aléatoires ne dépendent que de la structure de création des tâches d'un programme, et non du programme d'exécution parallèle. « Il a fallu un peu de débat pour que nous soyons tous à l'aise avec l'idée de dépenser de précieux octets d'objets Task de cette manière, mais nous sommes de grands fans de la reproductibilité et la proposition a donc été finalement adoptée », souligne L’équipe de développement de Julia.

    Gestionnaire de paquets

    Avec la version 1.7 de Julia, si un paquet existe dans un registre mais n'est pas installé, une installation automatique est maintenant proposée lorsqu'un chargement de paquet est tenté dans le shell interactif de niveau supérieur ou de langage. Voici, cidessous, quelques paquets dans l'écosystème construire sur cette fondation pour fournir des abstractions thread-safe :

    • tkf/ThreadsX.jl : Des versions parallélisées de certaines fonctions de Base ;
    • JuliaConcurrent/ConcurrentCollections.jl : files d'attente et dictionnaires pour l'état partagé ;
    • JuliaActors/Actors.jl : des modèles pour rendre la concurrence facile à comprendre et à raisonner ;
    • JuliaFolds/FLoops.jl : génère une itération séquentielle et parallèle générique rapide sur des collections complexes ;
    • JuliaFolds/Transducers.jl : parallélismes basés sur les threads (foldxt) et les processus (foldxd) avec la même API composable ; i.e. les transducteurs.

    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
    julia> using Foo
    ERROR: ArgumentError: Package Foo not found in current path:
    - Run `import Pkg; Pkg.add("Foo")` to install the Foo package.
     
    Stacktrace:
     [1] require(into::Module, mod::Symbol)
       @ Base ./loading.jl:871
     
    (@1.6) pkg> add Foo
    ...
     
    julia> using Foo
     
    julia> Foo
    Foo

    peut désormais être réalisé avec seulement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    julia> using Foo
     │ Package Foo not found, but a package named Foo is available from a registry.
     │ Install package?
     │   (@v1.7) pkg> add Foo
     └ (y/n) [y]: y
     ...
    julia> Foo
    Foo

    Par défaut, le paquet sera installé dans l'environnement actif actuel, sélectionné par y ou par une simple pression sur la touche retour.

    Nouveau format de manifeste

    Chaque fois qu'un utilisateur ajoute un paquetage dans Julia, le gestionnaire de paquetage (Pkg) écrit un fichier TOML appelé manifest avec la version exacte de toutes les dépendances de ce paquetage. Différentes versions de paquetage peuvent être compatibles avec différentes versions de Julia et la sortie du resolver(l'algorithme qui calcule un ensemble de versions compatibles pour tous les paquetages et dépendances dans le projet) dépend donc de la version de Julia. Il n'est donc pas recommandé d'utiliser un manifeste créé dans une version de Julia avec une autre version de Julia. Il serait pratique que Pkg puisse vous avertir lorsque cela se produit.

    Afin d'émettre un tel avertissement, Pkg aurait besoin de savoir quelle version de Julia a généré un manifeste donné. Cependant, le format actuel (ou schéma) du manifeste rend difficile l'ajout d'une telle information. La raison en est que le format est tel que les clés de premier niveau dans le fichier TOML sont les noms des paquets des dépendances. Cela signifie qu'il n'y a pas de place pour ajouter quelque chose comme une entrée julia_version. Bien sûr, il serait possible de créer une entrée spéciale avec ce nom (en supposant que personne ne nommera un paquet exactement julia_version) mais il serait beaucoup plus agréable de ne pas avoir la même entrée "structurelle" faisant référence à deux choses complètement différentes.

    Dans la version 1.7, le format du manifeste a été modifié afin que toutes les dépendances soient placées sous une clé [deps] commune. Cela libère l'espace de nom global pour permettre l'ajout d'une entrée julia_version. Cela ouvre également la possibilité d'ajouter de futures données utiles au manifeste. Pkg conservera également le format d'un manifeste existant, de sorte que seuls les nouveaux manifestes auront le nouveau format de manifeste à l'avenir.

    Amélioration des performances pour la gestion des registres sur Windows et les systèmes de fichiers distribués

    Suite à quelques plaintes concernant la vitesse du gestionnaire de paquets Julia (Pkg) sous Windows et sur les systèmes de fichiers réseau (NFS), l’équipe de développement à améliorer la situation dans Julia 1.7. Ce qui est commun entre ces systèmes est que ce sont des systèmes où les opérations sur les fichiers ont tendance à être significativement plus coûteuses.

    Le registre général est le registre par défaut que Pkg utilise pour rechercher des informations sur les paquets. Il est structuré de telle sorte que chaque paquet a quatre fichiers TOML différents. Au moment de la rédaction de cet article, le registre général contient 5761 paquets, ce qui signifie qu'il contient environ 23 000 fichiers. Il y a deux façons pour Pkg d'obtenir des mises à jour pour un registre, soit via le protocole git, soit via HTTPS en utilisant Pkg Server, qui est un moyen communautaire d'héberger des paquets et des registres où le registre est téléchargé sous la forme d'une archive compressée.

    Selon certains rapports, sous Windows, le téléchargement initial du registre général prendrait plusieurs minutes, alors que sous Linux et macOS, il ne prend que quelques secondes. La cause principale de ce ralentissement a été diagnostiquée comme étant Windows Defender, qui provoque des ralentissements lors de la fermeture des fichiers, ce qui est très difficile lors de l'extraction de 23 000 petits fichiers. Selon l’équipe Julia, la communauté Rust serait confrontée à un problème similaire lorsqu'il s'agit de décompresser sa documentation.

    Étant donné que Julia est fournie avec p7zip et avec la bibliothèque standard Tar.jl, au lieu d'utiliser un pool de threads pour accélérer la fermeture des fichiers, l’équipe a décidé de prendre une autre voie. Il est possible de lire directement le fichier compressé en mémoire sans matérialiser aucun fichier. En faisant cela, le problème de la matérialisation des fichiers est oublié ce qui améliore significativement les performances du registre sous Windows, NFS et autres systèmes de fichiers distribués comme ceux typiquement utilisés dans les systèmes HPC.

    À titre d'exemple, voici, l'effet sur un système propre lors de l'installation du paquetage Example à partir de zéro. D'abord, avec les anciennes méthodes de décompression de tous les fichiers (~30 secondes) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    julia> @time Pkg.add("Example")
      Installing known registries into `C:\Users\Kristoffer Carlsson\.julia`
       Resolving package versions...
       Installed Example ─ v0.5.3
     29.509835 seconds (4.81 M allocations: 320.162 MiB, 0.81% gc time)

    Et ensuite avec la nouvelle méthode qui consiste à lire le registre compressé directement en mémoire (~2 secondes) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    julia> @time Pkg.add("Example")
      Installing known registries into `C:\Users\Kristoffer Carlsson\.julia`
       Resolving package versions...
       Installed Example ─ v0.5.3
      1.953665 seconds (2.35 M allocations: 164.310 MiB, 1.96% gc time)


    Meilleure impression du chemin pour les bibliothèques standard dans les erreurs

    Le chemin d'accès à une méthode Julia est défini lors de la définition de la méthode. Cela signifie que lorsque l'on utilise une installation de Julia qui a été compilée ailleurs (par exemple les installations officielles de Julia) les chemins pour les méthodes livrées avec Julia se référeront à un serveur de cloud qui a fait la compilation. Comme exemple, ci-dessous le chemin vers le buildworker qui a compilé Julia est indiqué :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    julia> using Random; Random.seed!("seed")
    ERROR: MethodError: no method matching seed!(::String)
    Closest candidates are:
      seed!() at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.6/Random/src/RNGs.jl:362
    ...

    Certains éditeurs permettent d'ouvrir des fichiers en cliquant sur les chemins dans le terminal, mais cela ne fonctionne pas dans des cas comme celui-ci. Dans la version 1.7, cela a été corrigé afin d'imprimer les chemins qui sont valides localement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    julia> using Random; Random.seed!("seed")
    ERROR: MethodError: no method matching seed!(::String)
    Closest candidates are:
      seed!() at ~/Downloads/julia/share/julia/stdlib/v1.7/Random/src/RNGs.jl:387
    ...


    libblastrampoline + MKL.jl

    Julia v1.7 introduit une nouvelle bibliothèque de démuxage BLAS appelée libblastrampoline (LBT), qui fournit un moyen flexible et efficace de changer de bibliothèque BLAS au moment de l'exécution. Comme l'API BLAS/LAPACK est "pure" (c'est-à-dire que chaque invocation BLAS/LAPACK est séparée des autres ; il n'y a pas de transfert d'état d'un appel d'API à l'autre), il est possible de changer de backend BLAS pour répondre à un appel d'API client particulier, comme un appel DGEMM pour une multiplication Matrice-Matrice Float64.

    Cette absence d'état permet de passer facilement d'un backend BLAS à un autre sans avoir à modifier le code client, et en combinant cela avec une implémentation flexible du wrapper, il est possible de fournir une API unique et cohérente qui s'adapte automatiquement à une variété de fournisseurs BLAS/LAPACK sur toutes les plateformes que Julia supporte.

    Le wrapper lui-même consiste en des routines d'assemblage pour sauter à un pointeur de fonction stockée, en utilisant les mêmes morceaux d'assemblage que la Table de Liaison de Procédure (PLT) utilise dans chaque bibliothèque dynamique du système d'exploitation. Ces petites routines d'assemblage efficaces agissent comme un "trampoline", faisant rebondir un appel vers sa véritable destination dans OpenBLAS, MKL, etc...

    L'histoire ne s'arrête cependant pas à l'écriture de routines de transfert performantes ; l’équipe de developement de Julia doit également faire face à la complexité des différentes ABI BLAS/LAPACK. La différence d'ABI la plus visible pour l'utilisateur est celle des bibliothèques BLAS qui sont construites pour utiliser des indices 64 bits (ILP64) plutôt que des indices 32 bits (LP64). Mélanger les bibliothèques clientes qui passent un index à un backend BLAS qui attend des index d'une largeur de bit différente peut avoir des conséquences désastreuses, depuis le calcul silencieux d'un résultat erroné jusqu'à la défaillance pure et simple.

    Le projet Julia est depuis longtemps partisan de nommer ces deux ABI séparément, en suffixant les symboles BLAS ILP64 pour les différencier du reste du monde et ainsi éviter une confusion fatale, en renommant par exemple dgemm_ en dgemm_64_ notons que le soulignement de fin est une convention gfortran que Julia suit pour maintenir la compatibilité ABI.

    Pour gérer cela, LBT exporte deux jeux de symboles ; un jeu LP64 avec les noms que la plupart des logiciels attendent, et un jeu ILP64 avec les noms que beaucoup de logiciels dans le monde de Julia attendent déjà (par exemple suffixés avec 64_). En interne, LBT maintient des tables de transfert pour les fonctions exportées LP64 et ILP64 séparément, permettant un grand degré de flexibilité dans la gestion des backends BLAS/LAPACK.

    Une autre différence ABI possible est la dénomination des symboles eux-mêmes (dgemm, dgemm_, dgemm__, _dgemm_ et myblas_dgemm sont tous des noms de symboles BLAS qui ont été vus dans la nature) et donc LBT effectue une recherche simple sur les différentes dénominations possibles lors du chargement d'un backend BLAS/LAPACK.

    Le backend Accelerate d'Apple utilise une ABI légèrement différente de l'ABI par défaut de gfortran en ce qui concerne le passage d'arguments de caractères (comme le paramètre 'U' de certaines routines LAPACK marquant quelque chose comme une matrice triangulaire supérieure), et LBT convertit automatiquement vers/depuis cette autre ABI. Enfin, LBT gère certaines API spécifiques au fournisseur, comme le réglage du nombre de threads des bibliothèques dorsales, via un point d'entrée unique.

    La plupart des utilisateurs n'auront jamais besoin d'interagir directement avec LBT, cependant, pour ceux qui sont intéressés, il est recommendé de regarder les métadonnées que LBT suit sur les bibliothèques qui sont actuellement chargées :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    julia> LinearAlgebra.BLAS.lbt_get_config()
    LinearAlgebra.BLAS.LBTConfig
    Libraries:
    └ [ILP64] libopenblas64_.so

    Cela montre qu'une seule bibliothèque ILP64 est actuellement chargée, et cette bibliothèque est libopenblas64_.so. Le chargement d'une bibliothèque LP64 (telle que celle fournie par OpenBLAS32_jll) change quelque peu le résultat :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    julia> LinearAlgebra.BLAS.lbt_forward(OpenBLAS32_jll.libopenblas_path)
    4860
     
    julia> LinearAlgebra.BLAS.lbt_get_config()
    LinearAlgebra.BLAS.LBTConfig
    Libraries:
    ├ [ILP64] libopenblas64_.so
    └ [ LP64] libopenblas.so

    Le chargement de MKL fait basculer instantanément la configuration vers l'utilisation de MKL, et toutes les invocations BLAS à partir de ce moment seront effectuées par les noyaux écrits par Intel à la place. Il est possible de créer des configurations vraiment complexes (par exemple en superposant une bibliothèque qui ne fournit que quelques symboles BLAS à OpenBLAS qui peut fournir le reste) mais pour la plupart des utilisateurs l'impact principal sera simplement qu'il n'est plus nécessaire de recompiler Julia quand vous voulez utiliser une autre bibliothèque BLAS.

    Notons que le choix de Julia d'utiliser ILP64 ou LP64 est toujours une décision de compilation, et que même si l’utilisateur charge OpenBLAS32_jll pour fournir des symboles LP64, Julia utilisera toujours ILP64 sur les plateformes 64-bit par défaut. La raison principale pour supporter LP64 sur les plateformes 64 bits est de fournir les symboles pour d'autres programmes qui peuvent être liés dans l'espace de noms de Julia, comme l'utilisation de PyCall pour charger numpy.

    Amélioration des inférences

    Cette version vient avec de nombreuses améliorations de l'inférence de type. Avec ces améliorations, Julia 1.7 déduira plus "intelligemment" les types du programme et améliorera les performances. Plus particulièrement, 1.7 peut propager les contraintes de type qui peuvent être dérivées des conditions isa et === de manière inter-procédurale (c'est-à-dire à travers tous les appels de fonction). Certains programmes Julia sont écrits de manière à ce que leur comportement change en fonction des types d'exécution, et de tels programmes peuvent s'exécuter beaucoup plus rapidement grâce au gain d'inferrabilité de cette amélioration. Par exemple, maintenant il n'y a pas de différence d'inférrabilité entre x === nothing et isnothing(x) (et donc vous n'avez plus besoin de vous rappeler cette astuce de performance) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    julia> code_typed((Union{Nothing,Int},); optimize=false) do x
               return isnothing(x) ? 0 : x
           end |> first

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    --- v1.6
    +++ v1.7
    @@ -1,6 +1,6 @@
     CodeInfo(
     1 ─ %1 = Main.isnothing(x)::Bool
     └──      goto #3 if not %1
     2return 0
    -3return x
    -) => Union{Nothing, Int64}
    +3return x::Int64
    +) => Int64

    Bien entendu, cette propagation de contraintes interprocédurales fonctionne pour des fonctions génériques arbitraires :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    julia> ispositive(a) = isa(a, Number) && a > 0;
    julia> code_typed((Union{Nothing,Int},); optimize=false) do x
               return ispositive(x) ? x : 0
           end |> first

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    --- v1.6
    +++ v1.7
    @@ -1,6 +1,6 @@
     CodeInfo(
     1 ─ %1 = Main.ispositive(x)::Bool
     └──      goto #3 if not %1
    -2return x
    +2return x::Int64
     3return 0
    -) => Union{Nothing, Int64}
    +) => Int64

    Une autre amélioration remarquable est la propagation plus rapide des constantes. Julia 1.7 peut remplacer plus de calculs d'exécution par des constantes pré-calculées, et éliminer le code mort en résolvant les branches conditionnelles au moment de la compilation. Par exemple, dans 1.7, les calculs de fonctions spéciales peuvent être entièrement repliés au moment de la compilation :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    julia> code_typed((Int,)) do n
               n + sin(sum(sincos(42))) # no runtime computation of `sum(sincos(42))` in 1.7!
           end |> first

    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
    --- v1.6
    +++ v1.7
    @@ -1,32 +1,5 @@
     CodeInfo(
    -1 ─ %1  = Base.muladd_float(0.16933292771007588, 2.7557313707070068e-6, -0.0001984126982985795)::Float64
    -│   %2  = Base.muladd_float(0.16933292771007588, %1, 0.00833333333332249)::Float64
    -│   %3  = Base.muladd_float(0.16933292771007588, 1.58969099521155e-10, -2.5050760253406863e-8)::Float64
    -│   ... many runtime computations ...
    -│   %27 = invoke Main.sin(%26::Float64)::Float64
    -│   %28 = Base.sitofp(Float64, n)::Float64
    -│   %29 = Base.add_float(%28, %27)::Float64
    -└──       return %29
    +1 ─ %1 = Base.sitofp(Float64, n)::Float64
    +│   %2 = Base.add_float(%1, -0.9678422808766897)::Float64
    +└──      return %2
     ) => Float64


    Les littéraux des tableaux multidimensionnels

    Les tableaux multidimensionnels, notamment ceux à trois dimensions ou plus, sont des constructions utiles pour la programmation scientifique et l'apprentissage automatique. Cependant, les langages de programmation n'ont pas rendu facile la création et le travail avec eux. Julia a eu des méthodes de première classe pour travailler avec des tableaux multidimensionnels. Cependant, jusqu'à la version 1.6, il n'y avait aucun moyen de les créer avec une syntaxe pure et un coût d'allocation minimal. Vous deviez d'abord allouer des tableaux à 1 ou 2 dimensions et ensuite reshape(), ou cat() les rassembler une dimension à la fois. Il était également difficile de créer une matrice à une colonne et des tableaux à un seul élément de dimension supérieure.

    Avec Julia v1.7, nous avons ajouté une syntaxe pour vous permettre d'écrire un littéral pour les tableaux multidimensionnels. Cette nouvelle syntaxe rend les tableaux multidimensionnels beaucoup plus faciles à manipuler dans Julia qu'ils ne l'étaient auparavant, et nous pensons qu'elle se compare favorablement avec la création de tableaux multidimensionnels dans d'autres langages :

    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
    Julia v1.7:
    [1 2 ; 3 4 ;;; 5 6 ; 7 8]
    or
    [1 ; 3 ;; 2 ; 4 ;;; 5 ; 7 ;; 6 ; 8]
     
    Python with Numpy:
    import numpy as np
    np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])
     
    MATLAB:
    A = [1 2; 3 4]
    A(:,:,2) = [5 6; 7 8]
     
    R:
    array(c(1, 3, 2, 4, 5, 7, 6, 8), dim = c(2, 2, 2))

    La syntaxe est une simple extension de la syntaxe actuelle : un point-virgule supplémentaire == une dimension supplémentaire :

    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
    29
    30
    31
    julia> [1 2 ; 3 4]
    2×2 Matrix{Int64}:
     1  2
     3  4
     
    julia> [1 2 ;;; 3 4]
    1×2×2 Array{Int64, 3}:
    [:, :, 1] =
     1  2
     
    [:, :, 2] =
     3  4
     
    julia> [1 2 ;;;; 3 4]
    1×2×1×2 Array{Int64, 4}:
    [:, :, 1, 1] =
     1  2
     
    [:, :, 1, 2] =
     3  4
     
    julia> using BenchmarkTools
     
    julia> @btime [1 2 ;;;; 3 4];
      44.838 ns (2 allocations: 160 bytes)
     
    julia (v1.6)> @btime cat([1 2], [3 4], dims = 4); # clear, but slow, and gets worse with more dimensions
      1.380 μs (23 allocations: 1.05 KiB)
     
    julia (v1.6)> @btime reshape([1; 2; 3; 4], (1, 2, 1, 2)); # fast, but intent less clear
      65.884 ns (2 allocations: 192 bytes)

    Il s'agit d'une amélioration substantielle des performances pour cette opération de base, et le différentiel s'améliore grandement avec l'augmentation des dimensions. Pour faciliter la lecture d'une expression de tableau plus grande, les sauts de ligne sont bien sûr tolérés :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    julia> [ 1 2
             3 4
             ;;;
             5 6
             7 8 ]
    2×2×2 Array{Int64, 3}:
    [:, :, 1] =
     1  2
     3  4
     
    [:, :, 2] =
     5  6
     7  8

    Cette syntaxe permet également d'écrire des tableaux dans l'ordre des colonnes plutôt que dans celui des lignes, en utilisant des ; ; à la place des espaces pour les lignes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    julia> [1 ; 2 ;; 3 ; 4 ;;; 5 ; 6 ;; 7 ; 8]
    2×2×2 Array{Int64, 3}:
    [:, :, 1] =
     1  3
     2  4
     
    [:, :, 2] =
     5  7
     6  8

    Les points-virgules inférieurs sont prioritaires par rapport aux points-virgules supérieurs, de sorte que l'expression ci-dessus est équivalente à :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    julia> [[[1 ; 2] ;; [3 ; 4]] ;;; [[5 ; 6] ;; [7 ; 8]]];


    Support pour Apple Silicon

    Julia 1.7 est aussi la première version qui fonctionne sur Apple Silicon, par exemple la famille M1 de CPUs ARM. La planification de cette fonctionnalité a commencé il y a plus d'un an, peu après l'annonce par Apple de ses nouvelles puces. Les processeurs Apple Silicon sont des processeurs SoC et SiP utilisant l'architecture ARM conçus par Apple. Ils sont la base des appareils iPhone, iPad et Apple Watch ainsi que de produits tels que le HomePod, l'iPod touch et l'Apple TV.

    La route vers un support pour Apple Silicon a été initialement compliquée par l'absence d'un compilateur Fortran pour la nouvelle plateforme, qui est nécessaire pour construire l'une des dépendances binaires de Julia, à savoir OpenBLAS. Bien sûr, Julia n'était pas le seul projet open source pour le calcul numérique affecté par ce problème, qui a finalement été résolu par la disponibilité d'un fork de GCC.

    Bien que l’équipe de développement de Julia soit maintenant en mesure de fournir des binaires Julia préconstruits pour cette plateforme, son support est actuellement considéré comme de niveau 3, ce qui signifie qu'il est expérimental et que des bugs spécifiques sont à prévoir. L'enquête Julia User & Developer Survey 2021 a montré que 5 % des utilisateurs de Julia utilisaient déjà Julia sur cette plateforme avant qu'une version stable officielle ne soit publiée pour elle.
    L’équipe de developpement de Julia travail déjà sur la version 1.8 du langage de programmation.

    Source : Julia

    Et vous ?

    Entre Julia, Python et R, quel langage utilisez-vous pour la science des données ?

    Que pensez-vous de Julia ?

    Quelle amélioration de la version 1.7 vous interesse le plus ?

    Voir aussi :

    Le langage de programmation Julia serait capable de lire les fichiers CSV dix à vingt fois plus vite que Python et R, selon une étude

    La version 1.6 du langage Julia est disponible, elle apporte une réduction de la latence des compilateurs et supprime les recompilations inutiles

    L'équipe de développement de Julia a publié la première version admissible de Julia 1.7, mais elle n'est pas prête pour la production comme c'était le cas avec les précédentes RC

    Les raisons de l'adoption accélérée du langage Julia : un langage polyvalent, mais plus scientifique, supporte l'introspection et la métaprogrammation, selon Lee Phillips
    Contribuez au club : corrections, suggestions, critiques, ... Contactez le service news et Rédigez des actualités

  3. #3
    Invité
    Invité(e)
    Par défaut
    Espérons que la compilation statique soit bientôt supportée par Julia. Les possibilités du langage s'en trouveraient décuplées.

Discussions similaires

  1. Réponses: 1
    Dernier message: 15/03/2021, 22h45
  2. [Partenaire] Recherche équipe de développement concept WEB
    Par Lycan dans le forum Autres
    Réponses: 0
    Dernier message: 16/02/2009, 13h33
  3. Réponses: 0
    Dernier message: 24/11/2008, 18h05
  4. Réponses: 5
    Dernier message: 21/08/2007, 12h17
  5. Réponses: 8
    Dernier message: 29/05/2006, 07h50

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