Saliya's Blogs

Mostly technical stuff with some interesting moments of life

Showing posts with label linux. Show all posts
Showing posts with label linux. Show all posts

Get and Set Process Affinity in C

Affinity of a process can be retrieved and set within a C program using sched_getaffinity (man page) and sched_setaffinity (man page) routines available in the sched.h. The following are two examples showing these two methods in action.

Get Process Affinity

#define _GNU_SOURCE
#include 
#include 
#include 
#include 
#include 

int main(int argc, char* argvi[])
{
    pid_t pid = getpid();
    cpu_set_t my_set;
    int ret;

    CPU_ZERO(&my_set);
    ret = sched_getaffinity(0, sizeof(my_set), &my_set);
    char str[80];
    strcpy(str," ");
    int count = 0;
    int j;
    for (j = 0; j < CPU_SETSIZE; ++j)
    {
        if (CPU_ISSET(j, &my_set))
        {
            ++count;
            char cpunum[3];
            sprintf(cpunum, "%d ", j);
            strcat(str, cpunum);
        }
    }
    printf("pid %d affinity has %d CPUs ... %s\n", pid, count, str);
    return 0;
}
You can test this by using taskset command in linux to set the affinity of this program and checking if the program returns the same affinity you set. For example you could do something like,
taskset -c 1,2 ./a.out
Note, you could use the non-standard CPU_COUNT(&my_set) macro routine to retrieve how many cores are assigned to this process instead of using a count variable within the loop as in the above example.

Set Process Affinity

#define _GNU_SOURCE
#include 
#include 
#include 
#include 
#include 

int main(int argc, char* argvi[])
{
    pid_t pid = getpid();
    cpu_set_t my_set;
    int ret;

    CPU_ZERO(&my_set);
    CPU_SET(1, &my_set);
    CPU_SET(2, &my_set);

    ret = sched_setaffinity(0, sizeof(my_set), &my_set);
    printf("pid %d \n", pid);

    // A busy loop to keep the program from terminating while
    // you use taskset to check if affinity is set as you wanted
    long x = 0;
    long i;
    while (i < LONG_MAX)
    {
        x += i;
        ++i;
    }
    printf("%ld\n",x);
    return 0;
}
The program is set to bind to cores 1 and 2 (assuming you have that many cores) using the two CPU_SET macro routines. You can check if this is set correctly using the taskset command again. The output of the program will include its process id, say pid. Use this as follows to check withtaskset.
taskset -pc pid
Note, I've included a busy loop after printing the pid of the program just so that it'll keep running while you check if affinity is set correctly.

Running C# MPI.NET Applications with Mono and OpenMPI

I wrote an earlier post on the same subject, but just realized it's not detailed enough even for me to retry, hence the reason for this post.
I've tested this in FutreGrid with Infiniband to run our C# based pairwise clustering program on real data up to 32 nodes (I didn't find any restriction to go above this many nodes - it was just the maximum I could reserve at that time)
What you'll need
  • Mono 3.4.0
  • MPI.NET source code revision 338.
      svn co https://svn.osl.iu.edu/svn/mpi_net/trunk -r 338 mpi.net
    
  • OpenMPI 1.4.3. Note this is a retired version of OpenMPI and we are using it only because that's the best that I could get MPI.NET to compile against. If in future MPI.NET team provides support for a newer version of OpenMPI, you may be able to use it as well.
  • Automake 1.9. Newer versions may work, but I encountered some errors in the past, which made me stick with version 1.9.
