Friday, July 8, 2011

Logoff users under Windows terminal

(1) To display information about all user currently logged on the system
query user
(2) Find the numeric session id corresponding to a user from the display
(3) Logs off a user from a session and deletes the session from the server
logoff session_id

Wednesday, June 29, 2011

Using Microsoft Windows remote desktop via IPv6 Network

Firstly, intall IPv6 protocol.
Then run command: netsh interface portproxy add v6tov4 listenport=3389 connectport=3389

Tuesday, May 17, 2011

Install Sun Grid Engine (SGE) on Ubuntu Server 11.04

This post follows my previous note on how to "Set Up an MPICH2 Cluster With Ubuntu Server 11.04".

8. Install a Job Scheduler-Sun Grid Engine (SGE)

8.1. Install SGE on master node:
mpiuser@ub0:~$ sudo apt-get install gridengine-client gridengine-common gridengine-master gridengine-qmon gridengine-exec
#remove gridengine-exec from the list if master node is not supposed to run jobs
#during the installation, we need to set the cluster CELL name (such as ‘default’)

8.2. Install SGE on other nodes:
mpiuser@ub1:~$ sudo apt-get install gridengine-client gridengine-exec

#The CELL name is set the same as that of the master node

8.3. Set SGE_ROOT and SGE_CELL environment variables:
$SGE_ROOT refers to the installation path of SGE
$SGE_CELL is cell name which is ‘default’ on our machine
Edit /etc/profile and /etc/bash.bachrc, add the following two lines
export SGE_ROOT=/var/lib/gridengine #this is the path on our machines
export SGE_CELL=default
Source the script: source /etc/profile

8.4. Configure SGE with qmon (This section is modified from a note by [Ref. 1])
8.4.1. Invoke qmon as superuser:
mpiuser@ub0:~$ sudo qmon
#On our machine, qmon failed to start due to missing fonts ‘-adobe-helvetica-…”
# To solve the fonts problem:
mpiuser@ub0:~$ sudo apt-get install xfs xfstt
mpiuser@ub0:~$ sudo apt-get install t1-xfree86-nonfree ttf-xfree86-nonfree ttf-xfree86-nonfree-syriac xfonts-75dpi xfonts-100dpi
#I guess not all of these packages are required actually
#a better fix would be (update on 18/8/2013)
#(Ref: https://www.diigo.com/item/note/yf2q/p2nv)
apt-get install xfs
service xfs start
apt-get install xfonts-75dpi
xset +fp /usr/share/fonts/X11/75dpi
xset fp rehash

mpiuser@ub0:~$ sudo reboot #after reboot, the problem is gone
8.4.2. Configure hosts
"Host Configuration" -> "Administration Host" -> Add master node and other administrative nodes
"Host Configuration" -> "Submit Host" -> Add master node and other submit nodes
"Host Configuration" -> "Execution Host" -> Add slave nodes
->Click on "Done" to finish

8.4.3. Configure user
Add or delete users that are allowed to access SGE here. In this example, a user is added to an existing group and later this group will be allowed to submit jobs. Everything else is left as default values.

"User Configuration" -> "Userset" -> Highlight userset "arusers" and click on "Modify" -> Input user name in "User/Group" field
->Click "Done" to finish

8.4.4. Configure queue
While Host Configuration deals what computing resources are available and User Configuration defines who have access to the resources, this Queue Control defines ways to connect hosts and users.

"Queue Control" -> "Hosts" -> Confirm the execution hosts show up there.

"Queue Control" -> "Cluster Queues" -> Click on "Add" -> Name the queue, add execution nodes to Hostlist;
and
"Use access" -> allow access to user group arusers;
"General Configuration" -> Field "Slots" -> Raise the number to total CPU cores on slave nodes (ok to use a bigger number than actual CPU cores).

"Queue Control" -> "Queue Instances" -> This is the place to manually assign hosts to queues, and control the state (active, suspend ...) of hosts.

8.4.5. Configure parallel environment
"Queue Control" -> "Cluster Queues" -> Select a queue that will run parallel jobs -> Click on "Modify" -> "Parallel Environment" -> Click on icon "PE" below the right and left arrows -> Click on "Add" -> Name the PE, slots = 999, start_proc_args = $SGE_ROOT/mpi/startmpi.sh $pe_hostfile, stop_proc_args = $SGE_ROOT/mpi/stopmpi.sh, allocation_rule=$fill_up, check "Control slaves" to make this variable checked.

