
The Julia Language Challenge - simondanisch
https://nextjournal.com/sdanisch/the-julia-challenge
======
setr
If I understand the helper code part correctly, libraries are banned? That
makes the challenge quite pointless, as it doesn’t even pretend to be
equivalent to “real world” usage. All it can show is the julia language has it
by default... but not whether the language’s design actually leads to
something more clean, readable and sufficiently fast than what would
“normally” be done in other languages.

It doesn’t really matter if python doesnt have as powerful an array syntax as
julia, if I can pull in numpy (a standard, battle-tested library) and produce
equivalent (and good) code.

But if I pull in numpy, and _still_ can’t produce code as nice as julia
(because of whatever limitations of python as a language), then there’s an
argument to be made for switching to julia.

But going purely off what the language gives by its initial installation...
its just an arbitrary limitation to give the question one answer.

The article claims that it proves the point ... "This can be unfair since
Julia has lots of functionality for array algorithms built in, but also
illustrates the point" ... but assuming good intentions, I'm not sure what
point that is? At best, you might be comparing APL languages to one another,
but nothing broader than that.

~~~
ingenieroariel
The way I have experienced it (with Javascript, Perl, Python and Matlab) is
that many casual users give up whenever you mention packaging. Any language
that lets people go very far without involving external modules will get
significant usage from amateur programmers.

~~~
setr
Hell, so do I; I absolutely hate learning new package ecosystems &
infrastructure (but I absolutely do not have interest in learning a language
without a decent package infrastructure). Probably a bigger blocker for me
than learning the language itself!

But it's not clear to me that this "challenge" is intended to say that array
operations are easy, for a _newcomer_ to the language. As I understood it,
it's an argument for Julia being better in the _long run_ , for the code that
requires "developer effort, performance and extensibility"; that is, elements
of the language beyond the first few days of using it, for packages larger
than what would be written by "amateur programmers"

If depicting usage for the amateur was the main point of the article, it
totally went over my head

~~~
simondanisch
>If depicting usage for the amateur was the main point of the article

You understood that right, it is not :) That's why I wrote, that I'd probably
need years to create the same implementation in any other language.

I do think it does have a widespread implication for the ecosystem though, and
therefore at some point will also be relevant to newcomers.

------
Xcelerate
As someone who has used both languages extensively over the last 6 years
(Julia for grad school research and Python for my work as a data scientist),
I'm always surprised at how quickly people rush to defend Python. "Yes, you
can do that in Python too using such-and-such library or with this hack..."
Don't get me wrong — the numerous Python libraries are impressive, but at the
end of the day, for me personally the experience of using Julia is just far
more pleasant than using Python. It seems as though I'm always fighting
_against_ Python to accomplish something, whereas with Julia it feels like the
language just gets out of the way and lets me do what I want.

~~~
ummonk
Yes, so much this. I want to be able to write simple idiomatic code without
having an insanely large (10x-1000x) overhead. That just doesn't happen in
Python.

------
jacquesm
There is something that puts me off about all these languages that want to
show off their own strengths by pointing at other languages weaknesses. X in Y
is another such pattern, who cares what 'X' is written in, the question is
does it perform well, does it serve a need and is it maintainable and secure
if it is network facing or otherwise employed in a situation that would
require the program to be locked down properly.

Setting up an artificial challenge with rules that favor 'your' language up
front is a great way to get the result that you want, but not a great way to
learn. Each language has its strengths and its weaknesses, but none of those
strengths and weaknesses matter all that much from the point of view of an end
user until they have a direct impact on the quality of that which is produced.
And programmers have shown time and again they can write crappy code in just
about any language (and good code too...) with the language features having a
much smaller impact on the outcome than the quality of the people writing the
code.

~~~
simondanisch
I must admit, that I find your sentiment very understandable! It is an
egoistic challenge, after all. For me the problems I describe are highly
relevant, and I'm very curious about any solution that isn't written in Julia.
And I do think, that those challenges are also highly relevant for a large
part of the scientific computing community. So whatever language excels at
those should get proper recognition;) And I do believe, that if you can
implement a hard problem efficiently with little effort and not that much code
and still have it composable, that it will very quickly influence the quality
and user experience for the end user.

------
geoalchimista
> Use Python + Numba, Python + C, Swift, Cython, Go, Lua-Jit, Rust, D -
> surprise us!

I'm familiar with Python scientific ecosystems and currently learning Julia
and Rust. As far as I see it, these languages likely do not compete well with
Julia on _all_ three categories --- "developer effort, performance and
extensibility" for the problem you picked, because none of them was designed
for native array arithmetic with broadcasting in the first place (except Numba
maybe).

The current dominance of Python in scientific computing is rather a beneficent
coincidence, because most people were pretty fed up with C++ and legacy
Fortran back then, and efforts to improve tools of the trade tended to
converge on Python. Fast forward 18 years after Python was born, Julia came to
light and it was _designed_ to do numerical tasks fast and elegantly and to
avoid some pitfalls of "scripting languages". Does the success of Julia in
these tasks signify the incompetence of Python? I don't think so. It served
well what it was designed for. And if you tell me Julia is the right track of
the history, you'd have to wait for it to happen. (Don't get me wrong, I like
the Julia language and use it for a side project. I just don't see bashing
other languages to prove that Julia is the one language to rule them all would
be fruitful.)

