Co to jest Julia? Nowe podejście do obliczeń numerycznych

Julia to darmowy, wysokopoziomowy, dynamiczny język programowania o otwartym kodzie źródłowym do obliczeń numerycznych. Ma wygodę programowania dynamicznego języka z wydajnością skompilowanego języka statycznego, częściowo dzięki kompilatorowi JIT opartemu na LLVM, który generuje natywny kod maszynowy, a częściowo dzięki projektowi, który implementuje stabilność typu poprzez specjalizację poprzez wiele wysyłka, co ułatwia kompilację do wydajnego kodu.

W poście na blogu ogłaszającym pierwsze wydanie Julii w 2012 roku, autorzy języka - Jeff Bezanson, Stefan Karpinski, Viral Shah i Alan Edelman - stwierdzili, że spędzili trzy lata na tworzeniu Julii, ponieważ byli chciwi . Byli zmęczeni kompromisami między Matlab, Lisp, Python, Ruby, Perl, Mathematica, R i C i chcieli jednego języka, który byłby dobry do obliczeń naukowych, uczenia maszynowego, eksploracji danych, algebry liniowej na dużą skalę , przetwarzanie równoległe i przetwarzanie rozproszone.

Dla kogo jest Julia? Oprócz bycia atrakcyjną dla naukowców i inżynierów, Julia jest również atrakcyjna dla analityków danych, analityków finansowych i kwantów.

Projektanci języka i dwaj inni założyli Julia Computing w lipcu 2015 r., Aby „opracowywać produkty, które sprawiają, że Julia jest łatwa w użyciu, łatwa do wdrożenia i łatwa do skalowania”. W chwili pisania tego tekstu firma zatrudnia 28 pracowników i klientów, od laboratoriów krajowych po banki, ekonomistów i badaczy pojazdów autonomicznych. Oprócz utrzymywania repozytoriów open source Julia na GitHub, Julia Computing oferuje produkty komercyjne, w tym JuliaPro, która jest dostępna zarówno w wersji bezpłatnej, jak i płatnej.

Dlaczego Julia?

Julia „ma na celu stworzenie bezprecedensowego połączenia łatwości obsługi, mocy i wydajności w jednym języku”. Jeśli chodzi o kwestię wydajności, rozważ poniższy wykres:

Julia Computing

Testy Julii

Widzimy tutaj, że kod Julii może być szybszy niż C dla kilku rodzajów operacji i nie więcej niż kilka razy wolniejszy niż C dla innych. Porównaj to z, powiedzmy, R, które może być prawie 1000 razy wolniejsze niż C dla niektórych operacji.

Zauważ, że jednym z najwolniejszych testów Julii jest rekurencja Fibonacciego; Dzieje się tak dlatego, że Julia obecnie nie ma optymalizacji rekurencji ogonowej. Rekurencja jest z natury wolniejsza niż pętla. W przypadku prawdziwych programów Julii, które chcesz uruchomić w środowisku produkcyjnym, będziesz chciał zaimplementować formę pętli (iteracji) takich algorytmów.

Kompilacja Julia JIT

W przeciwieństwie do czystego interpretera, kompilator JIT (just-in-time) ma swój koszt: kompilator musi przeanalizować kod źródłowy i wygenerować kod maszynowy, zanim kod będzie można uruchomić. Może to oznaczać zauważalny czas uruchamiania programów Julia przy pierwszym uruchomieniu każdej funkcji i makra w sesji. Tak więc na poniższym zrzucie ekranu widzimy, że za drugim razem, gdy generujemy milion losowych liczb zmiennoprzecinkowych, potrzebny czas jest o rząd wielkości mniejszy niż przy pierwszym wykonaniu. Zarówno @timemakro, jak i rand()funkcja musiały zostać skompilowane po raz pierwszy za pomocą kodu, ponieważ biblioteki Julii są napisane w Julii.

julia> @time rand (10 ^ 6);

  0,62081 sekund (14,44 tys. Alokacji: 8,415 MiB)

julia> @time rand (10 ^ 6);

  0,004881 sekund (7 alokacji: 7,630 MiB)

Fani Julii twierdzą różnie, że ma łatwość użycia Pythona, R, a nawet Matlaba. Te porównania wymagają dokładnej analizy, ponieważ język Julia jest elegancki, potężny i zorientowany na obliczenia naukowe, a biblioteki zapewniają szeroki zakres zaawansowanych funkcji programowania.

Przykład Julii

Jako szybki przykład języka Julii, rozważ następujący kod wzorcowy zestawu Mandelbrota:

Jak widać, arytmetyka liczb zespolonych jest wbudowana w język, podobnie jak makra do testów i synchronizacji. Jak widać, w Julii nie ma końcowych średników, które są plagą języków typu C, oraz zagnieżdżonych nawiasów, które są plagą języków podobnych do Lispa. Zauważ, że mandelperf()jest wywoływana dwukrotnie w liniach 61 i 62. Pierwsze wywołanie sprawdza poprawność wyniku i wykonuje kompilację JIT; drugie połączenie pobiera czas.

Programowanie Julii

