Not so long ago I discussed my experiment to learn the X10 programming language as part of my “learn one programming language per year” project. Having constructed my first non-trivial application in X10 recently, I am now ready to make a preliminary opinion about its usability and the pros/cons. With that said, let’s take a look into one possible future for concurrent programming.
X10 follows the Partitioned Global Address Space (PGAS) model that languages such as Unified Parallel C (UPC) before it have taken. Thus like UPC, it has global arrays distributed over processors, but unlike UPC, the semantics of these arrays are quite a bit different. This is because computation is the first-class citizen of X10, while data is a second-class citizen. Don’t get me wrong, data operations are done very nicely in X10 (with great support for multi-dimensional arrays), but fundamentally this appears to be in order to make computation that uses this look nicer. With that, computation is really nice – if you want to run some code at a particular thread/process (known in X10 speak as a ‘Place’), just say
and you’re good to go! But since data is a second-class citizen, making sure that the data you want is available at the right place or how to move it there is the big paradigm shift that X10 requires you to learn.
In my particular case, I was converting some MPI code that I had which was doing a distributed power method computation to X10. Like when I converted this code to UPC in order to learn it, a similar (but certainly not the same) inversion of thought is necessary in order for me to do this. And inevitably, another inversion of thought is needed to change that code into something that runs quickly. But that’s not a bad thing – it’s just the learning process associated with a new programming language.
A while ago I was stuck in a vi/emacs of GTFO mindset, and being in this mindset made X10 development very difficult. I had initially run into X10 at a developer day IBM put together back in March and thought that it was different from what I had seen before but not too different, such that it might actually be a language I could get real work done in. However, X10 falls into a similar level of verbosity to C#, which is just enough where vi is a bit counter-productive. So having got over that mentality since my initial encounter with X10, I embraced Eclipse (but just for X10 development so far) and was able to really get into it. Thus, throughout this project, I was inherently at a disadvantage of having to learn both Eclipse and X10 – the interaction of which is a big part of this review.
With that said, I was able to complete my Power Method code and run it over a cluster of machines (as one of the backends compiles to MPI).
What I liked: * In many cases, X10 is more succinct than Java, and the type inference for immutable variables (vals) does a good job. If you’re using mutable variables (vars), however, you still have to specify the type by hand, which is about the same amount of code as Java. * Back in X10 2.0.6, the tutorials were the best I have every seen – in Eclipse there was about two hours worth of tutorials explaining all the new concepts and what differs from Java. They made the language easy to pick up since there were many things that could be molded into the code I needed and oftentimes showed me what I was doing wrong. * The concurrency abstractions are pretty cool and nice and high-level – need to fire off a lot of threads and block until they’re done? Just use ‘async’, give it a block of code, and slap that in a ‘finish’ block! Most programming languages offer some version of this – Ruby’s is pretty good for example but in contrast is not thread-safe by default – but this is certainly the cleanest I’ve seen thus far. * X10 easily supports mixing its code with Java or C++ libraries / code – haven’t needed to use this myself, but a cool selling point. The syntax doesn’t look too bad for this, but since the point of this experiment was to get away from Java and C++, I don’t see anything immediately compelling me to use this. Similarly, they have alpha support for compiling to CUDA code for running on GPUs – again, I don’t have a GPU sitting around to try this on, but looks very interesting. * The Eclipse support (called X10DT) is done very nicely – there’s just a plugin that natively interfaces with Eclipse that has installed for me without any problems over the last two releases I’ve played around with.
What snagged me or could have been improved:
* BadPlaceException – get used to seeing this fellow all the time once you start doing non-trivial programs. As the name suggests, a thread is trying to access data it doesn’t own, which causes it to violently explode. Debugging this is a pain since the line number in your X10 code doesn’t show up in the stack trace (the line number in whatever code it generates does show up, but that’s not helpful to me). Eclipse may have some debugging support integrated for this, but as I’m new to Eclipse, I have no idea what it is and the X10 documentation doesn’t appear to mention it. This was a double pain for me since once I was done getting rid of these on my local machine, I tried running it over a cluster of machines only to run into the same problem again – which without a line number for or debugging caused me to revert to the well documented “just put print line statements everywhere” strategy.
* Remember how I said the tutorials were really good in X10 2.0.6? Well I upgraded to the current version (X10 2.1) and all that cool documentation vanished, leaving me with the language reference. Now I have to specifically know the classes I want info on and use this and the X10 Standard Library documentation – essentially JavaDocs. It’s not that bad for me since I already got my first grasps on X10 with the cool tutorials, but I think it hurts new users not to have it. Interestingly, a new updated tutorial on X10 2.1 was just put out today that has a lot of great info – check that out here
* Syntax highlighting takes forever, and oftentimes error messages don’t go away until I save my code and let it do a pass over my code. Presumably future releases will fix this, but for now I just don’t trust the messages unless I save first and wait a few seconds for it to tell me what the real errors are.
* Lack of auto-completion support – I figured that since I was using Eclipse I could do the usual hot-key and do method completion or it would show up whenever I hit the “.” on my keyboard, but alas, the current version doesn’t have it. Again, this is likely due to the newness of the project or relative unimportance compared to more pressing issues, but since the rest of the “real languages with IDE support” have this, I’d expect X10 to have this in the next release or two.
* Putting my computer into sleep mode occasionally causes code to become not editable, which as you would suspect is a big pain in the ass. Interestingly, the code is always saved, so I just close Eclipse and re-launch it, but then I have to re-open the Eclipse X10 Help Menu to get back to the language reference (which takes 10-20 seconds to load), and get back to where I was before, and so on. Thankfully it doesn’t happen too often, and hopefully a future release will address this.
* The Java backend sets the number of Places to 4 by default, and when I ran it over MPI with the C++ backend, it ran with a single Place. Since my code wasn’t tested on that, it naturally didn’t work (BadPlaceException) and I couldn’t figure out how to run it over the Java backend (which runs really fast) with a single Place. I struggled for quite a while looking at environment variables to set and after trying what I thought were all of them when compiling or running my code, I found my solution: just run it with MPI on the C++ backend with
-n 1 -np <number of places>.
And that will do it! Debugging this still tends to be a pain since I’m now back to vi and 10-20 second compile times, but now I have some great code that looks a bit nicer than my MPI code. Since setting the number of Places is quite an important setting, I would also expect the documentation on how to set this to be improved by the next release or two.
Let’s wrap things up with an analogy: X10′s concurrency support is to MPI as Java’s garbage collection is to C++. MPI can give you super-fast code, but you’ll need to be a master coder to do so, and then it will likely only be optimized on whatever cluster your code was constructed on, just like how your C++ code will be memory-leak free only if you’re a pro at it – and in both cases, even the coding masters have had horribly slow code in MPI or leaky programs in C++. In the same way, Java and X10 offer much better programmer productivity since most of us aren’t memory management experts or gurus of concurrent programming (fun times with race conditions, shared program state, and so on).
X10 mixes things up just enough to be interesting, so it’s a project I will certainly be keeping an eye on and using in projects that permit it. If you have code you need to run concurrently or haven’t learned a new language recently, I definitely recommend checking it out!