85 comments

[ 3.2 ms ] story [ 135 ms ] thread
I find Julia to be a beautiful little language. Applause to the team for this 1.3 release!

In one of my CS classes we wrote a LISP using Julia. Our professor wrote the parser for us, so we just had to focus on the actual interpreter bit. The pattern matching/multi-dispatch mechanisms were really nice. We didn't get to play too much with the parallelism mechanisms, but I liked what I did see.

I feel like Julia is a much richer language than, say, Python, and it would be a nice drop-in replacement for numerical computing tasks: it's faster, in some ways more ergonomic, and afaik can call out to Python libraries if needed. Has anyone here switched from Python to Julia for scientific/ML/AI purposes?

I played around with Julia a bit last year. One thing that stuck with me was the non-negligible start-up speed. If you want tight feedback loops you have to figure out a way to reuse a Julia instance (like Jupyter).

On that train of thought, how interoperable is preexisting numpy/pandas code with Julia?

I agree and this still holds it back from being the main language in a research environment where one wants to have quick turnaround time.

On the other hand, it should work very well as a replacement for Numba. Numba already comes with a one-off jit cost, and it is much more limited in the sort of code it can speed up.

You can ;-) The secret sauce in Julia is to use Revise.jl package. Is makes your life so much better. It observes source code changes while you are at the REPL. No need to restart everything.
+1 for this package. Total game changer.
How reliable is Revise.jl compared to ipython autoreload? My experience with ipython autoreload is... very poor, even though some people swear by it, so I have trust issues with this type of thing.
I use it extensively. In my experience it is very reliable. Onle once or twice in two years of using it has something strange happened with JIT compilation of functions. All I had to do to fix was restart the Julia REPL and load things in again.
One downside is Revise v2 actually itself has a fairly high startup cost. Best alternative is to pin it to Revise v1.

I personsally don't mind the startup too much. But I do get where people are coming from

> One thing that stuck with me was the non-negligible start-up speed.

Yes! this is the biggest roadblock for me. I find python startup time unbearably long. I do not want to imagine even using julia. And this is sad because the language is orders of magnitude better (for math, at least).

If you're used to launching everything from your OS's command prompt, this is a killer. But if you get used to launching a REPL and running things from there, it's much better, because you only pay the startup latency once.
Some workflows require running scripts from the command line though
Julia has 0-copy numpy array interop through PyCall.jl if that's what you're asking.
As for startup speed, note that in this round our research software engineer in the Julia Lab just brought the "first time to plot" to about 1/4 of what it was before. Julia 1.3 has a lot of these updates, and Julia 1.4 has a development sprint for bringing down the latency. I would be surprised if the common major latency issues still exist past next summer. Of course a JIT will always have some bumps compared to a pure interpreter, but Julia's compiler is definitely getting a lot smarter as to what to try and fully analyze (and what to cache)
> If you want tight feedback loops you have to figure out a way to reuse a Julia instance

I think Julia is meant to be used like Lisp:

- Step 1: Open the REPL.

- Step 2: Don't close it until you are finished (both writing and running your program).

My best guess is that people that complain about startup speed of Julia (and Emacs too for that matter) ignore step 2.

For myself, I write scripts that are part of automated analysis pipelines. So in my case (and probably others), using the REPL is mostly useful for testing code.
Not being 100% interoperable with python make Julia doomed.

Library ecosystems have a human workforce value of billions of dollars, available for free. Any modern language that want to go mainstream must offer transparent and complete interoperability with an existing ecosystem. TypeScript -> js Kotlin -> jvm C++ -> C Elixir -> Erlang Hack -> php Crystal -> ruby

As we can see there are still Big ecosystems lacking a new modern language™ The python ecosystem The C# (CLR) ecosystem

It could be said that's mainly because those languages are already mostly "modern"

There are also dying big ecosystem and there would be economic value to make their old libraries accessible. Fortran Pascal Perl Etc

> As we can see there are still Big ecosystems lacking a new modern language™ [...] The C# (CLR) ecosystem

F#, obviously.

Not to mention C# is as modern as it gets...
Is it really? Class-based single dispatch OO with strictly explicit static typing—no gradual or optional or even Hindley-Milner type inference—is about as 90s a language design as there is. It’s like the “Friends” of PL designs. Which is to say, very popular and not bad, but certainly not modern or cutting edge.
C# supports multi-dispatch and gradual typing using the dynamic keyword since 4.0. It also does some type inference using var, but not full HM.
I didn't say "cutting edge" though, I said modern.

Modern is not some "PL-community favorite with small following" a la Haskell, it's what programmers in the trenches are using. The same way a modern car is (pick a popular current model) and not some limited edition car with limited sales.