Make sure the configured PE is loaded from "Available PE" to "Referenced PE".

Confirm and close all config windows and open "Queue Control" -> "Cluster Queues" -> "Parallel Environment" again, the named PE should show up.

Once created and linked to a queue, PE can be edited from "Queue Control" -> "PE" too.

8.5. Check whether sge hosts are running properly
mpiuser@ub0:~$ qhost #it should list the system info from all nodes
mpiuser@ub0:~$ qconf -sel #it should list the hostnames of nodes
mpiuser@ub0:~$ qconf -sql #it should list the queues
mpiuser@ub0:~$ ps aux | grep sge_qmaster | grep -v grep #check master daemon
mpiuser@ub0:~$ ps aux | grep sge_execd | grep -v grep #check execute daemon
mpiuser@ub1:~$ ps aux | grep sge_ execd | grep -v grep #check execute daemon

#If sge_qmaster or sge_execd daemon is not running, try starting by service
#mpiuser@ub1:~$ sudo service gridengine-master start
#mpiuser@ub1:~$ sudo service gridengine-exec start

#Reboot node(s) if sge_qmaster or sge_execd fails to start

8.6. Run a test script
Make a script named ‘test’ with content:
#!/bin/bash
### Request Bourne shell as shell for job
#$ -S /bin/bash
### Use current directory as working directory
#$ -CWD
### Name the job:
#$ -N test
echo “Running environment:”
env
echo “=============================”
###end of script

To submit the job: qsub test
#a job id returned if successful
Query the job status: qstat
#If the job is running successfully, there will be two output files produced in the current working directory with name test.oXXX (the standard output) and test.eXXX (the standard error), where test is the job name and XXX is the job id.

8.7. Check log messages if error occurs
mpiuser@ub0:~$ less /var/spool/gridengine/qmaster/messages #master node
mpiuser@ub0:~$ less /var/spool/gridengine/execd/ub0/messages #exec node

8.8. Common problems
Problem #1: Output file has a Warning: no access to tty (Bad file descriptor).Thus no job control in this shell.
Solution: This warning happens if you are using the tcsh or csh as shell for submitting job. It is safe to ignore this warning. Alternatively you can qsub -S /bin/bash to run your program in different shell or add a line of ‘#$ -S /bin/bash’ in the job script. [Modified from Ref. 2]
Problem #2: Master host failed to respond properly. Error message is “error: commlib error: access denied (client IP resolved to host name ‘ub0…’. This is not identical to clients host name ‘ub0’) error: unable to contact qmaster using port 6444 on host ‘ub0’”
Solution: Reboot the master node or install the SGE from source code on master node (this possible solution is not confirmed yet). In some situations, this error could be due to that the utility of gethostname (full path is ‘/usr/lib/gridengine/gethostname’ on our machines) returns a different hostname to that from running command ‘hostname -f’. If this is the case (e.g., host having multiple network interfaces), create a file named ‘host_aliases’ under ‘$SGE_ROOT/$SGE_CELL/common’ and populate as follows,
# cat host_aliases
ub0 ub0.my.com ub0-grid
ub1 ub1.my.com ub1-grid
ub2 ub2.my.com ub2-grid
ub3 ub3.my.com ub3-grid
and then restart the gridengine daemon (see man page of sge_host_aliases for details). Check the aliases:
mpiuser@ub0:~$ /usr/lib/gridengine/gethostname -aname ub0-grid
mpiuser@ub0:~$ /usr/lib/gridengine/gethostname -aname ub0
#both of them should return ub0