How to install
  1. I suggest installing everything to a user directory, which will avoid you requiring super user privileges. Let's create a directory called build_mono inside home directory.
     mkdir ~/build_mono
    
    The following lines added to your ~/.bashrc will help you follow the rest of the document.
     BUILD_MONO=~/build_mono
     PATH=$BUILD_MONO/bin:$PATH
     LD_LIBRARY_PATH=$BUILD_MONO/lib
     ac_cv_path_ILASM=$BUILD_MONO/bin/ilasm
    
     export BUILD_MONO PATH LD_LIBRARY_PATH ac_cv_path_ILASM
    
    Once these lines are added do,
     source ~/.bashrc
    
  2. Build automake by first going to the directory that containst automake-1.9.tar.gz and doing,
     tar -xzf automake-1.9.tar.gz
     cd automake-1.9
     ./configure --prefix=$BUILD_MONO
     make
     make install
    
    You can verify the installation by typing which automake, which should point to automake inside $BUILD_MONO/bin
  3. Build OpenMPI. Again, change directory to where you downloaded openmpi-1.4.3.tar.gz and do,
     tar -xzf openmpi-1.4.3.tar.gz
     cd openmpi-1.4.3
     ./configure --prefix=$BUILD_MONO
     make
     make install
    
    Optionally if Infiniband is available you can point to the verbs.h (usually this is in /usr/include/infiniband/) by specifying the folder /usr in the above configure command as,
     ./configure --prefix=$BUILD_MONO --with-openib=/usr
    
    If building OpenMPI is successfull, you'll see the following output for mpirun --version command,
     mpirun (Open MPI) 1.4.3
    
     Report bugs to http://www.open-mpi.org/community/help/
    
    Also, to make sure the Infiniband module is built correctly (if specified) you can do,
     ompi_info|grep openib
    
    which, should output the following.
     MCA btl: openib (MCA v2.0, API v2.0, Component v1.4.3)
    
  4. Build Mono. Go to directory containing mono-3.4.0.tar.bz2 and do,
     tar -xjf mono-3.4.0.tar.bz2
     cd mono-3.4.0
    
    Mono 3.4.0 release is missing a file, which you'll need to add by pasting the following content to a file called./mcs/tools/xbuild/targets/Microsoft.Portable.Common.targets
     <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
         <Import Project="..\Microsoft.Portable.Core.props" />
         <Import Project="..\Microsoft.Portable.Core.targets" />
     </Project>
    
    You can continue with the build by following,
     ./configure --prefix=$BUILD_MONO
     make
     make install
    
    There are several configuration parameters that you can play with and I suggest going through them either in README.md or in./configure --help. One parameter, in particular, that I'd like to test with is --with-tls=pthread
  5. Build MPI.NET. If you were wonder why we had that ac_cv_path_ILASM variable in ~/.bashrc then this is where it'll be used. MPI.NET by default tries to find the Intermediate Language Assembler (ILASM) at /usr/bin/ilasm2, which for 1. does not exist because we built Mono into $BUILD_MONO and not /usr 2. does not exist because newer versions of Mono calls this ilasm notilasm2. Therefore, after digging through the configure file I found that we can specify the path to the ILASM by exporting the above environment variable.
    Alright, back to building MPI.NET. First copy the downloaded Unsafe.pl.patch to the subversion checkout of MPI.NET. Then change directory there and do,
     patch MPI/Unsafe.pl < Unsafe.pl.patch
    
    This will say some hunks failed to apply, but that should be fine. It only means that those are already fixed in the checkout. Once patching is completed continue with the following.
     ./autogen.sh
     ./configure --prefix=$BUILD_MONO
     make
     make install
    
    At this point you should be able to find MPI.dll and MPI.dll.config inside MPI directory, which you can use to bind against your C# MPI application.
How to run
  • Here's a sample MPI program written in C# using MPI.NET.
      using System;
      using MPI;
      namespace MPINETinMono
      {
          class Program
          {
              static void Main(string[] args)
              {
                  using (new MPI.Environment(ref args))
                  {
                      Console.Write("Rank {0} of {1} running on {2}\n",
                                      Communicator.world.Rank,
                                      Communicator.world.Size,
                                      MPI.Environment.ProcessorName);
                  }
              }
          }
      }
    
  • There are two ways that you can compile this program.
    1. Use Visual Studio referring to MPI.dll built on Windows
    2. Use mcs from Linux referring to MPI.dll built on Linux
      mcs Program.cs -reference:$MPI.NET_DIR/tools/mpi_net/MPI/MPI.dll
      
      where $MPI.NET_DIR refers to the subversion checkout directory of MPI.NET
      Either way you should be able to get Program.exe in the end.
  • Once you have the executable you can use mono with mpirun to run this in Linux. For example you can do the following within the directory of the executable,
      mpirun -np 4 mono ./Program.exe
    
    which will produce,
      Rank 0 of 4 running on i81
      Rank 2 of 4 running on i81
      Rank 1 of 4 running on i81
      Rank 3 of 4 running on i81
    
    where i81 is one of the compute nodes in FutureGrid cluster.
    You may also use other advance options with mpirun to determine process mapping and binding. Note. the syntax for such controlling is different from latest versions of OpenMPI. Therefore, it's a good idea to look at different options from mpirun --help. For example you may be interested in specifying the following options,
      hostfile=<path-to-hostfile-listing-available-computing-nodes>
      ppn=<number-of-processes-per-node>
      cpp=<number-of-cpus-to-allocate-for-a-process>
    
      mpirun --display-map --mca btl ^tcp --hostfile $hostfile --bind-to-core --bysocket --npernode $ppn --cpus-per-proc $cpp -np $(($nodes*$ppn)) ...
    
    where, --display-map will print how processes are bind to processing units and --mca btl ^tcp forces to turn off tcp
