Giving up on Julia
zverovich.net
zverovich.net
- Startup performance/memory usage
Yes, we are definitely very acutely aware of these. Julia is not currently optimized for frequently run short scripts. That's the price on pays for having to bring up the entire runtime system (initializing the compiler, RNG, external libraries etc). The good news is that there will be a solution to this soon, which is to statically compile your julia program. The area where this really comes up for most people using is package load times. We're very actively working on making that faster. - Syntax
A little subjective, so not sure how much I can say here. I can say that I'm not a huge fan of our multi-line comment syntax. It's not entirely clear what a better syntax would be though (the original issue on this had some suggestions, but some of them were worse). - One-based indexing
I think there has been plenty said on this topic, though interestingly this is one of the only times I've seen the argument made in a way that I actually agree with. That said, I do think there is an easy way to deal with this though. For packages that needs arrays of indices, it would be quite easy to define an `IndexArray` type that does the translation automatically. - String Formatting
Yep, you're right, it's a mess. It'll have to be cleaned up. - Unsafe C Interface
There's two projects (Clang.jl and Cxx.jl) which can help with this. The former automatically generates ccall definitions for you, the latter just parses the header and generates the call directly. - Slowing down in development
I'm really not sure where that impression comes from. Perhaps it is that we're adding fewer features, but rather working on cleaning up existing features. Also, I personally at least have been doing a lot of work outside
of base (particularly on the debugger). Not sure. Would love to know.The question of syntax is subjective of course. From the set {C-like, Python, MATLAB} I'd definitely like to see more influence of the first two and less from the last one.
I am somewhat confused by your discussion of startup times. Since Julia is a "programming language for technical computing", what scenario are you imagining where startup times would be a significant concern?
In most functional languages using list indices are an anti-pattern. Pattern matching and generalized iteration is a much more elegant way to handle most things you would use an index for.
The primitive collection types index at 1, but, as you said, are almost never indexed that way. I'm not sure the motivation as to why, but the fact it feels clunky to use them that way is a benefit, as it raises resistance when you're using them wrong (as indexing them almost always is).
http://www.cs.utexas.edu/users/EWD/ewd08xx/EWD831.PDF
Having worked with both, I'm inclined to prefer 0 based addressing in most cases. It's slightly less intuitive, but it generally leads to cleaner code.
I see it as rather simple. If you're listing off-sets, starting at 0 makes sense, because there'll be something there. But if you're counting elements starting at 1 makes more sense. I don't have 9 fingers offset from my first one, which I call finger zero; I have ten fingers, starting with the first one.
A set with no members is the zero set, once you add one element, you have a set of one. An empty list contains no elements. It does not have a first member, because it's empty. Add an element, and it will have one member, and it will be in the first position. Not in the zeroeth offset from the beginning.
You can the numeric names of letters of a string in an array, but I don't see that as a compelling reason for naming the first letter of a word, the letter which is at the zero-eth offset from where the word is held in memory. At best, it's a low level optimization, at worst it's just a leaky abstraction. Maybe you want to store the length of the word there (like in Pascal), for a different trade-off in terms of what is optimized.
I think you mean Dijkstra, who did say that, because of an argument with mathematicians about indexing from 1.
There's even a section about this on wikipedia: https://en.m.wikipedia.org/wiki/IJ_(digraph) subsection "technical details".
Edit: from Wikipedia[1]: "It used to be common, in particular when writing in capitals, to write Y instead of IJ."
So it's an obsolete practice...
----
0. something along those lines: http://alphabetprintables.org/alphabet_printables_cursive/up...
Starting a REPL or running a computation that doesn't take long time, adjusting parameters, re-running. Startup time may not be too big in absolute numbers but it's noticeable and adds up quickly especially if you start using more packages rather than toy programs that I used as an example.
Yes, that's one example. Also when debugging one usually uses small data sets. There are plenty of cases where runtime is short.
I think the problem is that Julia is somewhat vague on how it should be used. If it stated explicitly that it is intended to be used in MATLAB-like fashion with one long-running instance that would save people from trying to use it as Python or other dynamic language.
Intel's Math Kernel Library, which is a performant math library hand-tuned for Intel processors is zero-based in MKL-CBLAS.
It all depends on what you are familiar with, and staying consistent in use. I just use zero-based indexing in J and C and my numerical low-level work.
I have used quite a few languages whose base index could be 0, 1 or whatever I choosed. Even enumerations.
https://en.wikipedia.org/wiki/Basic_Linear_Algebra_Subprogra...
metric distance conversion chart:
cm m km
1 1.00 1.00000
2 1.01 1.00001
3 1.02 1.00002
...
101 2.00 1.00100
...
100000 1000.99 1.99999
The ratios between the values aren't fixed now; we can't go from cm to m just by scaling by 100. We must subtract, scale then add.One based indexing falls apart if you have to index a region of storage as bits, bytes and words at the same time.
Counting is indexing!
What is it that you do when you count items in a set? You put them into correspondence with the natural numbers, indicating each one as 1, 2, 3, ... The last integer is the count.
Yes, it is related to the "is the first floor ground, or the one above it"; and it's clear that some programming languages take their cue from stairs and elevators.
Nobody ever has to calculate "what is the floor twice as high as this one?" Moreover, people are unfazed by 13 missing.
(I haven't seen a language that omits 13 from indexing, fortunately.)
Is skipping the 13th floor a US thing? I don't recall ever seeing it in the UK or Germany.
And their documentation has section numbers like 1.1, 1.2, ... 5.3.3.
OTOH, for something physical that actually is indexing, or at least closely analogous to it, we could ask "what if principal quantum numbers used 1-based indexing". But, then, the answer would be "things would look exactly like they do now, because it already does."
The index is the distance from the first element. Thus, the third element is two elements away from the first, thus it has index 2.
I think the only reason zero-based indexing is not the standard everywhere is because some people (usually non-programmers) have a problem with the idea that the fifth element has index four.
I am suggesting that this is a linguistic problem that has messed up programming.
Indices can be regarded as measures. We speak about an array having a "size" or "length": that is measurement language. Something is "3 words wide": ditto.
A given record in a file can be 25 words from the beginning, or 100 bytes, or 800 bits. All of these tell us how much storage immediately precedes that record and we can easily convert among them.
If indices support calculation, they should be displacements, and displacements should originate at zero.
Indices not intended for calculation (beyond simple successor/predecessor, perhaps) can place items into correspondence with any ordered set: natural numbers, letters of the alphabet, and so on. This is where we can get away with 1 based.
Indices not intented for any calculation whatsoever can use a set: like associating character strings with objects via an "associative" array or whatever.
// Construct matrix. Elements are not initialized.
// To initialize all elements to zero use
// Matrix<double> a(2, 2, 0.0).
Matrix<double> a(2, 2);
// Assign elements to first row using
// Fortran-style one-based indexing.
a(1,1) = 0.5; a(1,2) = 1.0;
// Assign elements to second row using
// C-style zero-based indexing.
a[1][0] = 1.5; a[1][1] = 2.0;
-- http://www.b-a-h.com/software/cpp/scppnt.htmlI really like your Cxx.jl, that does seem to answer the issue raised here (are there any good features in pybind11 though that aren't already in Cxx.jl? that might be a good source for ideas on how to improve Cxx.jl if not)
(just to add: there is currently an open pull request from a core array-focused developer adding such support to base)
There is certainly a need for better interim communication on progress between releases, to let people know what is happening without reading every GitHub thread.
Now, I don't know if people from that different world (Fortran, Matlab, some other languages used in academia maybe) would feel the same way about 0 based indexing but it certainly sends the message to programmers outside those domains.
I'm not defending Julia per se. I've been patiently observing from the sidelines to see how the language shapes up.
BTW i'm a julia proponent, I'm just starting into it but I like a lot about it.
I don't see how you concluded that? http://www.tiobe.com/tiobe_index?page=R
Possibly because you're used to working with languages like C, C++, Java, Pascal, Javascript, Python, etc. But in the world of languages tied closely to scientific / mathematical programming (Matlab/Octave, R, etc.) 1-based indexing is the norm. If you'd "grown up" so to speak, in that world, you'd probably find 0-based indexing distasteful.
Switching to zero based index Java/Javascript/C felt a lot more natural (no need for upper bound, always include->exclusive when it comes to bounds). Many algorithms benefit greatly from as well (hashtables + bitwise AND, for instance)
Virtually I do not recall making off-by-one errors while working with Java. Whilst it could be attributed to personal experience, the loops construct "for (int i=0; i<length; i++)" or "for(int i=length; i-->0;)" appear quite intuitive. Strict bounds (i.e. < or >) feel more elegant as well.
Seeing, using both type of indexing, 0-based one would a winner by large margin in my book.
I am not saying 0 based indexing is technically superior (I really have no opinion on that). I could compare it to switching positions of brake and accelerator in a car - you can talk about brake on the right design being superior all you want but the fatal crashes will happen if you implement it.
It's an easy thing to discuss, and everyone is an expert. Meanwhile, the real problems get ignored.
If they're used to R, MATLAB, or basically any statistics programming/scripting language ever, not only will they be expecting 1-based indexing, they might not even know that that's a thing they have to think about.
The truth of the matter is that this is not a point that anyone should ever mention as either a pro or con of any language. It's simply a fact that you're going to see one or the other, and it's useless to complain about which one is present in any given language. It's a one-time discovery as to which you're working with. People try to make it out to be a debilitating factor, when in reality it's a non-issue.
The problem doesn't just go away with for each style loops. Python added enumerate for this reason but it really is quite clumsy for anything more complicated (and you have to choose if it's indexing from 0 or 1 anyway).
I think part of this problem is the community, multiple people have reported having bad interactions with core language devs. Also the policies for inclusion of features, how to propose features, how decisions are made with respect to the code base, etc. all seem poorly documented.
I can only think of a couple of instance where I've heard anything like this.
The first and most prominent is Dan Luu. I'm very sad about losing him from the community. I've met him a couple of times in person, I still read his blog and I very much respect him. I don't think any of us have the full story of what happened there, but I sincerely hope that time may be able to smooth things over.
The second was in an HN comment that I just went back to find, and discovered that is was you. I'm sorry if you had a bad experience with the community. I know my perspective is biased, but I've rarely interacted with a community that's as passionate, helpful and friendly as the julia community (LLVM is up there as well).
As for documenting the process, I agree there could be some improvement there. We do have a contributors guide (CONTRIBUTING.md in the main repository). As for policies for feature inclusion, we've considered having more formal code owners for parts of the code base (right now there's mostly de facto code owners for various parts), but haven't found it necessary so far. I definitely expect some of this to be discussed at JuliaCon in June.
As to the code standards, my problem isn't with the CONTRIBUTING.md; that seems fine. It's how people make long term suggestions about fixing lasting problems. As an example people who suggest refactoring large sections of Julia's expansive base library (1600 symbols? a problem that causes parts of the slow startup time and memory usage) into other libraries (which would improve batteries included, etc. features) are summarily ignored / shouted down / (predicated on my previous paragraph) banned. Important improvements to the language go in circles (often on JULEP tagged issues) especially any large improvement that would require multiple people and lots of dev work and seem to gain little traction unless a core dev just takes the time to just do it; rather than a timeline to reach consensus and then design a plan for implementing it.
As smaller examples. There was a push to increase test coverage and then months later commits plummeted the code coverage numbers and no one seemed to care. Sections of important code are uncommented, undocumented, and (mostly) untested on purpose. There are modularity problems and software architecture limitations inherent in the language design that go unaddressed. Unpredictable un-typed exceptions, namespaces/modules being hard to use for non-trivial designs, "interfaces" that aren't really. And these are just the ones without serious work behind them I can remember off the top of my head (the debugger and threading I acknowledge being worked on seriously). Though things being worked on seriously suffer problems as I mentioned earlier.
Issues like these cause many of the original poster's problems. Julia is a great language, but the community seems unable to take the steps it needs to to actually make a "Tier 1" general purpose language (e.g. like python, go, clojure etc.). Setup a serious set of policies regarding language proposals; setup a transparent community policy and actually follow it; acknowledge that certain development idiosyncrasies aren't going to fly anymore; take software architecture concerns seriously; remove the toxic core language dev (that to my count has cost you at least 4 serious contributors if not more).
Julia is likely "slowing down" relative to the expected development (which many people have observed) likely (by my thinking) because it is failing to attract/retain the developers it should be as a promising language (in my opinion) because of it's poor development and community standards.
But hey, these are just my suggestions, I don't have any skin in this game. I just wish Julia was as good as it promised to be, and I'm a bit bitter it isn't for human, rather than technological or financial, reasons.
Edit: Sorry I expanded, it felt unfair to not be more complete about it.
I do think HN is not the right forum to link to individual comments and call out people for their behavior. Perfectly happy to discuss the technical issues though. If you would would still like to discuss, or at least bring such instances to my attention, please do feel free to send me an email.
> People who suggest refactoring large sections of Julia's expansive base library (1600 symbols? a problem that causes parts of the slow startup time and memory usage) into other libraries (which would improve batteries included, etc. features) are summarily ignored / shouted down / (predicated on my previous paragraph) banned.
There are several recent examples where people have suggested such things, e.g. They were neither ignored nor shouted down nor banned. https://github.com/JuliaLang/julia/issues/16357 https://github.com/JuliaLang/julia/pull/16070
> Important improvements to the language go in circles on JULEP tagged issues namely any large improvement that would require multiple people and lots of dev work seems to gain little traction unless a core dev just takes the time to do it; rather than a timeline to reach consensus and then design a plan for implementing it.
I don't understand what exactly the criticism is. At first I thought it was about, too much dicussion, but then it seemed to be about too little dev time, please do clarify.
> There was a push to increase test coverage and then a few months later commits plummeted the code coverage numbers and no one seemed to care.
I'm not really sure which instance you're referring to, but last time there was a major drop in coverage, it was investigated, found to be a bug in the instrumentation (which was fixed). I don't really think it's fair to say that people don't care. There's somewhat of a tooling problem here, since we can't run the coverage tests on travis, so we don't get them integrated in the GitHub UI, but people do look at them and add tests as appropriate.
> Sections of important code are uncommented, undocumented, and untested on purpose.
Yes, there are undocumented and uncommented sections in the code base, but I wouldn't say that they are so on purpose. I do admit to having added such hacks in the past (and not documented them because they were gonna go away soon after), because I needed them in outside packages, but people don't let me do that anymore ;).
> Unpredictable un-typed exceptions, namespaces/modules being hard to use for non-trivial designs, interfaces without any sort of type enhancement.
These are fair points, which I'm sure you've seen the issues about. The problem is the availability of developer time, not some sort of unwillingness to fix problems. Putting together the road map of what goes into each release and prioritizing are very hard, because there's just so much that could be worked on.
> setup a transparent community policy and actually follow it;
This is being discussed (as part of larger discussions around community governance) and as I mentioned will likely be a topic at JuliaCon.
Fair enough, my problem is that the project continually looses what appear to be serious contributors to a toxic developer (admittedly all second hand to me; but there are public examples and some private reports I have; including the person who first showed me Julia years ago). For all that it is an interesting language with plenty of problems I would enjoy fixing and taking the initiative on I simply don't have a desire to want to contribute. Again mostly due to politics. Which just sort of makes me bitter you fail to acknowledge the problems.
Like why should I take lots of time (I'm fine doing hard things like reading undocumented code bases if it's worth it (large sections of the core compiler code due to it's lack of comments or documentation are hard to read)) to help you fix technical problems, when you have social problems that are noticeable to anyone paying close enough attention to the community.
Also, thanks for taking the time to listen to my rants. I'm just disappointed.
I'm perfectly happy to acknowledge that there have been conflicts in the community. However, I maintain that the overwhelming majority of interactions in the community are immensely positive. Please do also consider that there may be parts of the story that you are not seeing in the public issues. I do hope you will consider giving the community a second chance. You have quite clearly identified some of the major technical challenges we face and we'd love to hear any ideas you have to address them.
That's great but amount to a couple of functions, the larger issues addressing more serious refactorings never get off the ground (Base contains multiple thousands of symbols (not even counting how in a multiple dispatch language one symbol can contain hundreds of definitions) common lisp, by all accounts a sprawling language with multiple dispatch, has 978).
> I don't understand what exactly the criticism is. At first I thought it was about, too much dicussion, but then it seemed to be about too little dev time, please do clarify.
Both. Neither. It's about how there is unending discussion until a core dev just does it. This is not an efficient use of anyone's time. Set the scope of an issue, discuss, decide on a course of action, layout issues. This allows a core dev to get their input in place, but then not have to actually wait for them to have the time to do the whole thing themselves.
> There's somewhat of a tooling problem here, since we can't run the coverage tests on travis, so we don't get them integrated in the GitHub UI, but people do look at them and add tests as appropriate.
The number seems to fluctuate randomly from 83% in January, to 11%, 45%, 65%, 75%, 11%, 81% now. Which is a net loss and wholly sporadic. How does anyone know what to write tests for when coverage bounces all over the place? Also what good are the tests if no one takes the time to use them anyway? You have tests but they seem pretty useless with how you are using them. I understand it's a tooling issue, but a metric isn't very good if no one is bothering to use it, why waste the time to not use it.
> but I wouldn't say that they are so on purpose
"Look at the code and you'll understand." is the jist of the documentation of a 10000+ SLOC base used at the heart of Julia. Sure I could read all that, but I'd rather have a bit of documentation. Also the tests for this amount to it's examples.
> not some sort of unwillingness to fix problems
I disagree on at least 1 of them. Typed exception handling was flat out rejected because it's too much like Java by key devs; forget the fact everyone does it anyway using reflection. Interfaces and modules don't seem to make any progress because of some people complaining about similar issues.
> Putting together the road map of what goes into each release and prioritizing are very hard, because there's just so much that could be worked on.
Then stop wasting dev time and work on the community policies that make it easier to retain devs.
I have seen this point about a toxic dev been made before in some blog post. Back then I followed the story up because it seemed so at odds with my experience with the core devs. It took a bit of googling and following links, but in the end, in my mind, there was simply nothing to the whole story. The supposedly rude behavior was not at all rude, imho.
I don't really know where these allegations come from, but I find this kind of "I've heard second hand that there is a toxic dev" inappropriate. If someone has a problem with someone, make it explicit, post the email that you dislike, so that others can judge themselves. But these vague accusations are not helpful, and at least from my point of view entirely at odds with how I have perceived the behavior of the core devs over the last two years.
I should say that I'm not part of the MIT crowd. I've never met or talked with any of the core devs and don't know them beyond reading their emails on mailing lists and sporadic interactions on github.
Maybe a source of discontent is that startups are using Julia 'for real' and are under pressure to deliver. On the other side Julia is still developing. Core devs work feverishly but some issues just need 'time to brew'. Quiet thinking/coding alone or in small circles.
IIRC on a video of Alan Edelman he ~ said that he was involved in HPC for 30 years and to this day they weren't that successful and don't know how to do it. Julia is trying to do it in a completely different way. - Considering 30 years, does it matter if Julia takes 'her' time to be crowned?
But measuring performance with timing a "hello world" program? Seriously? What scenario does the author have in mind that makes this particular benchmark even remotely relevant?
The rest of the rant pretty much comes down to "it doesn't look like Python" (which is IMO a good thing, and I would certainly not call Python a "de facto standard of numerical computing" -- sure, it's there, but I still see a lot more of R and Matlab -- and note how both have 1-based indexes.)
To be fair, last time I checked, Julia definitely had some catching up to do in a few areas to become a real competitor to those two, but "hello world" benchmarks would not be among these.
It's been a little while though, and I am tempted to check again -- leaving libraries alone for the moment, does vectorization still result in a lot of performance loss compared to loops?
If Julia is to replace Python in scientific computing, people will want to use it for short plotting scripts. Startup time matters there. That hello world is so slow is already telling. A plotting script needs tens of seconds just to load the Julia libraries.
Yes, but it should be fixed in the nearish future. https://github.com/JuliaLang/julia/issues/16285
The "hello" benchmark is a fantastic benchmark for production-strength JIT-based runtimes because it tells you how long it takes for your system to warm up enough to be able to print something to the screen. You don't want this to be long. I prefer for "hello" to take about 10ms or less. In WebKit we have a few benchmarks that are the moral equivalent of "hello" and these are some of our most important benchmarks.
The reason why warm-up time is so insanely important is that any programming language, no matter what the domain is, will be used for the following things eventually:
- Tests.
- Data definitions in your language (moral equivalent of JSONP - every language/runtime has to deal with something like this).
- Initialization.
All of these things comprise run-once code that tends to be large. All of these things are important, even in math languages. The glorious "hello" benchmark is an excellent proxy for the performance of these kinds of code. So, I think that if Julia requires 300ms to run "hello" then they should make the "hello" benchmark into their primary optimization target.
Fortunately, it's easy to make "hello" run fast: just tier your JIT. This can be done with LLVM just fine, see https://webkit.org/blog/3362/introducing-the-webkit-ftl-jit/
Although we have since moved to using B3, LLVM was absolutely amazing for us, for the same reasons why it's amazing for Julia: you get tons of optimizations for a lot of targets with little effort. But you have to harness this power the right way. You can't fire up the full LLVM pipeline for code that runs once! It's a waste to unleash so many optimizations only to immediately throw away the result.
1. The static typing makes a big and positive difference. Its nice having a statically typed repl.
2. The documentation is good.
3. Using unicode symbols and \mu style tab completion is nice, especially in Jupyter where you can use the same symbols in latex style equations.
4. The base install is a bit bare. It would be nice if batteries were included - distributions and dataframes in particular.
5. R uses 1 based indexing and it was no shock to see this in Julia.
6. I had no problems with the mix of lisp and C++ in the source code. The lisp implementation is beautiful and worth a read.
Generally, I was shocked to see a blog post like this given that my first day with Julia was so positive.
I think the problem here is the library approach. They should break stuff out of Julia's core library and move them into default included libraries (like python does).
* faster start up time
* cleaner global scope
- Both Julia Computing and the Julia Lab have grown sizably over the past two years. The Lab now houses ten full-time researchers (up from four last year), with five new students coming online over the summer and fall. We also maintain more active research collaborations with more research groups at MIT and off-campus.
- Julia is a grateful recipient of 12 Google Summer of Code slots this year, compared to 8 for 2015's Julia Summer of Code program (sponsored by the Moore Foundation) and 4 for GSoC 2014.
- JuliaCon grew from 72 attendees in 2014 to 225 in 2015 and we are on track to meet or exceed last year's ticket sales for 2016.
- New packages continue to be registered on the central METADATA repository at roughly the same rate since June 2014. http://pkg.julialang.org/pulse.html
By some measures we are still a relatively small project, but I don't see any serious evidence for the imminent heat death of the Julia universe.
Original program was 50min in python, 1 min pypy
After figuring out some inefficiencies that were O(Nsquared), it was 3 seconds in python
This was timing for a case where N was much larger than my normal cases, where run time had been a couple seconds with the original version and optimization didn't really matter.
Example: popping from the beginning of a list in Python is O(N). Popping from the end is O(1). Initial poorly written code can have a lot of such obvious optimizations.
This is what is killing me when I use Python. So hard to run things in parallel.
I have had luck with Go trying to do this and set up a concurrent application.
But, I think judging a language (which claims math and scientific computing is it's strongest point) by print screen performance is not fair.
And, the authors last example is a little bit misleading I think. The C code sets up registers and jumps to the main sprintf routine. I don't know why didn't he tell that routine's instructions count...
Has any one counted?
You pay for it by having the compiler JIT the code in a highly optimized fashion. If you have actual numerical calculations that are compile-once, run-many-many-many-times, then you will see a huge performance benefit, amortizing the cost of expensive compilation and optimization that happens once at the beginning of the program cycle.
The very title of what he links to "How To Make Python run as fast as Julia" betrays the problem. The goal of Julia is to not have to do that sort of boilerplate/arcane tweaking to get really good performance - the system will do it out of the box.
I'll have to disagree with the notion that Julia is hard to read. I'm currently deploying Julia to run automated hardware verification on a computer chip. Effectively, I've written a DSL using Julia macros that generates assembly code files, compiles, and executes it, and my coworkers (who do not use julia) have found it easy to read my code and understand what's going on. Far easier, in any case, than the equivalent C code using asm blocks.
I do agree about the one-based indexing. I get it, it's what matlab does. But it would be nice to say, be able to throw an option at the top of a program that forces the appropriate indexing.
I agree, and I haven't found anything like this in other (non-exotic) languages. I recently wrote a function using the @generated macro to produce Wigner-D matrices via the recursion relations. The function dispatches on the size of the matrix (using Type{Val{N}}) and after it compiles once for a particular value of N, all future calls are blazing fast (since the machine code is essentially just a long list of multiply and add instructions).
As someone who is new to python (for bioinformatics), and find python is a fine language... but..
The do it "this way not that way" method of implementation of the same algorithms to get it to run fast makes writing performant python a tedious exercise in research and profiling. The article cited suggests Cpython, numby and numpy [1] as ways to make it faster.
Why not C using GPU acceleration as the time spent coding would probably be the same? Thats what I love about plain python, its fast to write and has some good data structures.
I haven't tried Julia, but someday its on my list of languages to learn more about.
[1]https://www.ibm.com/developerworks/community/blogs/jfp/entry...
As someone who does that sort of thing I can assure you it isn't. And when I do use C and GPU acceleration, doing so via cython and pyCUDA (and the myriad of libraries that build on cython and pyCUDA) saves massive amounts of time and effort.
That being said I do agree that writing fast python is quite different from writing python, probably more so than in most other languages.
jmp __sprintf_chk
I would guess that another few hundred instructions run as a result of this jmp. Thus, the difference in the number of instructions that C's sprintf and Julia's @sprintf compile to are not as drastic as the author makes it seem. $ julia -e 'f(a, b) = @sprintf("this is a %s %15.1f", a, b); code_native(f, (AbstractString, Float64))' | wc -l
WARNING: Returned code may not match what actually runs.
628
$ julia -e 'f(a, b) = @sprintf("this is a %s %15.1f", a, b); code_native(f, (ASCIIString, Float64))' | wc -l
194
$ julia -e 'f(a, b) = @sprintf("this is a %s %15.1f", a, b); code_native(f, (UTF8String, Float64))' | wc -l
194You can not only easily create parallel tasks on your machine, but on any machine that you have ssh access to that also has Julia installed.
That is simply amazing. Until something else can do that, Julia is going no where but up in my mind.
A) the author is entitled to all their opinions and experiences and
B) raises some good points (see Keno's comment) but
C) raises some subjective (syntax, etc) and odd (measuring performance by timing a one line hello world) points.
Julia is not the right hammer for all nails, but I use it every day and enjoy doing so. If you're on the fence, I encourage you to give it a try. And for what it's worth, end as a keyword aside, I really like the syntax, particularly :: type decorators. Your mileage may vary.
The error bars show it's probably slower, but i'm pretty sure he's not going to get valid measurements to 0.002s by running it once with time without doing things like disabling CPU throttling, etc :)
Of course, looking at julia's microbenchmark for C, they had to do a bunch of things to get the compilers to stop optimizing away their benchmarks, so that should tell you something right there :)
The example they give of sprintf calls is completely misleading, since sprintf_chk is going to be several hundred instructions itself.
Follow https://github.com/lattera/glibc/blob/master/debug/sprintf_c... all the way down the rabbit hole :)
For what it's worth, my impression of Julia has been overwhelmingly positive, and all the developers I've interacted with have been polite and friendly. I haven't made the switch from Python because:
- I prefer the Python syntax
- I like Python libraries (I know about PyCall, and it rocks)
- The increased speed of Julia doesn't really add much given numba/theano and so forth
However, I really like:
- Optional static typing for sanity checking
- Can write fast functions directly in julia - which is handy when passing callbacks or doing numerical routines like integration (although this requires timholy's fast lambda package)
Not on nightly. That's fixed now. The technical concerns here about startup time etc are fixable, we'll get to them.
On the other hand everyone knows that Julia is 0.x which means that while this is the IDEA of Julia it's still not claimed as the reality - although my experience (and some other people) is that it's pretty true most of the time.
Matlab used to have the same problem, and they even used to have docs on how to vectorise. When I first learned Matlab in 2004, they told me, "don't use loops". Twelve years later, you're supposed to write all the deeply-nested loops you want.
So yes, most Matlab code out there is loopy, so it's slow in Octave. But if you write it for Octave and don't make it loopy, it's quite good.
After I switched to Python/C I can say that I never want to work with 1-index languages again.
I've used several languages in both camps, and you know what? When I'm in Matlab I start my indeces at 1, and in C i start at 0. Who would have thought it would be that simple!
I think dynamic typing has its place, but more in experimental design and prototyping than in bigger application development (big IMHO).
So its popularity is really historical incident, in particular I think, that it was the first hack (see worse is better) to allow to easily deploy dynamic web applications (via web-server side interpretation of code, which got popular in Apache). Furthermore PHP hosting is still very popular in low-cost bundles to integrate e.g. Wordpress.
Clojure is another nice language, but could benefit from typing. :p Maybe the main "problem" for dynamic languages ist the fact that it requires more discipline on the Programmer's side, so I imagine it is popular for smaller teams, but this is hard to achieve for bigger development efforts, where you can benefit from a stronger type system.
This is why I wish Groovy with it's combined static / dynamic typing abilities was a) better and b) more popular. Its ability to interweave static and dynamic typed code is really spectacular when it works. Unfortunately there are a lot of holes and it can still be quite painful when in static mode, so I mainly only use it for performance rather than as I would like to - as the default mode.
Having said that, I've actually since found Clojure to be better than Groovy at testing Java classes. A well-placed macro can often cut out syntactic clutter when testing some repetitive scenario.
1. You can detect very common errors (e.g. typos) at compile-time instead of maybe detecting them at run-time. This makes the code much much more reliable (or equivalently you don't need to do nearly as much testing).
2. Dynamic typing prevents IDEs from doing extremely useful things like real code completion and symbol renaming.
If you're thinking "but I edit Javascript with code completion" or "code completion isn't such a big deal" then it's probably because you've never used accurate code completion, e.g. Microsoft's Intellisense for C++, or pretty much an Java IDE.
1) Common Lisp implementation use a compiler to detect typos, etc.
CL-USER 21 > (defun bar () (fo0))
BAR
CL-USER 22 > (compile *)
The following function is undefined:
FO0 which is referenced by BAR
2) In Common Lisp one can ask the running Lisp system for information about classes, symbols, functions, etc.The use cases for renaming are also completely different. If you take for example a Java class and you want to rename an attribute and update the getter/setters you might want to use a 'tool'. In a dynamically typed language like Common Lisp, this is often not necessary because code generation is widely used and changes can be propagate that way.
(disclaimer, I have never been in the Army or any military force and the above post is based on my imagination and watching films)
Neither approach is wrong, but most developers have (sometimes very strong) opinions on which is the right way to do it in various different cases.
That's not true if you seriously unit-test your code base, which you should in both cases.
Strong typing is awesome. I personally think that dynamic typing is wonderful, too, but opinions vary about that.
Also I love that first alphabet image on that page.
setting aside whether zero- or one-based indexing is 'better'; R and MATLAB have one-based indexing, so the convention is likely familiar to many in the Julia target audience.
still, as the OP says, (relatively) painless interoperability with C and C++ is an advertised Julia feature, both of which use zero-based index (although Fortran is one-based), and that mis-match is a definite obstacle to interoperability.
The last set of programs I wrote in julia had run times of hours to days. A few extra seconds of startup time is well worth the 10x or better improvement over using python for the same tasks. The code was also tighter and easier to understand. A win all around.
I did enjoy the article and the linked article that spelled out ways to increase performance with Python. With any environment there are dramatic performance improvements to be had with a little bit of engineering and knowledge.
I've seen a bit of an odd shift towards Julia - People seem to be adopting it in droves from my perspective. That means that the development team is doing something very right. Given some of the people I've heard talking about Julia, I don't think it's going away any time soon.
This kind of feedback is good for the team. If you are going in another direction for the time being, stating why is always helpful. Glad to see a developer here in this thread.
Python can be a very useful mess for this sort of work (numerical analysis etc.), and is succeeding at that quite well. In fact, that's it's main challenge to something like Julia. Not design, that ship sailed a long time ago. But practicality and availability of packages and bindings. Once you get too far ahead in that, it's hard to justify using any other platform for "real work", rather than because it's fun to hack on.
What are these design principles in Julia that Python can't possibly uphold?
What's specifically better about Julia here?
With Julia is it more well defined when your code is fast. Write type stable code, according to these guidelines...
http://docs.julialang.org/en/release-0.4/manual/performance-...
and you code will be going fast. Specifically, @code_warntype tells you when your code is going to be slow.
I don't think the Julia team should be blamed for anything. I have not heard of the project receiving any support from large companies as Python, Golang and Rust do.
For this reason, I find it very unfair to compare Julia to these languages. FYI Julia has not even reached version 1.0 yet!
The language just needs support, and the author is not helping out.
It has static types and is fast. The libraries for scientific computing are not there yet, but it lends very nicely to mathematical abstraction.
This is going to be a tough sell for any data analytics work.
(Not trolling, genuinely curious).
You can manually allocate memory if you want, and you can also pass pointers, either to manually allocated or gc memory. The gc will not run when c is working, since it is triggered by allocation
For such cases, you can either manually allocate the pointers you pass to c, or temporarily disable the gc. Each thread has its own heap, so gc for one thread does not break anything in other threads
(C++ has such a trivial FFI, as well as non-GC languages which compile to C code... there may be more as well)
You mention non-GC languages. Are there any GC languages that do? :)
Not an expert on these things by far but I remembered painless use of C in that language and it's GC'd. Thoughts?
But if anyone knows of counter examples, I would be interested in them as well.
Which I'd still consider trivial...
Manually managing the memory that the GC "owns" doesn't fit the bill in my definition.
"I became very enthusiastic about it."