Julia, en este punto (mayo de 2019, Julia v1.1 con v1.2 a punto de salir) está bastante madura para la informática científica. La versión v1.0 significó el fin de la ruptura anual del código . Con eso, muchas bibliotecas de computación científica han tenido el tiempo de crecer simplemente sin interrupciones. Se puede encontrar una visión general de los paquetes de Julia en pkg.julialang.org .
Para la computación científica central, la biblioteca DifferentialEquations.jl para ecuaciones diferenciales (ODE, SDE, DAE, DDE, simulaciones de Gillespie, etc.), Flux.jl para redes neuronales y la biblioteca JuMP para programación matemática (optimización: lineal, cuadrática, programación de enteros mixtos, etc.) son tres de los pilares del ecosistema informático científico. La biblioteca de ecuaciones diferenciales en particular está mucho más desarrollada de lo que vería en otros idiomas, con un gran equipo de desarrollo que implementa características como integradores EPIRK , Runge-Kutta-Nystrom , ecuación diferencial de retardo rígido / diferencial-algebraico yintegradores de ecuaciones diferenciales estocásticas rígidas adaptables al tiempo , junto con un montón de otras ventajas como análisis de sensibilidad adjuntos , DSL de reacción química , Newton-Krylov sin matriz y compatibilidad completa con GPU (sin transferencia de datos), con entrenamiento de ecuaciones diferenciales neuronales , todo con resultados fantásticos de referencia (descargo de responsabilidad: soy el desarrollador principal).
Lo que es un poco alucinante sobre el ecosistema maduro de Julia es su composibilidad. Esencialmente, cuando alguien crea una función genérica de biblioteca como las de DifferentialEquations.jl, puede usar cualquier tipo AbstractArray / Number para generar un código nuevo sobre la marcha. Entonces, por ejemplo, hay una biblioteca para la propagación de errores ( Measurements.jl ) y cuando la pega en el solucionador ODE, automáticamente compila una nueva versión del solucionador ODE que realiza la propagación de errores sin muestreo de parámetros . Debido a esto, es posible que no encuentre algunas características documentadas porque el código de las características se genera solo, por lo que debe pensar más sobre la composición de la biblioteca.
Una de las formas en que la composición es más útil es en álgebra lineal. Los solucionadores de ODE, por ejemplo, le permiten especificar jac_prototype
, permitiéndole darle el tipo de Jacobian que se utilizará internamente. Por supuesto que hay cosas en la biblioteca estándar LineraAlgebra como Symmetric
y Tridiagonal
se puede usar aquí, pero teniendo en cuenta la utilidad de composibility en algoritmos de tipo genérico, la gente ha ido por ahora y construido bibliotecas enteras de tipo matriz. BandedMatrices.jl y BlockBandedMatrices.jl son bibliotecas que definen tipos de matriz con bandas (Block) que tienen lu
sobrecargas rápidas , lo que las convierte en una buena forma de acelerar la solución de discretizaciones rígidas de MOL de sistemas de ecuaciones diferenciales parciales. PDMats.jlpermite la especificación de matrices definidas positivas. Elemental.jl le permite definir un jacobiano disperso distribuido. CuArrays.jl define matrices en la GPU. Etc.
Entonces tienes todos tus tipos de números. Unitful.jl realiza la comprobación de unidades en tiempo de compilación, por lo que es una biblioteca de unidades sin gastos generales. DoubleFloats.jl es una biblioteca rápida de mayor precisión, junto con Quadmath.jl y ArbFloats.jl . ForwardDiff.jl es una biblioteca para la diferenciación automática en modo directo que utiliza aritmética de número dual. Y puedo seguir enumerando estos. Y sí, puede lanzarlos en bibliotecas de Julia suficientemente genéricas como DifferentialEquations.jl para compilar una versión específicamente optimizada para estos tipos de números. Incluso algo como ApproxFun.jlque funciona como objetos algebraicos (como Chebfun) funciona con este sistema genérico, permitiendo la especificación de PDE como ODE en escalares en un espacio de funciones.
Dadas las ventajas de la composibilidad y la forma en que los tipos se pueden usar para generar código nuevo y eficiente en las funciones genéricas de Julia, ha habido mucho trabajo para implementar implementaciones de la funcionalidad de la informática científica central en Julia pura. Optim.jl para optimización no lineal, NLsolve.jl para resolver sistemas no lineales, IterativeSolvers.jl para solucionadores iterativos de sistemas lineales y eigensystems, BlackBoxOptim.jl para optimización de caja negra, etc. Incluso la biblioteca de redes neuronales Flux.jl solo usa CuArrays. La compilación automática de código de jl en la GPU para sus capacidades de GPU. Esta composibilidad fue el núcleo de lo que creó cosas como ecuaciones diferenciales neuronales en DiffEqFlux.jl. Los lenguajes de programación probabilísticos como Turing.jl también son bastante maduros ahora y utilizan las mismas herramientas subyacentes.
Dado que las bibliotecas de Julia se basan fundamentalmente en herramientas de generación de código, no debería sorprendernos que haya muchas herramientas en torno a la generación de código. El sistema de difusión de Julia genera núcleos fusionados sobre la marcha que están sobrecargados por los tipos de matriz para proporcionar muchas de las características mencionadas anteriormente. CUDAnative.jl permite compilar el código de Julia en los núcleos de GPU. ModelingToolkit.jl elimina automáticamente el azúcar de los AST en un sistema simbólico para transformar el código matemático. Cassette.jlle permite "sobregrabar" la función existente de otra persona, utilizando reglas para cambiar su función antes del tiempo de compilación (por ejemplo: cambiar todas sus asignaciones de matriz a asignaciones de matriz estática y mover operaciones a la GPU). Se trata de herramientas más avanzadas (no espero que todos los que realizan computación científica tomen el control directo del compilador), pero así es como se están construyendo muchas de las herramientas de la próxima generación (o más bien, cómo se escriben las características por sí mismas).
En cuanto al paralelismo, mencioné las GPU, y Julia ha incorporado computación multiproceso y distribuida . El subprocesamiento múltiple de Julia muy pronto usará una arquitectura de tiempo de ejecución de tareas paralelas (PARTR) que permite la programación automática de subprocesos múltiples anidados . Si desea utilizar MPI, sólo puede utilizar MPI.jl . Y, por supuesto, la forma más fácil de usarlo es usar una configuración de tipo AbstractArray para usar el paralelismo en sus operaciones.
Julia también tiene el ecosistema subyacente básico que cabría esperar de un lenguaje de propósito general utilizado para aplicaciones científicas. Tiene el IDE de Juno con un depurador incorporado con puntos de interrupción , tiene Plots.jl para hacer todo tipo de tramas. Muchas herramientas específicas también son buenas, como Revise.jl actualiza automáticamente sus funciones / biblioteca cuando se guarda un archivo. Tiene sus DataFrames.jl , bibliotecas de estadísticas , etc. Una de las mejores bibliotecas es Distributions.jl, que le permite escribir algoritmos genéricos para la distribución (por ejemplo:rand(dist)
toma un número aleatorio de cualquier distribución que se haya pasado), y hay una gran cantidad de distribuciones univariadas y multivariadas (y, por supuesto, el envío ocurre en tiempo de compilación, lo que hace que todo sea tan rápido como codificar una función específica de la distribución). Hay un montón de herramientas de manejo de datos , servidores web , etc., lo que sea. En este punto, es lo suficientemente maduro como para que si hay algo científico básico y esperarías que exista, solo lo buscas en Google con .jl o Julia y aparecerá.
Luego hay algunas cosas a tener en cuenta en el horizonte. PackageCompiler está buscando construir binarios a partir de las bibliotecas de Julia, y ya tiene algunos éxitos pero necesita más desarrollo. Makie.jl es una biblioteca completa para el trazado acelerado por GPU con interactividad, y todavía necesita más trabajo, pero realmente está buscando convertirse en la principal biblioteca de trazado en Julia. Zygote.jl es una biblioteca de diferenciación automática de fuente a fuente que no tiene los problemas de rendimiento de un AD basado en rastreo (Flux's Tracker, PyTorch, Jax), y que está buscando funcionar en todos los códigos puros de Julia. Etc.
En conclusión, puede encontrar mucho movimiento en muchos lugares, pero en la mayoría de las áreas ya existe una biblioteca sólida y madura. Ya no está en un lugar donde preguntas "¿será adoptado?": Julia ha sido adoptada por suficientes personas (millones de descargas) que tiene el impulso para quedarse para siempre. Tiene una comunidad realmente agradable, por lo que si alguna vez quieres disparar la brisa y hablar sobre computación paralela o ecuaciones diferenciales numéricas, algunas de las mejores salas de chat para eso están en Julialang Slack . Si es un idioma que debe aprender es una pregunta personal, y si es el idioma adecuado para su proyecto es una pregunta técnica, y esas son diferentes. ¿Pero es un lenguaje que ha madurado y cuenta con el respaldo de un gran grupo consistente de desarrolladores? Eso parece ser un sí afirmativo.