C# "keeps up with the Joneses", brings in ideas from functional programming (bringing in F# features incrementally), etc.

LINQ, pattern matching, dynamic, value types, tuples, destructuring, async/await, null-coalescing operators/assignment, streams, and much more...

Not only is up there with any popular language in the same domain (Swift, Kotlin, etc), and way ahead of Java, but compared to something like Go that gets people excited this is space technology.

(Plus is not like multiple dispatch is a new development, or gradual/optional typing is the "new" thing - we had those things for decades, and I don't see them catching on except the latter where necessary - e.g. adding gradual typing in JS/Python/etc variants like TS, where they can't have strict static typing for compatibility/historical reasons. The only language with gradual typing I remember in recent times was not very cutting-edge itself, Dart, and didn't manage to go anywhere).

You can use Python, C and Fortran code from Julia. More importantly package development is much faster in Julia than in Python. Which means the speed of which packages get added to Julia is much faster than Python.

And here is the kicker: Packages is Julia are far more interoperable than in any other eco system I have seen.

Than means 10 packages in Julia can quickly do more than 50 packages in other language. Say somebody makes a GPU processing package and somebody else makes a Machine learning package. They don't know about it each other.

Yet with Julia we frequently see that these guy can use each others package. The ML package can with little effort run on a GPU by including a GPU package even if it was never designed for it.

Julia just moves way faster than the competition and that is why Julia is NOT doomed.

>You can use Python, C and Fortran code from Julia. More importantly package development is much faster in Julia than in Python. Which means the speed of which packages get added to Julia is much faster than Python.

That's because Python already has tons, while Julia lacks tons.

Are the new ones added to Julia as good or better though?

>That means 10 packages in Julia can quickly do more than 50 packages in other language. Say somebody makes a GPU processing package and somebody else makes a Machine learning package. They don't know about it each other. Yet with Julia we frequently see that these guy can use each others package. The ML package can with little effort run on a GPU by including a GPU package even if it was never designed for it.

This sounds like magic bullet / handwaving.

Perhaps Julia's multiple dispatch helps here (?), but why would the above be the case and wouldn't be achievable in other existing languages as is?

> Perhaps Julia's multiple dispatch helps here (?), but why would the above be the case and wouldn't be achievable in other existing languages as is?

Yes, ubiquitous, zero-overhead multiple dispatch is the reason, as explained in depth here:

https://youtu.be/kc9HwsxE1OY

>This sounds like magic bullet / handwaving.

It's not handwaving when it already exists. CUDAnative.jl gives native compilation of Julia code to GPUs, which allows CuArrays.jl to do efficient loop fusion among other tricks. This is then enough for DifferentialEquations.jl, Flux.jl (the big neural net library, think PyTorch), CLIMA (a MIT-CalTech next-gen climate model), etc. (too many packages to list) to all utilize the same underlying GPU framework. It's as if someone got rid of the GPU functionality of Numba, PyTorch, TensorFlow, etc. and just made one good enough Python library for everyone to share. As you can imagine, that reduces the amount of work to do package development but gets the same functionality in the end with a lot less maintenance issues. You can also say the same for how many JITs and transpilers to C there are in Python libraries vs the single Julia JIT.

The real danger of the Python monoliths is that when something as simple as a neural network package starts to include a JIT, a GPU compiler, and automatic differentiation library, and it's all written in C++, it gets really hard to attract developers because the code base is so hard to understand. This means that instead of getting new developers and more maintenance, people just spawn new libraries all of the time in Python, starting from scratch to write a new JIT, new GPU kernels, etc. I just cannot see how that's a good thing.

>> Not being 100% interoperable with python make Julia doomed.

> Than means 10 packages in Julia can quickly do more than 50 packages in other language.

Maybe you guys would like to compare your text editors now?

There are only 2 languages with really good Python interop (you could call it "as close as possible to 100%" since there is no such thing as "100% interop" except across languages sharing same VM like on the JVM Java & Clojure & Kotlin...).

One of them is Julia! - https://github.com/JuliaPy/PyCall.jl .

The other is Swift - https://github.com/tensorflow/swift/blob/master/docs/PythonI... .

And pretty sure the Swift team did it after seeing how well it went for julia.
Is there any chance the course material is available? I've been looking to better my Julia meta-programming. Most of the resources out there are geared towards other languages. It would be amazing to see some simple parser/interpreter implementations.
I switched to Julia from Python due to facing the classic '2-language problem' of scientists. We wanted an easy to use API and good speed.

The main bottleneck was computing the Mittag-Leffler function. First we tried in Python, then we get a ~10x improvement by outsourcing that bit to Fortran. The Julia implementation of the Mittag-Leffler function is comparable to Fortran but writing the entire software package in Julia led to ~5x speedup due to avoiding language interop issues and taking advantage of other Julia-specific benefits.

So, you obtained a 5x speedup of the whole package compared to the Python version with some Fortran extensions?
Yes.

And for anyone wondering about the state of the Julia package ecosystem compared to Python, someone had already written the main two packages we needed in Julia (for Mittag-Leffler computation and Inverse Laplace computation). At that time there was no Mittag-Leffler implemented in Python or SciPy that I could find.

I could also add that we were computing integral equations with Mittag-Leffler function in the Kernels so in worst cases we needed O(n^2) calls to Mittag-Leffler function where n could be O(10^5).

If you need another speedup consider LuaJIT which is used at CERN for heavy number crunching and data analysis, see http://cds.cern.ch/record/2157242?ln=de. E.g. on slide 14: LuaJIT took 5.3 sec, C++/GCC 5.7 sec, PyPy 7.6 sec, Julia 35 sec and Python > 2 hours.
From the comments on that:

> No one should use global scope of Julia for calculations: [...] which is said that takes 35 seconds. > If you wrap it in a function and not had a type instability, You'd get 4.704 seconds...

Half-decently written Julia ought not to be much slower than C.

But it does also allow you to write quick and dirty scripts with no care for speed, which is also useful. It would be nice if people wouldn't benchmark the latter. The manual has a pretty helpful section for avoiding this: https://docs.julialang.org/en/v1/manual/performance-tips/

Indeed, I would imagine that well written Julia is on par with LuaJIT.

Even more importantly, from a cursory look online I cannot find any Lua implementation of either the Mittag-Leffler function or Inverse Laplace routines. And there is no reference to any wider ecosystem of scientific computing packages.

Sure I could call some C functions but then I'm back to facing a 2-language problem which I don't want.

Furthermore, it looks like there has been no new releases of LuaJIT since 2017. Development on it looks to have stopped.

If you can measure you don't have to imagine.
(comment deleted)
I watched the video, those benchmarks are just terrible. If one wants to use LuaJIT for a porject, sure go for it, but making up weird benchmarks like that which purposefully cripple competitor language performance is just embarrassing.
Well, weird benchmarks are probably all those where your favorite language doesn't look good ;-)
I would say in this case what's 'weird' about the benchmarks is that the optimization strategy taken across the languages is incredibly uneven. Indeed, simply wrapping the above julia code in a `let` block so it's not out in the global scope is sufficient to have it on par with C++ (assuming the same flags are used, e.g. fastmath).
>> Zero-dimensional arrays are now consistently preserved in the return values of mathematical functions that operate on the array(s) as a whole (and are not explicitly broadcasted across their elements). Previously, the functions +, -, *, /, conj, real and imag returned the unwrapped element when operating over zero-dimensional arrays.

That's great news, it drives me crazy when languages or libraries get that wrong.

In other words, mostly catching up features present in mainstream languages.
This is not a bad thing and it is quite natural considreing how young the language is. The same is true for golang and many other new cool languages. Being conservative when introuducing features in a new language is a very wise approach.
This is natural indeed but it should be more frequently said, as I feel too many developers will go to the new shiny language and loose so many times because of what I call software poverty. (lack of libs, lack of features, lack of stackoverflow, lack of documentation, and even lack of stability) Indeed new languages have new shiny features but they do not outweigh the poverty cost. Especially since there are modern languages compatible with big ecosystems like typescript or kotlin, I don't really see how new languages that are not compatible can be competitive.
> modern languages compatible with big ecosystems like typescript or kotlin

...if you do anything towards ML or datascience, typescript and kotlin are the poor relatives. For most tasks 90% of the ecosystem is useless to you and you can spend more time wrangling the dependencies of a nasty nodejs package than quickly coding smth from scratch.

That "richness" is also... "garbage".

If the language fills a niche sufficiently better than existing ones. Julia doesn’t bring too many novel concepts (JIT, macros, multimethods, parallelism) but ties them together nicely for scientific computing.

The best chance Julia has isn’t attracting average devs alone, but the library developers. Writing new python libraries for research purposes often requires writing C/C++ code. There’s already a number of Julia libraries focusing on interesting research topics in scientific, mathematics, and AI. Those lead to better and more useful libraries over time which can interact over time. Plus Julia Computing seems to be going towards building a successful commercial side of Julia. Personally I don’t find the software poverty thing much of an issue, outside a few core areas (database drivers, basic http, c interop, networking, text editors).

> I don't really see how new languages that are not compatible can be competitive.

What exactly would you like Julia to be compatible with?

Python? https://github.com/JuliaPy/PyCall.jl

JS? https://github.com/SimonDanisch/JSCall.jl

C++? https://github.com/JuliaInterop/Cxx.jl

Java? https://github.com/JuliaInterop/JavaCall.jl

R? https://github.com/JuliaInterop/RCall.jl

Not all of these are fully polished, but they're all being worked on (plus there are a bunch of others that aren't being actively worked on that I haven't put here).

Seems like multi-processing is already better than Python, which is a hot mess. For things that you'd actually need multi-processing in, say, deep learning - like preparing and loading and then saving data, Python is difficult to use. And if you have to run something on windows, you are doomed.

I wrote a custom data pipeline for huge HDF5 files for some ai thing, which was a headache in linux but doable. Then it had to run on windows and I just wanted to kill myself.

Doing the same in Julia or even Matlab was easy, and faster.

And python is supposed to be easy to use :<

One day Python will be as fast as Dylan.
The only other dynamic language with this kind of multithreading capability is, wait for it... Raku (aka Perl 6). And my impression is that Raku doesn’t get very high performance with its multithreading, which is mostly designed to improve I/O throughput (and because it’s a cool feature and Raku has never met a feature it doesn’t like).

Even among static languages, it’s a relatively rare capability: Go has excellent support (of course), C extensions like Cilk and TBB support it, Rust has something similar with tokio, and I’ve heard people claim that Haskell can do something similar with appropriate extensions.

> And my impression is that Raku doesn’t get very high performance with its multithreading

Could you elaborate on how you got that impression? Do you have any benchmarks that the Raku core developers could look at?

I recall seeing various benchmarks of Raku that were on the slow side—slower than Perl 5 / Python speed, which are already what I'd describe as "slow languages". I can't currently find what specifically I read, but https://www.reddit.com/r/perl6/comments/btvkoz/is_perl6_stil... seems to have some discussion (and I think you're on that thread, so I'm sure you're aware). This doesn't specifically address threading performance, but if the runtime is 100-500x slower than C, it's not like threading can make up that kind of performance deficit.
The Raku runtime is still improving, and several object creation benchmarks now outrun Perl. A low bar, some might argue. But still.

Threading can make a difference on non-IO bound tasks if you're interested in wallclock rather than CPU: for instance, `say (1..Inf).grep( { .is-prime } )[9999]` (showing the 10000th prime number) runs 22 seconds on my machine, but the threaded version of that: `say (1..Inf).hyper.grep( *.is-prime )[9999]` runs in 8 seconds. That's just by adding the `.hyper` method to the chain!

Here's a comparable thing in Julia:

    julia> using Primes, Lazy

    julia> @time drop(9999, filter(isprime, Lazy.range(1)))[1]
      0.119811 seconds (1.25 M allocations: 23.502 MiB)
    104729
The Lazy package doesn't support using threads yet since 1.3 was just released, so doing the threaded comparison isn't simple at the moment. However, this illustrates what I was getting at: the sequential Julia code is 185x faster than the the sequential Raku code and 67x faster than the threaded Raku code. It's great that Raku threading gets some scaling here (not sure how many cores you have, so it's unclear if 2.75x scaling is good or not, but it's not nothing). But it's considerably easier to scale if there's already a lot of performance on the table. The faster each operation is, the harder it is to make a threading implementation that has low enough overhead to make threads worthwhile. From the performance perspective, any effort spent on threading in Raku would be better spent on sequential speed until that has been maxed out.

I should also note that this is not how one would actually find the 10000th prime efficiently. For that you'd use the `nextprime` function also provided by the Primes package, like so:

    julia> @time nextprime(1, 10000)
      0.010456 seconds (17.00 k allocations: 265.562 KiB)
    104729
That's another 10x faster than the lazy sequence approach. Which mostly tells me that the lazy code is impressively efficient—I would have expected a dedicated function to have more of an edge. Lest anyone cry foul about using C or whatever, this function is implemented fairly straightforwardly in Julia:

https://github.com/JuliaMath/Primes.jl/blob/ce0c1e388e1fd375....

Thank you for these goals :-)