Julia ma wiele innych cech, o których warto wspomnieć. Po pierwsze, typy zdefiniowane przez użytkownika są tak szybkie i kompaktowe, jak typy wbudowane. W rzeczywistości można zadeklarować typy abstrakcyjne, które zachowują się jak typy ogólne, z wyjątkiem tego, że są kompilowane dla przekazywanych typów argumentów.

Po drugie, wbudowana wektoryzacja kodu Julii oznacza, że ​​programista nie musi wektoryzować kodu w celu zwiększenia wydajności; zwykły zdewektorowany kod jest szybki. Kompilator może skorzystać z instrukcji i rejestrów SIMD, jeśli są obecne na bazowym procesorze, i rozwinąć pętle w procesie sekwencyjnym, aby wektoryzować je tak bardzo, jak pozwala na to sprzęt. Za pomocą @simdadnotacji można oznaczyć pętle jako możliwe do wektoryzacji .

Paralelizm Julii

Julia została również zaprojektowana pod kątem równoległości i obliczeń rozproszonych, przy użyciu dwóch prymitywów: zdalnych odwołań i zdalnych wywołań. Zdalne odniesienia występują w dwóch wersjach:  Future i  RemoteChannel. A Futurejest odpowiednikiem JavaScript promise; a RemoteChanneljest wielokrotnego zapisu i może być używany do komunikacji między procesami, jak Unix pipelub Go channel. Zakładając, że zaczęli Julia z wieloma procesami (np julia -p 8dla procesora osiem-core, takim jak Intel Core i7), można @spawnlub remotecall()wywołania funkcji do wykonania na inny proces Julii asynchronicznie, a później zwracany, gdy chcesz synchronizować i obsługi wynik.fetch()Future

Jeśli nie potrzebujesz pracować na wielu rdzeniach, możesz użyć lekkiego „zielonego” Task()wątku , zwanego w języku Julii a, a także programu w innych językach. A Task()lub @taskdziała w połączeniu z a Channel, który jest wersją jednoprocesową RemoteChannel.

System typu Julia

Julia ma dyskretny, ale potężny system typów, który jest dynamiczny z domyślnym wnioskiem o typie w czasie wykonywania, ale umożliwia opcjonalne adnotacje typu. Jest to podobne do TypeScript. Na przykład:

julia> (1 + 2) :: AbstractFloat

BŁĄD: TypeError: typeassert: spodziewano się AbstractFloat, pobrano Int64

julia> (1 + 2) :: Int

3

Tutaj za pierwszym razem potwierdzamy niezgodny typ, powodując błąd, a zgodny typ za drugim razem.

Struny Julii

Julia ma wydajną obsługę ciągów i znaków Unicode, przechowywanych w formacie UTF-8, a także wydajną obsługę znaków ASCII, ponieważ w UTF-8 punkty kodowe mniejsze niż 0x80 (128) są kodowane w jednym znaku. W przeciwnym razie UTF-8 jest kodowaniem o zmiennej długości, więc nie można założyć, że długość łańcucha Julia jest równa indeksowi ostatniego znaku.

Pełne wsparcie dla UTF-8 oznacza między innymi, że można łatwo definiować zmienne za pomocą greckich liter, dzięki czemu naukowy kod Julii może wyglądać bardzo podobnie do podręcznikowych wyjaśnień formuł, np sin(2π). Dostępna transcode()jest funkcja umożliwiająca konwersję UTF-8 do iz innych kodowań Unicode.

Funkcje C i Fortran

Julia może wywoływać funkcje C i Fortran bezpośrednio, bez żadnych opakowań ani specjalnych interfejsów API, chociaż musisz znać „ozdobioną” nazwę funkcji, emitowaną przez kompilator języka Fortran. Zewnętrzna funkcja C lub Fortran musi znajdować się w bibliotece współdzielonej; używasz ccall()funkcji Julia do rzeczywistego wywołania. Na przykład w systemie uniksopodobnym możesz użyć tego kodu Julii, aby uzyskać wartość zmiennej środowiskowej za pomocą getenvfunkcji w libc:

function getenv (var :: AbstractString)

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

                 Cstring, (Cstring,), var)

     jeśli val == C_NULL

         błąd („getenv: undefined variable:”, var)

     koniec

     unsafe_string (val)

koniec

julia> getenv ("POWŁOKA")

„/ bin / bash”

Julia makra

Julia ma makra podobne do Lisp, w odróżnieniu od preprocesorów makr używanych przez C i C ++. Julia ma również inne funkcje metaprogramowania, takie jak odbicie, generowanie kodu, obiekty symboli (np. :foo) I wyrażeń (np. :(a+b*c+1)) Oraz eval()generowane funkcje. Makra Julia są oceniane w czasie analizowania.

Z drugiej strony generowane funkcje są rozszerzane, gdy znane są typy ich parametrów przed kompilacją funkcji. Generowane funkcje charakteryzują się elastycznością funkcji ogólnych (zaimplementowanych w C ++ i Javie) oraz wydajnością funkcji silnie typizowanych, dzięki wyeliminowaniu konieczności wysyłania w czasie wykonywania w celu obsługi polimorfizmu parametrycznego.