On the other hand, I'd say you forget to count in Fortran 2008! For
broadcasting with multithreading, Fortran + OpenMP works pretty well.

------
oxinabox
I think the point is to be able demonstrate the ability to implement high-
level abstractions, in a very composable way, that doesn't cost on
performance.

------
HankB99
Am I the only one who sees a big PR push for Julia? Up until a few weeks ago
I'd never heard of it. Not I see it all over, frequently touted as the "one
language to rule them all."

~~~
bbatha
It hit 1.0 about a month ago. Its always been a pretty exciting language, but
it was hard to seriously use it without stability for an ecosystem to build
around.

------
evincarofautumn
So the actual challenge is to provide a means, in your language of choice, to
write an arbitrary expression like:

    
    
        user_defined(x) + y + z
    

Which may mix matrices ( _x_ ), vectors ( _y_ ), scalars ( _z_ ), and
_user_defined_ or built-in (+) functions applied elementwise; has automatic
extension of dimensions; and must operate in a single pass, performing only
one traversal.

This problem statement is rather tailored to Julia’s way of doing things—I
don’t believe any other language can really “succeed” as a result, and not
because Julia is any _better_ (nor worse).

In Haskell I might simply rely on laziness and rewrite rules for fusion, or
reach for a package like repa¹ or folds², depending on the actual problem at
hand. There wouldn’t need to _be_ a library providing this “broadcast”
functionality, because it can be expressed already with other composable
tools.

If you work with the language and type system, there are lots of tools
available for giving the compiler enough information about the structure of
your code to guarantee good performance, abstracted behind a reasonable API.
You might end up writing something more explicit, like:

    
    
        zipWith3 (+) (userDefined <$> x) (extend y) (extend z)
    
        -- With MonadComprehensions + ParallelListComp
        [ userDefined a + b + c
        | a <- x | b <- extend y | c <- extend z
        ]
    

But I’d be perfectly happy with that, since it uses abstractions like functors
and monads that I already understand. I probably _wouldn’t_ reach for the
direct equivalent of this Julia solution, which would be to write some
Template Haskell macro that rewrites an expression to insert dimensional
conversions (“extend” in the pseudocode above) and fusion of operations—that
approach feels too brittle and difficult to extend, and not because of any
deficiency in the language.

¹
[http://hackage.haskell.org/package/repa](http://hackage.haskell.org/package/repa)

²
[https://hackage.haskell.org/package/folds](https://hackage.haskell.org/package/folds)

~~~
simondanisch
>There wouldn’t need to be a library providing this “broadcast” functionality

Actually, your sample "solution" is (was?) also a much used pattern in Julia -
especially before we had such a powerful broadcast implementation.

So in Julia there is no need either, since it is already implemented much
better in Base. I think you're overlooking the actual point of my challenge:
it's not that we need a broadcast package, but that a lot of other scientific
libraries will need to use similar patterns, to write new packages with new
algorithms!

The point is also, that I can go into the Julia repository, and without a lot
of time & effort, can improve the current implementation of our broadcast -
because it is not that much code and pretty easy to follow.

So, an equivalent in your example would be, if you can quickly implement
something like repa or folds in a similar minimal example like my Julia
implementation.

If you don't like the details of my challenge, feel free to make a minimal
folds implementation from scratch, and show me that the result is fast and
composable ;)

~~~
simondanisch
>Actually, your sample "solution" is (was?) also a much used pattern in Julia
- especially before we had such a powerful broadcast implementation.

To add some more historical facts to this: before broadcast, we mostly used
maps & zips in Julia. Which is not very elegant if you want to write down your
math. Even with broadcast, some math nuts still complain that it isn't close
enough to the actual math :D So consider, that those people are Julia's user
base ;)

And then, someone pretty much implemented broadcast in their freetime and
added it as a PR to the Julia language. This is how the language grows, and a
large part of that is possible, because it takes relatively little time to
come up with a performant implementation of such a difficult problem.

And now we have broadcasting in the language, and maps + zips are indeed less
idiomatic... Because anyone who started using the new broadcast immediately
thought it was an improvement to "the old ways".

------
ummonk
This seems very finely tuned to the Julia language (i.e. relying heavily on
meta-programming). It's not clear to me that strong support for meta-
programming is actually that necessary for every day use cases.

I'd be curious to see what kinds of implementations someone could come up with
in CUDA using templates, though. It could easily blow the Julia performance
out of the water.

~~~
ChrisRackauckas
How could it blow the Julia performance out of the water? Julia is just
manipulating the generated LLVM IR, and LLVM generates the .ptx. If C++ and
Julia are both using LLVM for this compilation, you'll get to pretty much the
same place.

And this is tuned towards package development, specifically generic package
development. This is quite a hot topic in scientific computing. The challenge
isn't for people who use packages, it's for people who develop packages and
are looking to make them generally useful (i.e. not just single project).

