Cos'è Julia? Un nuovo approccio al calcolo numerico

Julia è un linguaggio di programmazione dinamico open source, di alto livello e ad alte prestazioni per il calcolo numerico. Ha la comodità di sviluppo di un linguaggio dinamico con le prestazioni di un linguaggio compilato staticamente tipizzato, grazie in parte a un compilatore JIT basato su LLVM che genera codice macchina nativo, e in parte a un design che implementa la stabilità del tipo attraverso la specializzazione tramite più dispatch, che semplifica la compilazione di codice efficiente.

Nel post sul blog che annunciava il rilascio iniziale di Julia nel 2012, gli autori del linguaggio - Jeff Bezanson, Stefan Karpinski, Viral Shah e Alan Edelman - hanno dichiarato di aver trascorso tre anni a creare Julia perché erano avidi . Erano stanchi dei compromessi tra Matlab, Lisp, Python, Ruby, Perl, Mathematica, R e C e volevano un unico linguaggio che fosse buono per il calcolo scientifico, l'apprendimento automatico, il data mining, l'algebra lineare su larga scala , calcolo parallelo e calcolo distribuito.

Per chi è Julia? Oltre ad essere attraente per ricercatori e ingegneri, Julia è anche attraente per i data scientist e per gli analisti e i quanti finanziari.

I designer del linguaggio e altri due hanno fondato Julia Computing nel luglio 2015 per "sviluppare prodotti che rendano Julia facile da usare, facile da distribuire e facile da scalare". Al momento della stesura di questo documento, l'azienda ha uno staff di 28 persone e clienti che vanno dai laboratori nazionali alle banche, dagli economisti ai ricercatori di veicoli autonomi. Oltre a mantenere i repository open source Julia su GitHub, Julia Computing offre prodotti commerciali, tra cui JuliaPro, disponibile sia in versione gratuita che a pagamento.

Perché Julia?

Julia "mira a creare una combinazione senza precedenti di facilità d'uso, potenza ed efficienza in un unico linguaggio". Per la questione dell'efficienza, si consideri il grafico seguente:

Julia Computing

Benchmark di Julia

Quello che stiamo vedendo qui è che il codice Julia può essere più veloce di C per alcuni tipi di operazioni e non più di alcune volte più lento di C per altri. Confrontalo con, diciamo, R, che può essere quasi 1.000 volte più lento di C per alcune operazioni.

Notare che uno dei test più lenti per Julia è la ricorsione di Fibonacci; questo perché a Julia attualmente manca l'ottimizzazione della ricorsione della coda. La ricorsione è intrinsecamente più lenta del ciclo. Per i veri programmi Julia che vuoi eseguire in produzione, ti consigliamo di implementare la forma di ciclo (iterazione) di tali algoritmi.

Compilazione Julia JIT

C'è un costo per l'approccio del compilatore JIT (just-in-time) rispetto a un interprete puro: il compilatore deve analizzare il codice sorgente e generare codice macchina prima che il codice possa essere eseguito. Ciò può significare un notevole tempo di avvio per i programmi Julia la prima volta che ogni funzione e macro viene eseguita in una sessione. Quindi, nello screenshot qui sotto, vediamo che la seconda volta che generiamo un milione di numeri in virgola mobile casuali, il tempo impiegato è un ordine di grandezza inferiore a quello della prima esecuzione. Sia la @timemacro che la rand()funzione dovevano essere compilate la prima volta tramite il codice, perché le librerie Julia sono scritte in Julia.

julia> @time rand (10 ^ 6);

  0,62081 secondi (14,44 k allocazioni: 8,415 MiB)

julia> @time rand (10 ^ 6);

  0,004881 secondi (7 allocazioni: 7,630 MiB)

I fan di Julia affermano, in vari modi, che ha la facilità d'uso di Python, R o anche Matlab. Questi confronti richiedono un esame accurato, poiché il linguaggio Julia è elegante, potente e orientato al calcolo scientifico e le librerie forniscono un'ampia gamma di funzionalità di programmazione avanzate.

Esempio di Julia

Come rapido esempio in linguaggio Julia, considera il seguente codice di benchmark del set di Mandelbrot:

Come puoi vedere, l'aritmetica dei numeri complessi è incorporata nel linguaggio, così come le macro per i test e i tempi. Come puoi anche vedere, i punti e virgola finali che affliggono i linguaggi simili al C e le parentesi nidificate che affliggono i linguaggi Lisp sono assenti da Julia. Notare che mandelperf()viene chiamato due volte, nelle righe 61 e 62. La prima chiamata verifica la correttezza del risultato ed esegue la compilazione JIT; la seconda chiamata ottiene il tempismo.