Just for the record: yes, there are faster ways of finding the 10000th prime, but I use this example often as an example of a CPU-intensive task that can be spread over multiple threads easily.

Also, please note that all features of the example are built-in into Raku: no external module loading needed.

I'm rooting for Julia. Currently we are using python and rust, but rust is not an easy language to do exploratory analysis in, so it's relegated to handling only the stable parts of our analytics libraries.

It looks like Julia integrates quite seamlessly with python, so I'm hoping that we can start using it to easily speed up exploratory research code without having to spend a lot of time.

I keep my eye on Julia, but still did not have a chance to dig into it. I would be interested to learn more about its place and capabilities:

- I want to build an new (yet another) distributed data processing framework, say, Hadoop or Spark Next, generic or for a particular industry, and I do not want to use Java or C++.

Can Julia be a feasible choice for a distributed computation like Spark, for distributed file system like HDFS, for resource allocator like Yarn? Can it be a good choice for a database engine, or its place is in layers above the engine - say a layer to support aggregation and computations?

Or it's not a right choice comparing with Rust, C++, or Java for core systems, and it's better to stick with it just for computations on the top of those core systems?

What about kotlin? You would benefit from existing java/scala libraries.
My question was more about figuring out if Julia can be a good candidate, not like writing off Java or C++. Something when you build things for fun, for personal project, for prototype, or research project.