Obsługa GPU

Julia obsługuje GPU, korzystając m.in. z pakietu uczenia głębokiego MXNet, biblioteki macierzy GPU ArrayFire, algebry liniowej cuBLAS i cuDNN oraz bibliotek głębokich sieci neuronowych, a także frameworka CUDA do obliczeń GPU ogólnego przeznaczenia. Opakowania Julia i odpowiadające im biblioteki pokazano na poniższym diagramie.

Julia Computing

JuliaPro i Juno IDE

Możesz pobrać darmowy wiersz poleceń Julia o otwartym kodzie źródłowym dla systemów Windows, MacOS, ogólnego Linuksa lub ogólnego FreeBSD z witryny językowej Julia. Możesz sklonować repozytorium kodu źródłowego Julii z GitHub.

Alternatywnie możesz pobrać JuliaPro z Julia Computing. Oprócz kompilatora, JuliaPro oferuje oparte na Atom środowisko Juno IDE (pokazane poniżej) i ponad 160 wyselekcjonowanych pakietów, w tym wizualizację i kreślenie.

Oprócz tego, co jest dostępne w bezpłatnej aplikacji JuliaPro, możesz dodać subskrypcje wsparcia dla przedsiębiorstw, funkcje finansów ilościowych, obsługę baz danych i analizę szeregów czasowych. JuliaRun to skalowalny serwer dla klastra lub chmury.

Zeszyty Jupyter i IJulia

Oprócz używania Juno jako środowiska Julia IDE, możesz użyć Visual Studio Code z rozszerzeniem Julia (pokazanym bezpośrednio poniżej) oraz notesów Jupyter z jądrem IJulia (pokazane na drugim i trzecim zrzucie ekranu poniżej). Może być konieczne zainstalowanie notebooków Jupyter dla Pythona 2 lub (najlepiej) Pythona 3 z Anacondą lub pip.

JuliaBox

Możesz uruchomić Julię w notebookach Jupyter online za pomocą JuliaBox (pokazanego poniżej), innego produktu Julia Computing, bez wykonywania żadnej instalacji na komputerze lokalnym. JuliaBox zawiera obecnie ponad 300 pakietów, uruchamia Julię 0.6.2 i zawiera dziesiątki samouczków notatników Jupyter. Lista folderów samouczków najwyższego poziomu jest pokazana poniżej. Darmowy poziom dostępu do JuliaBox zapewnia 90-minutowe sesje z trzema rdzeniami procesora; subskrypcja osobista w wysokości 14 USD miesięcznie zapewnia czterogodzinne sesje z pięcioma rdzeniami; a subskrypcja pro w wysokości 70 USD miesięcznie zapewnia 8-godzinne sesje z 32 rdzeniami. Dostęp do GPU nie jest jeszcze dostępny od czerwca 2018 r.

Opakowania Julia

Julia „chodzi jak Python, ale biegnie jak C.” Jak napisał mój kolega Serdar Yegulalp w grudniu 2017 r., Julia zaczyna rzucać wyzwanie Pythonowi w programowaniu do nauki o danych, a oba języki mają zalety. Jako wskazanie szybko dojrzewającego wsparcia dla nauki o danych w Julii, weź pod uwagę, że istnieją już dwie książki zatytułowane Julia for Data Science , jedna autorstwa Zachariasa Voulgarisa, a druga autorstwa Anshula Joshiego, chociaż nie mogę mówić o jakości żadnej z nich. jeden.

Jeśli spojrzysz na ogólnie najwyżej oceniane pakiety Julia od Julia Observer, pokazane poniżej, zobaczysz jądro Julia dla notebooków Jupyter, pakiet graficzny Gadfly (podobny do ggplot2w R), ogólny interfejs kreślenia, kilka głębokiego uczenia i maszynowego pakiety edukacyjne, rozwiązywanie równań różniczkowych, ramki DataFrames, dynamiczne stochastyczne modele równowagi ogólnej (DSGE) New York Fed, język modelowania optymalizacji oraz interfejsy do Pythona i C ++. Jeśli pójdziesz nieco dalej w dół tej ogólnej listy, znajdziesz również QuantEcon, PyPlot, ScikitLearn, pakiet bioinformatyczny oraz implementację leniwych list do programowania funkcjonalnego.

Jeśli pakiety Julia nie są wystarczające dla Twoich potrzeb, a interfejs Pythona nie prowadzi Cię tam, gdzie chcesz, możesz również zainstalować pakiet, który zapewnia ogólne interfejsy do R (RCall) i Matlab.

Julia dla analityków finansowych i kwantów

Kwanty i analitycy finansowi znajdą wiele bezpłatnych pakietów przyspieszających ich pracę, jak pokazano na poniższym zrzucie ekranu. Ponadto Julia Computing oferuje pakiet JuliaFin, składający się z Miletu (DSL dla kontraktów finansowych),  JuliaDB (wysokowydajna pamięć i rozproszona baza danych),  JuliaInXL (zadzwoń do Julii z arkuszy Excela) oraz  łączność Bloomberg (dostęp do rzeczywistych -czasowe i historyczne dane rynkowe).