A few weeks ago, I got myself an iPad. Ebook readers are well and good in principle, but as my friend Tyler pointed out, for technical papers and books that are rife with figures, it becomes necessary to zoom in and out, and ebook readers just aren’t there yet. Plus, this gives me the internet, directions, my news, email, pictures, and movies on long flights (which have become a part of living in Saudi Arabia).
Getting the device, however, proved interesting. I had originally planned to get one almost two months ago, and called up the 5th Avenue Apple store around 11 at night, thinking it would be less busy. They’re open 24/7, and the idea of walking into the store in the middle of the night and buying a device held a certain appeal. After 20 minutes on hold, I talked to a guy, and asked him if they had any in stock (after all, it’s kind of a long walk). He sort of laughed, said ‘no,’ and that I’d have to make an appointment to buy one. This didn’t seem right to me, but it was late and I wasn’t in the mood to deal with a smarmy Apple employee.
A few weeks after that, I figured I’d bike down to the Upper West Side store, figuring out that it would be faster to ride there than to wait on hold. I asked if they had stock, and someone told me they did, and that he’d go back and get it. Then, 15 minutes later he returns saying he was mistaken. Then, I zip off to the 5th Ave store, where it’s the same story. Then downtown to the 14th St. store, and eventually the SoHo store. Nothing. And, it was actually faster to bike to every Apple store in Manhattan than to call them.
It wasn’t until two weeks after that when I drove up to New Hampshire to see my sister that I was finally able to get one. I called her campus book store, and they had everything in stock. And to boot, there’s no sales tax there. A 10-minute phone call (and a five-hour drive I was making anyway) later, I finally had an iPad. Such an ordeal!
In the end, I wonder, why does Apple make it so hard to love them? All I want to do is buy their latest polished turd of a device. That said, I really have been enjoying the hell out of it. But the spite is growing, Apple. The spite is growing.
For me, operating systems was one of the most worth-while courses in my undergraduate career. Not only gaining insight into the black-box that can be the operating system, but learning a bunch of skills that I have found invaluable since then.
Even in graduate school, I encounter computer scientists that have never used the command line. While its all well and good to use your IDE, it is absolutely crippling to not be able to do all the same magics from the command line. Not only that, but there is a wealth of tools accessible from your favorite shell and bash scripting is a useful piece to keep in one’s toolbox. The command line was one thing with which I was better acquainted through operating systems; this was especially true in one project where we had to roll our own shell. This was particularly good because the shell gives access to a lot of system tools that I’ve since found I want to use in other programs: forking, dup’ing, interacting with environment variables, etc.
Other good experiences were working with threading libraries and even booting up EC2 instances and testing out code there. I am extremely grateful to then-professor Mike Colagrosso for making it such a worthwhile experience. Lately I’ve been working with code where I remember quality code promises he made us make:
ALWAYS save the return value of system calls. I try to avoid programming in C as much as possible (after all, C++ is usually an alternative, if not Python), but whenever I do I am constantly reminded of this one. The most common design for functions that I encounter in that kind of code is to accept the variable that is to be updated, and return instead, a code indicating the success/failure/warnings/etc. of the code. In some cases, the return value is the only way you’ll have access to the resource just requested (for example in the case of fork(2) ), but either way it’s the basic mechanism for getting feedback about how code has executed.
NEVER use strcpy(3). I’ve never used a buffer overflow in a clever way (though this is a someday project), or I should say on purpose. But I’ve dealt with enough instances of me being distracted and writing bad code that I’ve gotten to know gdb (the GNU DeBugger) better than I would like. The strcpy(3) function relies on null character termination to stop copying memory from one string into another. If, however, a string isn’t null terminated or isn’t terminated before the length of the string buffer being copied into, then the operation will overrun the buffer. Instead, ALWAYS use strncpy(3). It allows you to specify the maximum length that should be copied (like, for instance the length of the buffer being copied into) so as to avoid this embarrassing problem.
Despite the taking the class just over three years ago (it’s unsettling to realize its been so long), these few promises have stuck with me. So Mike, if you’re reading this, I’m doing my part!
It’s an itch. A compulsion. Sometimes when working with a new library I get a very strong impulse to do a very bad thing – reinvent the wheel. Or, in this case, re-write the wheel.
It’s easy to object to the way code is organized, and can cause a certain amount of discomfort. Whether it’s the desire to go through and reformat code (braces belong on the same line as the if statement!) or the pain of hacking together relatively incompatible library designs, it can be unpleasant.
Something that I’ve been pushing myself to do, and slowly learning to do is to be comfortable with that discomfort. To resist the urge to rewrite code, as it’s never just a matter of rewriting it, but also testing it, an so forth. I’m slowly beginning to accept the painful truth: no code is perfect.
That said, there are times when I do rewrite libraries. Sometimes you’re handed code from ten years ago that’s no longer applicable, or antiquated, or just plain ugly. In these scenarios it’s perfectly justified to make large sweeping structural changes (with the protection of your favorite version control, of course). Just, hold off. Wait, and try to use the library, and the first-pass issues will either grow into systemic problems or wither and recede into the cracks.
Last week I was in Los Angeles, CA for SIGGRAPH, and though I discovered that I far prefer New York to LA (sorry, Angelinos) I did get something great out of it – a trip to Channel Islands National Park.
About 30,000 visitors step onto its shores every year, making it one of the least-visited national parks. It consists of five islands of varying sizes, and we stayed on one of the larger ones. There were a few dozen other campers we saw, but the vast majority of people on the boat were day-trippers.
We “set sail” at 8 am with Island Packers, who were fantastically efficient and a pleasure to travel with despite their apparent monopoly on service out to the islands. Upon landing, the campers were required to get a brief orientation from the live-in park ranger describing their pack-in pack-out policy and the fact that we should never leave zippers exposed as the island’s ravens have learned to unzip backpacks.
With wetsuits rented from Ventura Dive and Sport, plunged into the icy waters (ok, they’re not icy, but they’re pretty frigid compared to the warm Red Sea). The kelp beds were amazing, stretching below beyond visibility and then tangling at the surface, creating an enormous labyrinth of giant leaves. Their bases covered in sea urchins eating away at the tendrils. On the second day we saw a couple of stingrays, and a school of fish thousands strong trolling the area. I had hoped to swim and play with the local sea lions, but they weren’t particularly interested in us apparently.
While not freezing in the water, we hiked the many trails, perching atop the various cliffs overlooking the many harbors. And when not hiking, we ate and watched the chihuahua-sized island foxes looking for food and fending off the comparably-sized ravens.
It was a fun excursion, and I hope to go back for more diving and exploration of the islands. During the year they see countless whales and dolphins, and organize dive trips. Oddly enough, I found out about it two years ago from an in-flight magazine on my way to a KAUST orientation meetup. Chalk one up to the in-flight magazine!
I must admit, at times, looking down at the bright blue water, and ships coming into harbor, I felt a little bit like a pirate.
This last week saw SIGGRAPH 2010 in Los Angeles, sunny California. It was there that I gave my first talk at a real conference. One request that I had not anticipated was for the slides from the talk, and so I post them here now.
Pending some red tape resolution, I hope to post the live-working demos soon. Until then, I hope that this video from the original conference submission will whet your appetite!
For those particularly curious, feel free to contact me or refer to the abstract.
I arrived in Los Angeles yesterday to attend (and talk at) SIGGRAPH 2010. This is not the first time the conference has been here, but it is certainly my first time to this smoggy city.
Adjacent to the Los Angeles Convention Center is the Staples Center, where workers have been setting up for the X Games. Fortunately they won’t begin until July 29th, the last day of this conference, but in watching the setup I was imagining an enormous re-enactment of high school stereotypes. Tens of thousands of jocks right next door to tens of thousands of nerds.
It’s a question that comes up often in conversation, and especially when meeting new people. The normal pleasantries of where one is from and what one does naturally lead there. “High-Performance Computing, eh? What’s that?”
I sometimes feel it a mission to dispel myths about supercomputing that the layperson might have. Pop culture is full of stern-looking authority figures leering at a screen, looking over the shoulder of an endearingly-disheveled nerd. Or I think Chuck represents this well:
So when answering this seemingly question about what exactly my job entails, I have to start at the bottom, explaining how processors aren’t getting any faster (and haven’t been for quite a while, relatively speaking). And how this fact necessitates a different way of looking at programming tasks, moving from “fast” or “deep” to “wide.” Supercomputers aren’t single small boxes in the middle of a vast room covered in billions of pixels, as Chuck would seem to suggest. No, nothing so glamorous. In fact, seeing a rack of IBM’s Blue Gene is more akin to 2001: A Space Odyssey - being confronted with a towering black monolith:
[caption id=”attachment_875” align=”aligncenter” width=”300” caption=”The BlueGene/P system at Argonne National Lab. The man in the picture is actually now an awesome system administrator for the KAUST Supercomputing Lab!”][/caption]
So modern supercomputers are not a single chip that can perform trillions of calculations per second, but are rather a set of relatively simple processors that each perform modestly. Though when working in concert, the results are astounding. Not long ago a supercomputer sustained calculations at a rate of 1 petaflop, or a million billion operations every second. If we were to compare that to a relatively modern desktop, a second on that computer is the equivalent of about four days of computation on your desktop. If the same code were to run on the computers used in the Apollo missions, it would take approximately 630 years (this is a rough approximation based on a figure of 20 microseconds per add).
The reason for the modest clock rates of each processor in modern devices is power. Intel successfully grew processor performance by increasing the rate at which operations were performed (among other advances), but at a great cost in power. For example, a chip on a BlueGene/P compute node runs at a mere 850MHz, though it’s impossible to use this number alone to compare performance. In fact, of the budget allocated for the purchase of a system like that, only half that money goes towards actual equipment. The rest goes towards the power of not only running it, but cooling the damn thing off.
Graphics cards have become an unlikely source of high-performance computing in the last ten years or so. It’s seen many struggles, from being difficult to program and even harder to debug, to early cards not supporting floating-point calculations and not supporting certain types of loops. And yet NVIDIA now markets a graphics card with as many as 480 cores.
I recently happened upon this video of Jamie Hyneman and Adam Savage of Myth Busters explaining the difference between a CPU (the brain of your computer for the uninitiated) and a GPU (the part the handles much of the graphics). When presented with explosions, robots and paintballs, the difference really lights up (skip to 8 minutes in for the really good bit, but the whole thing is worth a watch):
I’ve been working with a large shared system at my school, sometimes building packages for myself and sometimes for others. The one thing that’s almost certain across all such installations is that it’s difficult. Installing dependencies can be a very deep rabbit hole, and there are seemingly more configuration, build and source control systems than there are atoms in the universe.
On this particular shared system, our awesome sysadmins (these guys are really pretty great!) use a package called modules to set environment variables for use with various packages. Suppose you have several versions of a library that you’re working with. Let’s say some users need Python 2.4, and other 2.6 and 3.0. Instead of managing your path yourself, modules can help:
123
$> module load python-2.4
$> which python
/opt/share/python/2.4/ppc64/bin/python
One of the really great things about modules is that the way so-called modulefiles are written, not only can you load modules easily, but you can also unload them just as easily:
123456
$> which python
/opt/share/python/2.4/ppc64/bin/python
$> module unload python-2.4
$> module load python-2.6
$> which python
/opt/share/python/2.6/ppc64/bin/python
It’s of course not limited to any particular environment variable. The modulefile can specify where the man pages are, what paths to include when using cmake, dynamic library path and whatever you’d like.
Modulefiles are also extremely convenient places to store information on how you actually built the library. When you come back to it three months from now to build the next version of some code base, you won’t remember the complex arguments you had to pass into configure or cmake in order to get the damned thing to build. Build notes are an essential part of maintaining code, especially if other people will be using the libraries you’ve built.
Speaking of which, I’ve worked on other shared systems before where several people need to use the same library and end up building it separately. Frank and Steve both need libX, and have made their installations accessible to the other users on the system, but who wants to sully their .bash_profile by adding some long and ugly paths to their PATH? If Steve makes his modulefiles directory public, too, then you can just that directory in MODULEPATH:
1234
# in ~/.bash_profile...
export MODULEPATH=~/modules/:/home/frank/modules/
...
Perhaps it’s not the best thing since sliced bread, but I like that it affords me a way to bridge the gap between having a convention for where libraries are installed (say, if you use MacPorts, for example?) and being able to easily set all your environment variables to easier if not easy compilation.
By way of a way that its helped me, I’ve been compiling quite a few projects recently that rely on cmake. These projects also have a whole lot of dependencies, but my build process is now something along the lines of:
Computers aren’t perfect, but they are experts at remembering the details. Almost to a fault. Modules helps my interactions to be a little more equitable where I have to remember the important parts (the names of the modules I need, for example) and the computer can keep track of where the hell I put everything!
I’m not quite sure what the message here is.
[caption id=”attachment_870” align=”aligncenter” width=”225” caption=”Freshest dolphin in town?”][/caption]
I’m not a “network guy.” I still don’t know what exactly the subnet mask means, and I am often thankful that OS X is so willing to automatically configure network settings for me well.
That said, recently I’ve been finding myself doing a lot of programming with sockets. They provide a low-level network interface to communicate between computers, and are used like other file descriptors. On the C side of things there’s a little more work than I’d like, and as such, I’ve found Python an invaluable tool.
In fact, I think any time you’re working with a new concept, technique or algorithm it’s extremely helpful to use a scripting language. Like others, Python offers an interactive session where you can develop code fragments by trial and error with each step, rather than trying to debug a chunk of code you’ve written with only a vague notion of what’s going on behind the scenes. It allows you to pause between steps and see the effects and results of each function.
Interestingly enough, another tool has come in extremely handy - netcat. It’s designed to print to stdout everything that it hears on the socket, and then it sends everything it receives on stdin through the socket. It allows you to examine some of the specifics of a protocol without worrying about the details of your own code or whether or not your code works. Netcat is tried and true, and will tell you exactly what’s happening.
This all came up in the context of WebSockets. They’re a part of the HTML5 spec and provide a JavaScript interface for real socket communication (there are of course some caveats, especially with respect to how to handle binary data). We’ve been using them for a project where we’d like the client to not need a special program to interact with a piece of software, and so instead implemented the protocol in JavaScript.
There was, however, some trouble at the offset. I had a bit of difficulty finding out why exactly the WebSocket client would seem to start to make a connection but then immediately complain about handshakes. What would have been much easier is to just open up netcat on the same port and have a conversation with the WebSocket itself.
1234
# First off, I was running SimpleHTTPServer from a directory with a dummy html file$>python-mSimpleHTTPServer8888# On the terminal, listen on port 35000$>netcat-l35000
And then try to make a connection from the JavaScript side
It was only after realizing that this is what the WebSocket was sending that it became clear that the reason that no connection was actually happening was because the browser wasn’t getting the rest of the handshake:
Oddly enough, I can’t seem to get netcat to play nice sending the response code, but it can easily-enough give us an indication of what was happening at first. Python can handle the rest for us:
And notice that it’s not until the listening socket sends its response portion of the handshake that the JavaScript console will print the “hello” we told it to upon opening the connection. Now that we have the two talking, let’s actually send and receive a couple of messages:
12
#AgainfromtheJavaScriptconsolews.send("Hello from JavaScript!")
And then we receive the message in Python:
12
>>>client.recv(1024)'\x00Hello from JavaScript!\xff'
And here we find another oddity of WebSockets. All messages seem to be prepended with \x00 and appended with \xff (though this is also mentioned in the specification). If we try to send a message from Python without these two extra characters, we’ll get nothing out on the JavaScript side (go ahead and give it a try!):
Of course I’m sure there are other robust tools the real “networking guys” use to make their lives easier. But outside of pulling up WireShark or trying to figure this out by writing C code, netcat and Python definitely saved the day.