That's all you'll need to run C# based MPI.NET applications in Linux with Mono and OpenMPI. Hope this helps!

Running MPI.NET Applications with Mono in Ubuntu

Sometime back I played around Mono to get some of our parallel applications running on Ubuntu. These applications were C# based and used MPI.NET.

The following blog post is a great starting point with all the details you'll need. So I'll skip the steps, except to point out couple of caveats you need to consider.

http://blog.biophysengr.net/2011/11/compiling-mpinet-under-ubuntu-oneiric.html


  1. automake versions above 1.9 will give you an error when building MPI.NET. May be you can change the make script to work with them, but I found it easy to just install automake1.9 to solve it.
  2. You'll need to add /usr/local/lib to your LD_LIBRARY_PATH. Essentially what you need to do is add this path to /etc/ld.so.conf and run ldconfig as root. See documenation from Mono on this at http://www.mono-project.com/DllNotFoundException
  3. Make sure to do chmod +x to your dlls

Download a Set of URLs with GNU Wget

I had a list of URLs that I wanted to download and it was a pain to do it manually. So end up writing a simple shell script and downloading all of them using GNU Wget. Here’s the shell script (modified the one at http://www.linuxquestions.org/questions/programming-9/shell-script-that-read-each-line-separatly-364259/).

#!/bin/bash
# Set the field seperator to a newline
IFS="
"
# Loop through the file
for line in `cat file.txt`;do
wget $line
done

Pidgin: Unable to Connect to Yahoo

Pidgin was giving trouble when connecting to my Yahoo account since recently. Today I got to know that it's because of this (http://www.celticwolf.com/useful-information/faqs/26-pidgin-yahoo).

Then I wanted to install a latest version of pidgin on my Ubuntu 9.04. I tried the "how to" given in the official pidgin site (http://www.pidgin.im/download/ubuntu/), but it was unsuccessful. Then I came across these debs (http://linux.softpedia.com/progDownload/Pidgin-Download-6.html) which solved the issue.

Just a quick how-to:

1. Download the i386 (or amd 64) debs
2. Download the two DEB ALL debs
3. Use dpkg -i to install the debs. Start with libpurple-bin_2.6.3-1~getdeb1_all.deb.
Then libpurple0_2.6.3-1~getdeb1_i386.deb (or amd 64 one).
Now move ahead with pidgin-data_2.6.3-1~getdeb1_all.deb.
Next pidgin_2.6.3-1~getdeb1_i386.deb (or amd 64 one)

That's it! no more troubles with Yahoo ;)

Ubuntu: Resizing Partitions

"No space left on device": Damn, how did this happen?, I told my self. I am pretty sure that I gave enough space for my home partition to carry on with Maven builds at WSO2. Out of curiosity, I issued df -h to see the partitions. Gee, I have accidentally assigned the larger partition to / (root) and smaller one for the home. The only solution is to resize the partitions. After a while, I remembered the great tool that comes with Ubuntu distribution, i.e. gparted.

I booted my machine using an Ubuntu CD and ran gparted. I was very much pleased with its graphical view and was done with my problem in just minutes. Initially my paritions were like,

|------------home----------|--------------/ (root)---------------------------------------------|

After resizing it looked like,

|----------------home----------------------------------------|----------------/ (root)---------|

I was pretty happy with this little tool since it saved me from one hell of a trouble.

Access Vista from Ubuntu

Ever tried accessing a shared folder in Vista from Ubuntu? Here are the simple step I followed.

For this example say your Vista user account is vista-pc and password is vista-pw. Also say the IP is 192.168.1.2

----Do the following in your Vista machine----
1. Start/Run secpol.msc
2. Open Local Policies/Security Options, find "Network Security: LAN Manager"
3. Change it to "Send LM & NTLM"
4. share the folder that you want (say movies)

---Do the following in your Ubuntu machine---
1. sudo apt-get install smbfs
2. sudo apt-get install smbclient
3. sudo mkdir /mnt/hd
4. sudo mount -t smbfs -o username=vista-pc,password=vista-pw //192.168.1.2/movies /mnt/hd

That's it :) You can now access the shared Vista folder from /mnt/hd

ATI X1300 with Ubuntu 8.04 (Hardy)

In one of my previous posts I mentioned how to setup ATI X1300 graphics card in Ubuntu Gusty. Recently I installed Ubuntu Hardy because Gusty came up with couple of bugs. Unfortunately I had to set up my graphics card again :(

So I tried with the Unofficial ATI Wiki and it worked just as expected. Try method 2 mentioned here.

The great news is hibernation works with it :)

How to Access Linux (Ext2) Partitions from Windows OS

I've been using Explore2fs for sometime to access my Linux partition from Windows OS. But it was very boring to copy files from Ext2 partition all the time when I wanted to access them. So I decided to search for a better option. So here it is, Ext2 installable file system. It's very cool. You can even write to Ext2 partition. Here is the good article where I found these stuff.

ATI x1300 with Ubuntu Gusty (7.10)

Ah! I had to give another fight to get my x1300 ATI card working properly with Ubuntu Gusty. The restricted driver that comes by default would correct the wide screen problem but video quality is changed. You will find lot of illuminant people while watching a film in totem.

So here goes the answer

Good luck and have fun :)

Ubuntu 7.10 on DELL E1505 Notebook

I installed Ubuntu (Gusty Gibbon) on my Dell notebook and I felt the beauty of it from the very beginning.

The two most interesting features I see:
1. Read/Write facility to NTFS (Windows) partitions
2. Easy configuration of restricted drivers (no need to worry about setting up your ATI video card :)

HUAWEI ETS 2251 with Ubuntu 6.10

We recently purchased a CDMA data phone and I wanted to connect to the Internet with Linux (Ubuntu 6.10). Try the following steps:

1. plug-in the USB cable (your cable should be Serial (phone side) to USB one).
2. sudo dmesg -c

you should see the following at the bottom

ti_usb_3410_5052 2-1:2.0: TI USB 3410 1 port adapter converter detected

if you see ti_usb_3410_5052: probe of 1-1:1.0 failed with error -5 after the above line then copy the following lines,

#TI USB 3410

SUBSYSTEM=="usb_device" ACTION=="add" SYSFS{idVendor}=="0451",SYSFS{idProduct}=="3410" \

SYSFS{bNumConfigurations}=="2" \

SYSFS{bConfigurationValue}=="1" \

RUN+="/bin/sh -c 'echo 2 > /sys%p/device/bConfigurationValue'"


and save them as /etc/udev/rules.d/026_ti_usb_3410.rules


Now run sudo dmesg -c again and you'll see the following two lines,

ti_usb_3410_5052 1-1:2.0: TI USB 3410 1 port adapter converter detected
usb 1-1: TI USB 3410 1 port adapter converter now attached to /dev/ttyUSB0



3. Now configure the /etc/wvdial.conf as follows, please note that you need to replace your given username, password and phone number with my configuration (abc@prepaid, 1234, #777) given here.


[Dialer suntel]

Modem = /dev/ttyUSB0

Baud = 230400

Phone = #777

Init1 = ATZ

Stupid Mode = 1

Dial Command = ATDT

Username = abc@prepaid

Password = 1234


4. Now type sudo wvdial suntel and enjoy the Internet. If you can't browse then plese add the DNS addresses to /etc/resolv.conf (these DNS addresses can be found in the command line while connecting).

Thanks Farhan Naeem for sharing knowledge on this matter