April 28, 2012

Memory at each node on a NUMA machine using libnuma (linux only)

For the past few days I have been occupied with trying to understand how NUMA works and what are related implications and challenges for system design. Linux supports more than a few memory location policies on a NUMA supported machine and a corresponding user space library to deal with these policies, migration of memory, thread location etc among other things. The library for most part seems to get information from the files in /proc/self and in /sys/devices/system/node. The latter location in the sys filesystem has a multitude of information pertaining to the memory on the system.
Here is a simple program I wrote toady which prints the memory located at each "defined" memory node on the NUMA system, this program uses the numa library libnuma. It is a rather trivial piece of code. My next task at hand (once I am done with the semester finals) would be to play around with my parallel implementation of QuickSort using pthreads and see if I can improve performance by manually playing with locality of memory and thread execution.





I did hit upon one important piece of information which I did not know before, that my laptop (DELL E6410) is NUMA compatible but has a single memory node with all the 8 Gigs of memory. This might as well be the reason why the parallel QuickSort worked faster on my laptop than on some of the department machines with distributed memory banks and faster truly multithreaded cores.

EDIT :

if you have the numactl package installed, you can also list numa related hardware information using the following command :

numactl --hardware

looking at the information you can tell that it is the same as what you would see under the various entries in the /sys/devices/system/node directory.

April 24, 2012

Quick everyday scripting in bash

From my experience, mostly in grading courses and everyday tasks on my linux box, the most common requirements for scripting deal with iterating over a given set of entities and performing some task, or iterating over a given folder's contents and performing some task. Here are some sample cases and solutions to performing the same quickly. (I use bash so I am sure all the following work in bash).

Case 1 : 


You have a program X and you want to verify that it runs correctly (lets assume running correctly means the same as the program X exiting with success) over, say 100 iterations.

Solution

for i in `seq 100`
do
    ./X [ args for X]
    if [ $? -ne 0 ]; then
        echo "X failed in iteration $i"
        exit 1
    fi
done

The construct `...` runs the command inside and is replaced by the output of that command. the "basename" command gives you the last literal in a path.
The special variable $? stores the exit code of the previous program that was run in the shell script, this is typically what you return at the end of the main() function in a C program. A return code of 0 stands for success.
Note that the above snippet will work assuming that you are in the directory which contains the file (program) X.

Case 2 : 

A folder X has contents a, b, c, d, e, f, g , each of which is a folder. You want to create a file [parent_folder_name].txt in each of those folders.

for file in X/*
do
    touch $file/$(basename $file).txt
done

The construct $(...) runs the command inside and is replaced by the output of that command. the "basename" command gives you the last literal in a path. so

$ basename X/a
a
$ basename X/b
b

A slight modification to case 2, if X has both files and directories and you want to run the operation only for directories then you can modify the above snippet to check if the entry is a file/directory and act accordingly :


for file in X/*
do
    if [ -d $file ]; then
        touch $file/$(basename $file).txt
    fi
done

Note that the above two snippets (for Case 2) will work assuming that your current working directory is the parent of directory X.

Case 3 :

Execute a command via ssh on a set of remote machines, whose hostnames are in lexicographic order. For example the CS department here at purdue has the following set of machines : 
sslab01-sslab21 and suppose I want to run the command "who" on each one of them.

for i in `seq 21`
do
    if [ $i -lt 10 ]; then
        echo "Running 'who' on sslab0$i"
        ssh sslab0$i "who"
    else
        echo "Running 'who' on sslab$i"
        ssh sslab$i "who"
    fi
done

The if conditions in the above snippet are required because, by default the "seq"  does not output numbers of equal width, that is , it does not pad zeros at the beginning. However if you pass the "-w" option to seq, you can simplify the above snippet to : 

for i in `seq -w 21`
do
    echo "Running 'who' on sslab$i"
    ssh sslab$i "who"
done

The "-w" option ensures that `seq` prints its output in fixed width, padding the number with zeroes when ever necessary.

I will edit the post and add more common scenarios as I come across new ones, but all the above snippets are short and once you get hold of things, you can actually type them in on the prompt whenever you want rather than storing them in a script file and running that file. 

Adding Scripts to the PATH

However if you do want to run them as a script (from a file), it is a better option to do the following : 

1. if  ! [ -d ~/bin ]; then mkdir ~/bin; fi
2. touch ~/bin/script_I_run_often
3. Add the snippet to the script
4. chmod +x ~/bin/script_I_run_often
5. add "export PATH=$PATH:~/bin" to ~/.bashrc

Now you can just run the script as : 

$ script_I_run_often
Other Special Variables

Some other special variables which are very useful in everyday scripting are : 

$# : the number of arguments passed to the script, you can check this variable to see if your script got the correct number of arguments or not 
$1, $2, $3 ... : are the arguments passed to the script
$$ : Pid of the current process

NOTE : None of the information mentioned above is "new" or "novel", the post is just meant to serve as a compilation of some quick bash tricks. I am sure many other such compilations exist on the internet.


April 17, 2012

[Fixed] Blue Tint on Youtube videos (flash problem) on Centos 6.x

I have the adobe flash plugin from the adobe repository with the following version installed on my laptop running Centos  :


flash-plugin.x86_64                    11.2.202.233-release    @adobe-linux-x86_64

Since the last update, the videos on Youtube have mostly had a blue tint and less often a pale orange shade. After a couple of days of not trying to fix it (thanks to the hectic semester) I guessed this was a problem with flash or something to do with how flash uses the GPU, since those are the only two pieces of proprietary software on my laptop (and thus would be expected to be fixed rather slow for a problem so evident). 
Finally, a little googling around showed this post on the Arch Linux forums : https://bbs.archlinux.org/viewtopic.php?pid=1084648

I just followed whatever was mentioned there, and the flash plugin looks far more stable now. Here are the steps I followed on my Centos 6.x machine : 

1. Created the file /etc/adobe/mms.cfg and added the following contents : 

#Hardware video decoding
EnableLinuxHWVideoDecode=1
OverrideGPUValidation=true

2. Added the following line at the beginning of  /etc/X11/xinit/xinitrc-common

export VDPAU_NVIDIA_NO_OVERLAY=1

You will need root permissions for both of the above, an alternative for the second step can be adding the same line to the user specific xinitrc file (~/.xinitrc). I logged out and logged in again after the changes, the blue tint is gone and the flash plugin itself is far more stable than before. As suggested in the thread on the arch linux forums, it might be a good idea to try a free alternative to the adobe flash player plugin if possible.

PS : 
1. I run Centos 6.x on my Dell E6410, which has a NVIDIA NVS 3100M gpu.
2. It is just amazing the thread which showed up was on the arch linux forums, Arch Linux continues to amaze me.