References
1. Put SGE and MPICH together under Ubuntu 9.10 (http://pka.engr.ccny.cuny.edu/~jmao/node/51)
2. http://system.cs.odu.edu/?page=cluster

Set Up an MPICH2 Cluster With Ubuntu Server 11.04

This is a short note of setting up MPI cluster with Ubuntu system. Assume four machines named ub0-3, with ub0 being the master node. They are connected through private local network. At the time of writing this note, the operating system of these machines is Ubuntu Server 11.04.

1. Define hostnames in /etc/hosts

Edit /etc/hosts like this (change IP address accordingly):

127.0.0.1 localhost

192.168.133.100 ub0

192.168.133.101 ub1

192.168.133.102 ub2

192.168.133.103 ub3



2. Share files through NFS

2.1. Install NFS server on the master node:

user@ub0:~$ sudo apt-get install nfs-kernel-server

2.2. Make a directory to be exported:

user@ub0:~$ mkdir /mirror

2.3. Edit file /etc/exports by adding a line like this:

/mirror ub1_hostname(rw,sync,no_subtree_check) ub2_hostname(…) …

2.4. Restart the NFS service:

user@ub0:~$ sudo service portmap restart

user@ub0:~$ sudo service nfs-kernel-server restart

2.5. Configure firewall to open two ports 111 and 2049 if necessary:

user@ub0:~$ sudo iptables -I INPUT num -p tcp --dport 111 –s ub1_hostname --j ACCEPT

user@ub0:~$ sudo iptables -I INPUT num -p tcp --dport 2049 --s ub1_hostname --j ACCEPT



2.6. Mount the directory on client machines:

user@ub1:~$ sudo apt-get install nfs-common

user@ub1:~$ sudo mount ub0:/mirror /mirror



3. Set up an user account for running MPI

3.1. Create a user with same name and same userid on all nodes with a home directory in /mirror:

user@ub0:~$ sudo useradd -d /mirror/mpiuser -m -s /bin/bash mpiuser

user@ub0:~$ sudo passwd mpiuser

… #repeat the same process on other nodes (same password on all the nodes is not necessary)

3.2. Change the owner of /mirror to mpiuser:

user@ub0:~$ sudo chown mpiuser /mirror



4. Install SSH server on all nodes if SSH not available

user@ub0:~$ sudo apt--get install openssh--server



5. Setup SSH with no pass phrase for communication between nodes

5.1. Log in with the new user on the master node:

user@ub0:~$ su mpiuser

5.2. Generate ssh key:

mpiuser@ub0:~$ ssh-keygen -t dsa # Leave passphrase empty. A folder called .ssh will be created in the home directory. This folder will contain a file id_dsa.pub that contains the public key.
mpiuser@ub0:~$ ssh-keygen -t rsa # Leave passphrase empty. A folder called .ssh will be created in the home directory if not exist previously. This folder will have a file id_rsa.pub which contains the public key and a file id_rsa which contains the private identification.

(Update on 11/05/2014. SSH can use either "RSA" (Rivest-Shamir-Adleman) or "DSA" ("Digital Signature Algorithm") keys. Both of these were considered state-of-the-art algorithms when SSH was invented, but DSA has come to be seen as less secure in recent years. RSA is the only recommended choice for new keys. Please see ref 3)

5.3. If, as in the present note, the home directory is shared by NFS between master and slave nodes for user mpiuser, run the following command on the master node so as to copy public key to ~/.ssh/authorized_keys and then go to step 5.5: (Updated on 24 August 2012)

mpiuser@ub0:~$ cat ~/.ssh/id_dsa.pub >>~/.ssh/authorized_keys
mpiuser@ub0:~$ cat ~/.ssh/id_rsa.pub >>~/.ssh/authorized_keys

#please note the file ~/.ssh/authorized_keys should be in mode '644'

5.4. If the home directory is not shared by NFS between master and slave nodes for user mpiuser, transfer the public key file id_dsa.pub id_rsa.pub to slave nodes. On the slave nodes, log in as mpiuser, and then add the key generated from master node to file ~/.ssh/authorized_keys:

mpiuser@ub1:~$ cat id_dsa.pub >>~/.ssh/authorized_keys
mpiuser@ub1:~$ cat id_rsa.pub >>~/.ssh/authorized_keys

#please note the file ~/.ssh/authorized_keys should be in mode '644'


5.5. To test passwordless SSH login, run this command on the master node:

mpiuser@ub0:~$ ssh ub1 hostname

#It should return remote hostname without asking for passphrase.

(Update 2: to resolve file permission issue, ensure the user of accessing NFS shared files have same UID and GID on both server and client. Edit /etc/passwd and /etc/group when necessary)

6. Install GCC and other compilers

mpiuser@ub0:~$ sudo apt-get install build-essential



7. Install MPICH2

7.1. Install through package or using Synaptic:

mpiuser@ub0:~$ sudo apt-get install mpich2

7.2. Test installation by running:

mpiuser@ub0:~$ which mpiexec

mpiuser@ub0:~$ which mpirun

#If successful, paths to the two executables should be return

7.3. Set up Hydra Process Manager (which replaces MPD) on master node:

7.3.1. Create a file with the names of the nodes

mpiuser@ub0:~$ cat hosts

ub1:8 #8 is the number of cpu cores available

ub2:8

ub3:8

ub0:7

7.3.2. The hosts file can also be designated by setting variable HYDRA_HOST_FILE:

mpiuser@ub0:~$ echo HYDRA_HOST_FILE=/etc/hydra/hosts >> ~/.bashrc
#Note: do not set this environment variable HYDRA_HOST_FILE if the MPI environment is to be controlled by a cluster queueing system like SGE. (Updated on 17 May 2012)


7.4. Test parallel computation

7.4.1. Compile an application with mpicc:

mpiuser@ub0:~$ mpicc cpi.c -o cpi

#cpi.c is an example provided by the MPICH2 library

#On my machine, running mpicc got an error:

#/usr/bin/ld: cannot find –lcr

#collect2: ld returned 1 exit status

#This problem is due to missing package ‘libcr-dev’

#Install libcr-dev: mpiuser@ub0:~$ sudo apt-get install libcr-dev

7.4.2. Run the application using mpiexec:

mpiuser@ub0:~$ mpiexec -np 1 ./cpi #using single core

mpiuser@ub0:~$ mpiexec -np 16 ./cpi #using 16 cores

#Note the path to the executable (‘./’ here) should be specified, otherwise an error produced: HYDU_create_process (./utils/launch/launch.c:69): execvp error on file cpi (No such file or directory) (Updated on 17 October 2011)

#If hydra is not the default process manager for MPICH2, running mpi program with mpiexec may cause an error that all processes have rank 0. To overcome this error, use mpiexec.hydra instead of mpiexec (Updated on 17 October 2011)

#Configure firewall if connection is blocked, eg,

#mpiuser@ub0:~$ sudo iptables -I INPUT 1 -s ub1 -j ACCEPT

(Update 1: I've posted a relevant topic "Install Sun Grid Engine (SGE) on Ubuntu Server 11.04")

References
1. Setting Up an MPICH2 Cluster in Ubuntu (https://help.ubuntu.com/community/MpichCluster)
2. MPICH2 Developer Decumentation (http://wiki.mcs.anl.gov/mpich2/index.php/Developer_Documentation)
3. https://help.ubuntu.com/community/SSH/OpenSSH/Keys

Thursday, March 24, 2011

Print an array in clockwise direction

Original post has been deleted by the author.

Friday, March 11, 2011

Solve sudoku puzzle with logic and brute force

#!/usr/bin/perl -w
use strict;
# A perl script to solve sudoku puzzle using brute force
# Author: MH Wang

my ($file)=('problem.txt'); #input file containing sudoku puzzle matrix
#example of problem.txt (no leading # in the real file; uncompleted grids are filled with 0)
#0 0 0 0 0 0 2 0 0
#0 5 8 0 0 6 0 0 0
#0 0 0 3 0 0 0 8 5
#0 1 0 4 7 0 6 0 0
#9 0 6 0 0 0 5 0 7
#0 0 7 0 3 9 0 4 0
#7 6 0 0 0 8 0 0 0
#0 0 0 9 0 0 8 1 0
#0 0 9 0 0 0 0 0 0
my (@arr,%nums);

&readPuzzle(\@arr,$file);
&prtMatrix(\@arr);
&initialize(\@arr,\%nums);
&solve(\@arr,\%nums);
&prtMatrix(\@arr);

sub prtMatrix{
my $arr=$_[0];
for(my $i=0;$i<9;$i++){ j="0;$j<9;$j++){">[$j];
}
print "\n";
}
}
sub prtProb{
my ($nums,$toPrt)=@_;
$toPrt=0 if(! defined($toPrt));
my $nempty=0;
foreach my $k(keys %$nums){
foreach (keys %{$$nums{$k}}){
$nempty++;
if($toPrt){
print "$k-$_ ",(keys %{$$nums{$k}{$_}}),"\n";
}
}
}
print "$nempty empty cells\n" if($toPrt);
return($nempty);
}
sub readPuzzle{
my ($arr,$file)=@_;
open(FI,$file) || die "Can't open $file\n";
for(1..9){
chomp($_=<FI>);
push(@$arr,[split (/\s+/,$_)]);
}
close(FI)
}
sub initialize{ #to initialize all possible answers for every empty grid
my ($arr,$nums)=@_;
for(my $i=0;$i<9;$i++){ j="0;$j<9;$j++){" nempty="&logic_puzzle($arr,$nums);" nempty="="0);" itry="0;" nempty="&try_puzzle($arr,$nums,\$itry);">[2] <=> $b->[2]} @nem){
foreach (keys %{$$nums{$inem->[0]}{$inem->[1]}}){
my @rarr;
for(my $i=0;$i<@$arr;$i++){ my @xarr=@{$$arr[$i]}; $rarr[$i]=\@xarr; } my %rnums; foreach my $ir(keys %$nums){ foreach my $ic(keys %{$$nums{$ir}}){ foreach (keys %{$$nums{$ir}{$ic}}){ $rnums{$ir}{$ic}{$_}=$$nums{$ir}{$ic}{$_}; } } } $rarr[$inem->[0]][$inem->[1]]=$_;
delete($rnums{$inem->[0]}{$inem->[1]});
$nempty=&logic_puzzle(\@rarr,\%rnums);
if($nempty==0){
@$arr=@rarr;
%$nums=%rnums;
return($nempty);
}elsif($nempty>0){
$nempty=&try_puzzle(\@rarr,\%rnums,$itry);
if($nempty==0){
@$arr=@rarr;
%$nums=%rnums;
return($nempty);
}
}
}
return($nempty);
}
return(-1);
}
sub logic_puzzle{ # to iteratively eliminate, for each empty grid, answers incompatible with the numbers published in the puzzle
my ($arr,$nums)=@_;
my ($blkChk,$rowChk,$colChk);
my $nstep=0;
my $nempty=81;
do{
#print "Cycle ",++$nstep,"\n";
for(my $i=0;$i<9;$i=$i+3){ j="0;$j<9;$j="$j+3){" rv="chkBlk($arr,$nums,[$i..($i+2)],[$j..($j+2)]);" rv="="-1);" i="0;$i<9;$i++){" rv="chkBlk($arr,$nums,[$i],[0..8]);" rv="="-1);" rv="chkBlk($arr,$nums,[0..8],[$i]);" rv="="-1);" itmp="&prtProb($nums,0);" nempty="="$itmp);" nempty="$itmp;">0);
return ($nempty);
}
sub chkBlk{ #to check a 9-cell block
my ($arr,$nums,$row,$col)=@_;
my $blkChk=listNumbers($arr,$row,$col);
return(-1) if(exists($$blkChk{0})); #incomptatible
return(0) if(scalar keys %$blkChk==0); #a completed 3x3 block
foreach my $ii (@$row){
next if(! exists($$nums{$ii}));
foreach my $jj (@$col){
next if(! exists($$nums{$ii}{$jj}));
my @hkeys=keys %{$$nums{$ii}{$jj}};
foreach(@hkeys){
if(!exists($$blkChk{$_})){
delete($$nums{$ii}{$jj}{$_});
}else{
$$blkChk{$_}++; #to count the frequencies of undecided numbers
}
}
@hkeys=keys %{$$nums{$ii}{$jj}};
if(scalar @hkeys==1){
$$arr[$ii][$jj]=$hkeys[0];
delete($$blkChk{$hkeys[0]});
delete($$nums{$ii}{$jj});
}elsif(scalar @hkeys==0){
return -1;
}
}
}
my @bkeys=keys %$blkChk;
foreach my $bk (@bkeys){ #to look for singletons in undecided numbers, ie, frequency=1
next if $$blkChk{$bk}>1;
foreach my $ii (@$row){
next if(! exists($$nums{$ii}));
foreach my $jj (@$col){
if(exists($$nums{$ii}{$jj}) && exists($$nums{$ii}{$jj}{$bk})){
$$arr[$ii][$jj]=$bk;
delete($$blkChk{$bk});
delete($$nums{$ii}{$jj});
}
}
}
}
return 0
}
sub listNumbers{ #to list undecided numbers in a 9-cell block
my ($arr,$row,$col)=@_;
my %pr=map +($_=>0),1..9;
foreach my $ir (@$row){
foreach (@$col){
if($$arr[$ir]->[$_]>0){
if(! exists($pr{$$arr[$ir]->[$_]})){
return {0=>0};
#print "Not a valid puzzle. Check row ",$ir+1," column ",$_+1,"\n";
#exit;
}
delete($pr{$$arr[$ir]->[$_]});
}
}
}
return \%pr;
}