Julia programmazione

Julia ha molte altre caratteristiche degne di nota. Per prima cosa, i tipi definiti dall'utente sono veloci e compatti come i built-in. In effetti, puoi dichiarare tipi astratti che si comportano come tipi generici, tranne per il fatto che sono compilati per i tipi di argomento che vengono passati.

Dall'altro, la vettorizzazione del codice incorporata di Julia significa che non è necessario che un programmatore vettorizzi il codice per le prestazioni; il codice devettorizzato ordinario è veloce. Il compilatore può trarre vantaggio dalle istruzioni e dai registri SIMD, se presenti sulla CPU sottostante, e srotolare i loop in un processo sequenziale per vettorizzarli quanto l'hardware lo consente. È possibile contrassegnare i loop come vettorizzabili con l' @simdannotazione.

Julia parallelismo

Julia è stata progettata anche per il parallelismo e il calcolo distribuito, utilizzando due primitive: riferimenti remoti e chiamate remote. I riferimenti remoti sono disponibili in due versioni:  Future e  RemoteChannel. A Futureè l'equivalente di un JavaScript promise; a RemoteChannelè riscrivibile e può essere utilizzato per la comunicazione tra processi, come Unix pipeo Go channel. Supponendo che tu abbia avviato Julia con più processi (ad esempio julia -p 8per una CPU a otto core come un Intel Core i7), puoi @spawno remotecall()chiamate di funzione da eseguire su un altro processo Julia in modo asincrono, e in seguito fetch()le Futurerestituiscono quando vuoi sincronizzare e utilizzare il risultato.

Se non è necessario eseguire su più core, è possibile utilizzare un threading "verde" leggero, chiamato a Task()in Julia e coroutine in alcune altre lingue. A Task()o @taskfunziona in combinazione con a Channel, che è la versione a processo singolo di RemoteChannel.

Sistema di tipo Julia

Julia ha un sistema di tipi discreto ma potente che è dinamico con inferenza del tipo in fase di esecuzione per impostazione predefinita, ma consente annotazioni di tipo opzionali. Questo è simile a TypeScript. Per esempio:

julia> (1 + 2) :: AbstractFloat

ERRORE: TypeError: typeassert: previsto AbstractFloat, ottenuto Int64

julia> (1 + 2) :: Int

3

Qui stiamo affermando un tipo incompatibile la prima volta, causando un errore e un tipo compatibile la seconda volta.

Julia stringhe

Julia ha un supporto efficiente per stringhe e caratteri Unicode, archiviati in formato UTF-8, nonché un supporto efficiente per caratteri ASCII, poiché in UTF-8 i punti di codice inferiori a 0x80 (128) sono codificati in un singolo carattere. Altrimenti, UTF-8 è una codifica a lunghezza variabile, quindi non puoi presumere che la lunghezza di una stringa Julia sia uguale all'indice dell'ultimo carattere.

Il pieno supporto per UTF-8 significa, tra le altre cose, che puoi facilmente definire variabili usando lettere greche, il che può far sembrare il codice Julia scientifico molto simile alle spiegazioni delle formule dei libri di testo, ad es sin(2π). Viene transcode()fornita una funzione per convertire UTF-8 in e da altre codifiche Unicode.

Funzioni C e Fortran

Julia può chiamare direttamente le funzioni C e Fortran, senza bisogno di wrapper o API speciali, sebbene sia necessario conoscere il nome della funzione "decorato" emesso dal compilatore Fortran. La funzione C esterna o Fortran deve trovarsi in una libreria condivisa; si utilizza la ccall()funzione Julia per la chiamata effettiva. Ad esempio, su un sistema simile a Unix è possibile utilizzare questo codice Julia per ottenere il valore di una variabile di ambiente utilizzando la getenvfunzione in libc:

funzione getenv (var :: AbstractString)

     val = ccall ((: getenv, "libc"),

                 Cstring, (Cstring,), var)

     se val == C_NULL

         errore ("getenv: undefined variable:", var)

     fine

     unsafe_string (val)

fine

julia> getenv ("SHELL")

"/ bin / bash"

Macro di Julia

Julia ha macro simili a Lisp, distinte dai preprocessori macro usati da C e C ++. Julia ha anche altre strutture di meta-programmazione, come la riflessione, la generazione di codice, oggetti di simboli (ad esempio :foo) ed espressioni (ad esempio :(a+b*c+1)) eval()e funzioni generate. Le macro Julia vengono valutate al momento dell'analisi.

