Even if Julia wraps a library like Tensorflow, its API is looking really nice compared to Python [1]:
using TensorFlow
sess = TensorFlow.Session()
x = TensorFlow.constant(Float64[1,2])
y = TensorFlow.Variable(Float64[3,4])
z = TensorFlow.placeholder(Float64)
w = exp(x + z + -y)
run(sess, TensorFlow.global_variables_initializer())
res = run(sess, w, Dict(z=>Float64[1,2]))
Base.Test.@test res[1] ≈ exp(-1)
[1] https://github.com/malmaud/TensorFlow.jlIt looks like there are the beginnings of both of these in Julia:
Part of this is why we did JuliaDB: http://juliadb.org/ and continue to try push the boundaries on parallelism, missing data, OnlineStats.jl and making data manipulation and modeling that much easier.
I've joked before, about how there is no such thing as a "One Language To Replace Them All", however, I feel Julia is the best candidate for the "One Language To Rule Them All", since while it solves the "two-language" problem in many cases, you can use it bind code written in many languages together (hopefully in a bit nicer fashion than the "One Ring" bound the other rings and their users!)
I could see something like Julia earning a lot of mindshare if it had a really polished solution for the space between, “my data is hundreds of megabytes”, and, “my data is hundreds of gigabytes”.
Moving to a new language has more friction than basically anything else unless there's a real language feature missing or the budget doesn't allow for more compute hardware. Hundreds of gigabytes is well below where academic and industry labs will start having to think about these problems. It's going to be really tough to displace Python with anything equally as general purpose.
This is all to say that I buy that Julia can shine more than Python for I/O bound HPC, but it really shouldn't be I/O bound until you have terabytes of data (and likely tens of terabytes). And aside from that, the Python numerical computing ecosystem includes a lot more than just Numpy and Pandas. As other commenters have mentioned, you can use Dask if your hot data has grown into the terabyte range. Anaconda includes a lot of libraries which can bail you out of situations once you've left the familiar world of Pandas data frames.
Even highly tuned c++ code spends most of it's time on the CPU waiting on cache misses. Its a pretty exceptional usecase where your code is not IO bound
Then because putting all those dots can be unwieldy, there's the `@.` macro which puts a dot on all your function calls.
I think it's useful to differentiate between an operation which is purely CPU bound (i.e. it's just constantly calculating without a reference) and an operation which is cache bound (faster than memory but still bound over the CPU). But calling operations I/O bound when they're sufficiently optimized that they live in the cache and don't even hit memory, let alone disk is an abuse of terminology. In the context of what I'm talking about, most HPC is absolutely not I/O bound unless it's using SATA/SAS drives instead of cache and memory.
And circling back to my original point, most research labs which can afford it will sufficiently optimize their code and hardware so that they don't hit the disk unless they're working with terabytes of data. Python, C++ and R provide numerous packages between the three of them for numerical computing across each of these bottlenecks, so I don't think Julia can rely on differentiating itself by shining in an I/O bound setting (i.e., waiting on disk). And if it does, "hundreds of gigabytes" isn't really the data size in which people are (in my opinion) going to overcome the friction of a new language and ecosystem just to harvest those benefits.
In a compute-bound workload the CPU spends the bulk of its time actually retiring instructions, not stalled waiting on data.
Think about it from the perspective of what the FPU sees -- once it has done that FMA operation, does it have the data it needs to do the next one, or does it need to sit on its hands for a while?
The cache hierarchy, cache-friendly data structures and algorithms -- they all aim to reduce time spent waiting on IO.
Theoretically speaking we can model any process as one which has to wait and one which doesn't have to wait. But in modern usage we have a variety of types and speeds for reads and writes. When I/O simply means reads and writes, you lose all the practical granularity you'd otherwise get by decomposing the reads/writes into different bottlenecks. It's philosophically elegant, but practically unhelpful for optimizing HPC and distributed systems when, as the responder said, it's rare to be CPU bound.
I also think that the context of my original comment is pretty clearly using I/O in the modern sense of disk usage. Responding with a correction that everything is I/O bound is vacuous, not insightful.
Not when solving (partial) differential equations, which is what I am using Julia for.
Used to be you could count cycles, now that's only really true in the simplest of cases with trivial memory access patterns. Now high-information branches are much more expensive than cycle counting would have us believe, ditto pointer-chasing.
Operations waiting on the disk are "disk bound", IO bound is the generic term for data access, instead of cpu processing, being the bottleneck (which is usually the case, just a question of where).
I agree that Julia probably doesn't have a huge advantage, that said, having been stuck with slow Python code before, you're often stuck with rewriting large parts of the system in c++ or another low level language. That's the reality of Python, but at least it's not the most painful thing to do.
https://en.m.wikipedia.org/wiki/Gustafson%27s_law
For instance.
There's also Dask [1], a native Python framework for distributed computations (by Anaconda). Irina Truong gave an excellent talk at PyCon 2018 about it [2]. I had never thought to look into Dask because Spark worked well for my use cases, but it has a lot of advantages over Spark (e.g. speed -- it's faster and more lightweight than PySpark and has no JVM serialization overhead) if you're using Python. Dask also runs on Kubernetes clusters, so scaling is not an issue.
And yeah, a huge amount of important data analysis work will continue to be done on data that fits in memory. Data analysis on distributed datasets is important, but from what I can tell, outside of certain domains it's certainly not the majority of the data analysis work out there.
And my (very crude) understanding is that the stronger type system makes this much easier than in Python. The compiled version of any function is specific to the types of its inputs, and thus need not contain any further checks: simple functions often end up with literally the same assembly as C would produce.
The example I usually use is allowing integers to overflow, instead of automatically promoting to arbitrary precision (Python), or converting to a sentinel value (R). Integers are used in a _lot_ of places, so inserting these checks (or worse, access to heap-allocated memory) makes it difficult to optimise. (throwing an error might be a reasonable alternative in some cases).
Another is that you make it easier for the compiler to figure out things about an object, such as its size (e.g. you can declare the types of the fields of a Julia struct) and whether or not it can be mutated (immutable objects are easier to optimise).
IIRC Julia used to automatically promote integers, is this the main reason why this was dropped?
If an operation involves two different integer types, they do promote to the larger one (i.e. an Int64 + a BigInt will give a BigInt).
https://www.youtube.com/watch?v=qCGofLIzX6g
https://www.youtube.com/watch?v=HStF1RJOyxI
Take everything mentioned in these videos that make Python and R really hard to optimize and don't do those things :D
https://julialang.org/blog/2012/02/why-we-created-julia
https://discourse.julialang.org/t/julia-motivation-why-weren...
I don't expect anyone who has not spent a lot of time with Matlab to "get" it.
Has the language improved dramatically in the last few decade?
I don't think it is likely for a software engineer to understand Matlab's niche and effectiveness. It comes from a different direction.
A ball point pen, a paint brush and a piece of drafting graphite all have their uses.
It also has the drawback that most of its users generate write-only code, so everyone that learns it also learns to write code that way.
https://cheatsheets.quantecon.org/
You can go as far as to say that Python is verbose in many cases, and non-intuitive in others (A @ B?).
That said, you would never want to write a webapp in MATLAB, so as people expand from "math scripting" to "programming" they run into MATLAB issues which have absolutely no good solution. This is where the Python pickup comes from: it's still decent for scientific computing, but it also is an actual programming language. However, Julia keeps the nice syntax of MATLAB in the mathematical domain, keeps the technical computing focus of its community, adds some speed, and also is a general-purpose languages where webservers etc. are being written. In that sense, Julia is a really good fit for people looking to ditch MATLAB.
(A lot of MATLAB's bad syntax was bolted on later. It started as MATrix LAB, and later became a programming language. You can easily see the elegance of its initial design, and the terrible choices when extending it.)
[A, B]
concatenates two matrices/vectors, whereas in Python it "wraps" them in an `n+1`-dimensional "matrix".That said, you get most of what you want with libraries. In NumPy you won't write
[aRow + bRow for aRow, bRow in zip(aMat, bMat)]
because you'll just call `numpy.concatenate`.Also, Python is mostly not used for mathematical work, and programmers tend to assume matrices are scary or only useful for mathematical work, so it has a "boring" syntax more suited for operating on single items at a time, with lots of loops.
https://cheatsheets.quantecon.org/
Python works, but it's far from elegant in this domain.
I think that is a necessary trade-off for Python as a "general-purpose" programming language. I had used MATLAB and IDL quite intensively before I moved on to Python and R. When writing MATLAB, I felt like a scientist and did not have to bother with programming practices, like coding style, unit tests, writing functions instead of scripts, etc. But Python forces me to think like both a scientist and a programmer. (For example, every time you write `np.array([1, 2, 3])` instead of `[1, 2, 3]` it reminds you that array operation is not a free lunch offered by the language; it comes from the NumPy library. Also, it keeps the namespace pure.) I personally like this way better. But I also agree that not everyone likes it. (In my institution, researchers are kinda split half-and-half between Python and MATLAB.)
Also, if I'm just restricted to using Pandas on a laptop or small server instance, then loading in a several gigabyte csv file can really tax the memory.