~~~
ummonk
You can certainly use a GPU package for Julia with macros for generating ptx
code. That's not what the OP did though. He merely optimized for using SIMD,
which provides Julia a distinct advantage over other languages with strong
metaprogramming, such as C++. But if you care enough about performance that
you focus on the performance benefits of SIMD over ordinary execution, you
probably should be using the GPU instead. By using CUDA (not C++) as the
language, one can get far faster performance right out of the box.

Thus, a much fairer comparison, if we care so much about performance that non-
SIMD execution is a non-starter, would be CUDA vs. Julia targeting the GPU.

Note that I absolutely love Julia because I find it far easier to write than a
language like C++, but idiomatic Julia code still has low overhead, unlike,
say, Python, which introduces orders of magnitude of overhead compared to low
level languages, and you have to move away from simple idiomatic code to
achieve reasonable performance. However, I find it unreasonable to focus on
SIMD performance - the performance gain over non-vectorized code isn't that
big, and if you do want to eek out that much extra performance, you should
focus on using the GPU.

~~~
ChrisRackauckas
>But if you care enough about performance that you focus on the performance
benefits of SIMD over ordinary execution, you probably should be using the GPU
instead.

That's not true. There's a lot of heavily serial algorithms which do not
always work well on the GPU unless they are of a very large size, larger than
most applications. This happens a lot in optimization and differential
equations, two of the pillars of scientific computing.

>Thus, a much fairer comparison, if we care so much about performance that
non-SIMD execution is a non-starter, would be CUDA vs. Julia targeting the
GPU.

Tim already wrote that article where it shows how Julia code generation can be
faster in some instances for GPUs. [https://devblogs.nvidia.com/gpu-computing-
julia-programming-...](https://devblogs.nvidia.com/gpu-computing-julia-
programming-language/)

>but idiomatic Julia code still has low overhead

Where?

~~~
ummonk
>That's not true. There's a lot of heavily serial algorithms which do not
always work well on the GPU unless they are of a very large size, larger than
most applications. This happens a lot in optimization and differential
equations, two of the pillars of scientific computing.

And those situations tend to get a very minimal speedup from SIMD.

>Tim already wrote that article where it shows how Julia code generation can
be faster in some instances for GPUs. [https://devblogs.nvidia.com/gpu-
computing-julia-programming-...](https://devblogs.nvidia.com/gpu-computing-
julia-programming-..).

Yes, that's great, and would have made for an interesting challenge, rather
than focusing on SIMD instead of serial or GPU performance.

>Where?

I didn't word it well, but I meant to say that Julia doesn't have much
overhead compared to C/C++, unlike Python (what overhead it does have comes
from garbage collection).

------
UncleEntity
So...impossible challenge then?

~~~
quickben
Looks like it. Section 4.1 eliminates lower level languages on code size, and
4.2 eliminates higher level languages on performance. The challenge in C form
would be:

Create a better string copy way:

    
    
      while (*d++ = *s++);

~~~
simondanisch
as i said, if it makes sense, i'd totally allow using external libraries!
maybe i should make that clearer since quite a few people get hung up on that

~~~
quickben
A few of us perceive it as unrealistic, because it's too restrictive. C/C++
are general programming languages and I feel I am flat out eliminated before
even starting. So if you didn't target the general programming languages, who
did you want to target with the challenge?

Also, heck, it's a challenge, we all want in, please make it so :)

~~~
simondanisch
Makes sense. I will try to update the article! Feel free to use whatever
library that helps you to compose your program nicely. It would be nice
though, if those libraries were in a set of standard libraries ;) If you need
to implement all helpers yourself, my point "in Julia, you can just sit down
and start implementing a pretty difficult problem" would become a bit watered
down... First of all, Julia is also pretty multi-purpose - and secondly, if
you put it to the extreme, you could just write a DSL that you parse in C++
that is perfectly tailored to the problem, and consider the challenge as won
:P

~~~
quickben
Yes but, then we can draw some scientific conclusion.

If I can outperform Julia by 50% in C++, but I have to write 10x code. I won't
bother with C++.

If you manage to have that in the end, that's a very valuable promotional
information.

For one of my master courses, I had to write 200 lines in python. C++ solution
would have been in the thousands. My colleague solved it in 10 R lines. R is
on my list now :)

------
skinner_
> Even Tensorflow and Google have acknowledged this, and are trying to rewrite
> Tensorflow in one language, namely, Swift!

Come on.

~~~
simondanisch
What is the point?

~~~
Retra
The point is not to compare oneself to famous people or groups to score cheap
authority points.

~~~
simondanisch
Ok fair enough - maybe this is just my bad english, let me know if you have a
better way to phrase it.

I do think, that it is quite showing, that google + tensorflow don't believe
in the mix of python + c/c++. I've been working quite closely on the
challenges that faces machine learning libraries at the moment, and I can
totally see where they're coming from when they're unhappy with the current
solution and want to rewrite it in swift. How should I express this in a
better way?