Le funzioni generate, d'altra parte, vengono espanse quando i tipi dei loro parametri sono noti, prima della compilazione della funzione. Le funzioni generate hanno la flessibilità delle funzioni generiche (come implementate in C ++ e Java) e l'efficienza delle funzioni fortemente tipizzate, eliminando la necessità di invio in fase di esecuzione per supportare il polimorfismo parametrico.

Supporto GPU

Julia ha il supporto GPU utilizzando, tra gli altri, il pacchetto di deep learning MXNet, la libreria di array GPU ArrayFire, l'algebra lineare cuBLAS e cuDNN e le librerie di reti neurali profonde e il framework CUDA per il GPU computing generico. I wrapper Julia e le rispettive librerie sono mostrati nel diagramma seguente.

Julia Computing

JuliaPro e Juno IDE

Puoi scaricare la riga di comando Julia gratuita e open source per Windows, MacOS, Linux generico o FreeBSD generico dal sito in lingua Julia. Puoi clonare il repository del codice sorgente Julia da GitHub.

In alternativa puoi scaricare JuliaPro da Julia Computing. Oltre al compilatore, JuliaPro ti offre l'IDE Juno basato su Atom (mostrato sotto) e più di 160 pacchetti curati, inclusi visualizzazione e plottaggio.

Oltre a ciò che è incluso nel JuliaPro gratuito, puoi aggiungere abbonamenti per supporto aziendale, funzionalità di finanza quantitativa, supporto di database e analisi di serie temporali. JuliaRun è un server scalabile per un cluster o un cloud.

Quaderni Jupyter e IJulia

Oltre a utilizzare Juno come IDE Julia, puoi utilizzare Visual Studio Code con l'estensione Julia (mostrata direttamente sotto) e notebook Jupyter con il kernel IJulia (mostrato nella seconda e terza schermata di seguito). Potrebbe essere necessario installare i notebook Jupyter per Python 2 o (preferibilmente) Python 3 con Anaconda o pip.

JuliaBox

È possibile eseguire Julia nei notebook Jupyter online utilizzando JuliaBox (mostrato di seguito), un altro prodotto di Julia Computing, senza eseguire alcuna installazione sulla macchina locale. JuliaBox attualmente include più di 300 pacchetti, esegue Julia 0.6.2 e contiene dozzine di notebook Jupyter tutorial. Di seguito è riportato l'elenco di primo livello delle cartelle dei tutorial. Il livello gratuito di accesso JuliaBox offre sessioni di 90 minuti con tre core della CPU; l'abbonamento personale da $ 14 al mese ti offre sessioni di quattro ore con cinque core; e l'abbonamento professionale da $ 70 al mese ti offre sessioni di otto ore con 32 core. L'accesso alla GPU non è ancora disponibile a partire da giugno 2018.

Pacchetti Julia

Julia "cammina come Python, ma corre come C." Come ha scritto il mio collega Serdar Yegulalp nel dicembre 2017, Julia sta iniziando a sfidare Python per la programmazione della scienza dei dati ed entrambi i linguaggi hanno dei vantaggi. Come indicazione del supporto in rapida maturazione per la scienza dei dati in Julia, si consideri che ci sono già due libri intitolati Julia for Data Science , uno di Zacharias Voulgaris e l'altro di Anshul Joshi, anche se non posso parlare della qualità di nessuno dei due uno.

Se guardi i pacchetti Julia complessivamente più votati da Julia Observer, mostrati di seguito, vedrai un kernel Julia per i notebook Jupyter, il pacchetto grafico Gadfly (simile a ggplot2R), un'interfaccia di stampa generica, diversi deep learning e machine pacchetti di apprendimento, risolutori di equazioni differenziali, DataFrames, modelli DSGE (Dynamic Stochastic General Equilibrium) della Fed di New York, un linguaggio di modellazione dell'ottimizzazione e interfacce per Python e C ++. Se vai un po 'più in basso in questo elenco generale, troverai anche QuantEcon, PyPlot, ScikitLearn, un pacchetto di bioinformatica e un'implementazione di liste pigre per la programmazione funzionale.

Se i pacchetti Julia non sono sufficienti per le tue esigenze e l'interfaccia Python non ti porta dove vuoi andare, puoi anche installare un pacchetto che ti fornisce interfacce generiche per R (RCall) e Matlab.

Julia per analisti finanziari e quanti

Quants e analisti finanziari troveranno molti pacchetti gratuiti per velocizzare il loro lavoro, come mostrato nello screenshot qui sotto. Inoltre, Julia Computing offre la suite JuliaFin, composta da Miletus (un DSL per contratti finanziari),  JuliaDB (un database distribuito e in memoria ad alte prestazioni),  JuliaInXL (chiama Julia dai fogli Excel) e  connettività Bloomberg (accesso a dati reali -time e dati storici di mercato).