If I am a Chief Engineer / CTO of a company, and need to choose a language for Yet Another data platform, I would definitely look first at Java / Kotlin / Scala for implementation - they are a proven pragmatic choice for such tasks. If there are memory and garbage collection concerns of the former, I would look at C++ or Rust (still risky for staffing).

What I like in Julia is its expressiveness, and that it was built for writing maths and computations. So it's a great candidate for top level libraries above core components - it may be a reasonable choice for a business now.

But Julia promises good performance as well. Therefore, if one does not have very strict requirements to avoid GC it may look like an interesting idea to stick with the same language for the core components. Here was my question above :)

Yes to distributed data processing. JuliaDB.jl has promise.
I don't know the domain you describe, but you have e.g. JuliaDB which has quite good performance from what I read.

https://juliadb.org

JuliaDB is about storing and retrieving Julia data end to end, although it works with e.g. CSV files etc as far as I know.

The benefit of using Julia over something like Java or C++ is that user defined function can easily be added and they are JIT compiled for maximum performance.

The main consideration with respect to using Julia is about whether your domain has problems with JIT compilation or not. Anything that is started and shut down frequently and only runs for a short time will not work well with a JIT based system like Julia.

Also places where you need fine control over latency such as computer games or real time systems may not be suitable for Julia. Then I suspect Rust or Swift would be better.

