Tuesday, January 25, 2011

Indenting python code

Since python determines scoping by indentation, it's imperative to be able to indent and de-indent blocks of code. I just learned how to do this in emacs: M-x python-shift-right or M-x python-shift-left. Note that you have to be in python-mode for these to work. Here's a discussion of all the possible ways to do it. A good, non-python-specific solution is C-x TAB which calls indent-rigidly, but you need to give it an argument to indent more than a single space.

Sunday, January 16, 2011

Writing udev rules

One annoying thing about having a USB-connected Vantage Pro2 weather station is that, occasionally, there is sufficient noise in the line that Linux drops the connection and immediately reconnects. The immediate reconnection is good. What's annoying is that Linux usually assigns it a different device name upon reconnection. So, if I configure my weather station software, weewx with the ttyUSB0 device name, I have to change the configured name after every reconnect (every few months) and risk losing data (though considering that the VP2 data logger keeps up to 2560 records, or 8+ days with a 5 minute interval, it's a small risk).

The solution to this problem is to use a custom udev rule. Udev allows you to do a variety of things with the /dev directory, including providing a single, consistent name for each USB device you connect (no matter what /dev name it gets assigned by the kernel). The following rule creates a symbolic link from /dev/vpro to the current device name for my VP2:

ACTION=="add", ATTRS{interface}=="CP2102 USB to UART Bridge Controller", SYMLINK+="vpro"
This says to add the "vpro" link whenever a device with a matching "interface" attribute is "add"ed (i.e. connected/attached). What's a little tricky about adding a udev rule is figuring out what attribute to match against so that the rule triggers on the device you want (and only that device). For that, you need to know what device name the kernel assigns (what /dev entry),

To find out what to match against, you need to get the information about the device. The following command provides that. You will need to replace /dev/ttyUSB0 with the device name that you are interested in.

udevadm info --attribute-walk --path $(udevadm info --query=path --name=/dev/ttyUSB0) 
The command will yield a hierarchy of information about the device. Information at the beginning is probably too minimal to be useful for matching; information at the bottom is probably too general and will match too many different devices. Look for something towards the top which sounds like it might describe the device. Use the key and value to write a rule like the one I gave above. Put this rule in a file named like 66-vpro.rules in
/etc/udev/rules.d
Note that the number must be two-digit and the extension must be rules. Make sure that the file is world-readable.

To test your rule, restart udev:

sudo /etc/init.d/udev restart
then unplug your device of interest, wait a second, and plug it back in. You should be able to see the effect of your rule. In my case, udev creates a /dev/vpro symlink to the kernel dev entry (e.g. /dev/ttyUSB0 for my VP2).

Wednesday, January 12, 2011

Parallel Programming

My first introduction to parallel programming was the summer of 1994 at the Pennsylvania Governor's School for the Sciences. For my final project, we wrote Fortran77 code with an MPI library to parallelize neural network code for image recognition on a Cray T3D supercomputer with 256 processors. It was cute & fun, but neither terribly practical nor useful :-)

Four years ago, I had my second parallel programming experience, writing a recommendation engine for StyleFeeder. This work was in Java utilizing threads to take advantage of multiple cores on a single machine. I got to see performance per core degrade significantly as the number of cores increased and the joy of the Java garbage collector (which would lock-up the entire program for minutes at a time). I've heard that Java GC performance continues to improve...

My most recent experience with parallel programming could be considered the most primitive one (single-threaded python code). But, considering the difficulty of parallel programming, I'm not convinced that it's any worse than the other frameworks. We use twisted to simplify communication between processes and since twisted is an event loop (single thread), programming is greatly simplified---no need to worry about your code being interrupted anywhere.

A colleague of mine just discovered Is Parallel Programming Hard, And, If So, What Can You Do About It? by Paul E. McKenney. The table of contents piques my interest. I hope I'll find time to read it...