Other than that Julia is good for almost anything. I has great support for parallelism, concurrency and crunch numbers really fast.

While C++ and Rust may beat Julia in performance I think you should be able to outperform Java, because Julia is designed much more with performance in mind than Java. E.g. you have better control over memory layout, cache misses etc in Julia than in Java.

It was really a bad decision to design Java without value types, given the already existing plethora of GC enabled systems languages since the mid-70's.

However that will be eventually fixed, and then we won't be able to bash Java any longer for lack of value types.

In what GC languages are concerned, it would be more interesting to compare Julia's generated code against .NET Core languages, D (specially ldc), Nim.

Java has been around for multiple decades but the types are just around the corner? That reminds me of static compilation, which was also coming soon for 20 years.
AOT compilation has been an option to Java shops willing to buy third party commercial JVMs since around 2000.

You can play around with value types experimental releases already.

https://jdk.java.net/valhalla/

Adopting value types, while keeping 20+ year old jars working without any kind of changes is an engineering feat.

I bet that Java will get value types before Go gets its generics, if ever.

There is definately space for compeditors to JuliaDB. I think its shown the area can work. But some competition to drive innovation is a win for everyone
Does the Rust Rayon library have the issue the speaker was describing, where parallel inner loops mostly get executed serially once an outer loop is parallelized? (I assume it does, from its Cilk heritage?) Are there workarounds for when that is a problem?

Edit: Dumb mistake on my part. I was looking at the video linked in the top comment (https://www.youtube.com/watch?v=YdiZa0Y3F3c) and then I came back to this thread and thought it was the topic.

Julia feels like a scripting language but every function is effectively a template. I prototype lots of high perf stuff in it because it gives you control of memory layout and what gets evaluated at compile time, so it'll get you within spitting distance of an optimised c++ implementation but with 10x better iteration speed. Thoroughly recommend it to any Comp Sci / ML researchers.

Only thing I'd wish for is better control of memory layout for mutable structs, but I know that's unlikely since that's one thing that the Julia folks want to keep abstracted from the user.

???

Upcoming release: v1.3.0-rc5 (Nov 17, 2019)

We're currently testing release candidates for Julia v1.3.0

https://julialang.org/downloads/

Hacker News is just super on the ball, it out-paced actually updating the website.

Still when I built julia this morning, from the 1.3 banch, I can confirm the -RC5 label was gone.