ใช้งาน mono+rdotnet บน Rocks cluster

ตัวอย่างการใช้งาน mono + Rdotnet บนระบบ Rocks cluster ครับ

เวอร์ชั่น Rocks cluster ที่ผมใช้คือ 6.2 ครับ การติดตั้งก็แบบเดิมๆเลยตามที่อธิบายในเอกสารบนเวบของ Rocks เลย ไม่มีอะไรพิเศษ จากนั้นก็ผมก็ yum ติดตั้ง mono จาก https://copr.fedorainfracloud.org/coprs/tpokorra/mono-opt/  โดยในเวอร์ชั่นนี้ mono จะถูกติดตั้งไว้ที่ /opt/mono และก็ yum ติดตั้ง R ซึ่ง R จะถูกติดตั้งไว้ที่ /usr/lib64/R ของ head node ครับ

หลังจากที่ติดตั้ง mono และ R เรียบร้อยแล้วก็เอา code ของ C# ที่เขียนสำหรับเรียกใช้งาน rdotnet บวกกับก็อปปี้ไฟล์แอสเซมบลีของ Rdotnet ต่างๆมาไว้ใน folder ที่ต้องการก่อนทำการคอมไพล์ครับ โดยไฟล์ต่างๆของ Rdotnet ก็มีอย่างเช่น DynamicInterop.dll, RDotNet.dll, RDotNet.NativeLibrary.dll

ก่อนคอมไพล์หรือเรียกใช้งาน mono เราก็ต้องโหลดenviroment ต่างๆของ mono ก่อน โดยการพิมพ์

$ . /opt/mono/env.sh

ซึ่งมันก็คือเซ็ตpath ต่างๆของตัวแปรอย่าง LD_LIBRARY_PATH กับ PKG_CONFIG_PATH ครับ

export PATH=/opt/mono/bin:$PATH
export LD_LIBRARY_PATH=/opt/mono/lib:$LD_LIBRARY_PATH
export PKG_CONFIG_PATH=/opt/mono/lib/pkgconfig:$PKG_CONFIG_PATH

จากนั้นก็ export ค่า R_HOME ไปยัง path ของ R ที่ติดตั้งแล้ว

$ export R_HOME = “/usr/lib64/R”

อันนี้เป็นตัวอย่าง code ที่ผมก็อปปี้มาจากเวบของ RDotnet ครับ สำหรับเรียก R มาเพื่อทำ t-test ของเลข 2 ชุดครับ

#testRDotNet.cs
using System;
using System.Linq;
using RDotNet;

namespace Sample1
{
 class Program
 {
 static void Main(string[] args)
 {
 REngine.SetEnvironmentVariables();
 REngine engine = REngine.GetInstance();
 // REngine requires explicit initialization.
 // You can set some parameters.
 engine.Initialize();

// .NET Framework array to R vector.
 NumericVector group1 = engine.CreateNumericVector(new double[] { 30.02, 29.99, 30.11, 29.97, 30.01, 29.99 });
 engine.SetSymbol("group1", group1);
 // Direct parsing from R script.
 NumericVector group2 = engine.Evaluate("group2 <- c(29.89, 29.93, 29.72, 29.98, 30.02, 29.98)").AsNumeric();

// Test difference of mean and get the P-value.
 GenericVector testResult = engine.Evaluate("t.test(group1, group2)").AsList();
 double p = testResult["p.value"].AsNumeric().First();

Console.WriteLine("Group1: [{0}]", string.Join(", ", group1));
 Console.WriteLine("Group2: [{0}]", string.Join(", ", group2));
 Console.WriteLine("P-value = {0:0.000}", p);

// you should always dispose of the REngine properly.
 // After disposing of the engine, you cannot reinitialize nor reuse it
 engine.Dispose();

}
 }
}

เวลาคอมไพล์ก็เพียงพิมพ์

$ mcs /reference:RDotNet.dll /reference:RDotNet.NativeLibrary.dll /reference:DynamicInterop.dll testRDotNet.cs

ซึ่งคำสั่ง mcs นี้จะแปลงไฟล์ .cs ของเราให้เป็น binary ไฟล์ที่คอมพิวเตอร์จะเข้าใจได้ 🙂 ครับ ซึ่งในที่นี้มันจะสร้างไฟล์ชื่อ testRDotNet.exe ให้ครับ ส่วนoption ของคำสั่ง /reference เป็นการบอกว่าเราเรียกใช้ namespace จากไฟล์แอสเซมบลี่อะไรบ้าง

วิธีการรันไฟล์ exe ที่ได้จาก mcs ก็เพียงพิมพ์ mono แล้วตามด้วยไฟล์ exe ครับ เช่น

$ mono testRDotNet.exe

Welch Two Sample t-test

data: group1 and group2
t = 1.959, df = 7.0306, p-value = 0.09077
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.01956909 0.20956909
sample estimates:
mean of x mean of y
 30.015 29.920

Group1: [30.02, 29.99, 30.11, 29.97, 30.01, 29.99]
Group2: [29.89, 29.93, 29.72, 29.98, 30.02, 29.98]
P-value = 0.091

 

 

ปัญหาติดตั้ง PsN บน Rocks

PsN บอกว่าต้องการโมดูล perl Archive::Zip แต่ปรากฏว่า พอลง perl-Archive-Zip หรือ perl-Archive-Any แล้วมันก็ยังมีปัญหา

ตัวโมดูลที่ถูกต้องสำหรับลงบน Rocks (CentOs 6.6) คือ perl-Compress-Raw-Zlip

 

Rocks shutdown, reinstall

To shutdown all the compute nodes:

cluster-fork “shutdown -h now”
or
rocks run host “shutdown -h now”

To shutdown frontend:

shutdown -h now

To reboot after shutdown

rocks run host compute “/sbin/shutdown -r now”

reinstall nodes, how?
On a particular node (not on frontend)

/boot/kickstart/cluster-kickstart-pxe

On the frontend

rocks set host boot action=install compute-0-0

 

 

ตัวอย่าง SGE job file สำหรับส่งงาน R ที่ใช้ Rmpi

## Rocks 6.0

#!/bin/bash
#$ -N TestRmpi
#$ -pe mpi 16
#$ -cwd
#$ -j y
#$ -S /bin/bash
#
echo “Program start at: `/bin/date`.”
echo “Got $NSLOTS slots.”
/opt/openmpi/bin/mpirun -np 1 /usr/bin/R –slave CMD BATCH rmpitest.R
echo “Program finish at: `/bin/date`.”

———————–
### rmpitest.R
# Load the R MPI package if it is not already loaded.
if (!is.loaded(“mpi_initialize”)) {
library(Rmpi,lib.loc=”/share/apps/Rlib”)
}

# Spawn as many slaves as possible
mpi.spawn.Rslaves()

# In case R exits unexpectedly, have it automatically clean up
# resources taken up by Rmpi (slaves, memory, etc…)
.Last if (is.loaded(“mpi_initialize”)){
if (mpi.comm.size(1) > 0){
print(“Please use mpi.close.Rslaves() to close slaves.”)
mpi.close.Rslaves()
}
print(“Please use mpi.quit() to quit R”)
.Call(“mpi_finalize”)
}
}

# Tell all slaves to return a message identifying themselves
mpi.remote.exec(paste(“I am”,mpi.comm.rank(),”of”,mpi.comm.size()))

# Tell all slaves to close down, and exit the program
mpi.close.Rslaves()
mpi.quit()

การติดตั้งและใช้งาน Mathematica บนระบบ Rocks Clusters

พอดีมีโอกาสได้ติดตั้งและทดลองใช้งาน Mathematica บนระบบ Cluster ของหน่วยงานหนึ่ง ก็เลยจะมาเล่าให้ฟังครับ ระบบ Cluster ที่พูดถึงนี้ใช้ระบบ Rocks Clusters (www.rocksclusters.org) ซึ่งก็คือ Linux ที่มีการเพิ่มความสามารถการจัดการ Cluster เข้าไป งานที่ระบบ Cluster นี้ถูกใช้จะเป็นงานคำนวณด้วย software หลักๆอย่าง Gromacs, NAMD, NONMEM, R และก็ที่หน่วยงานนี้เขียนขึ้นกันเองโดยใช้ mpi บ้าง

license ของ Mathematica ที่ได้มานี้เป็นแบบ network ครับ นั่นหมายความว่าเราต้องทำการติดตั้ง Mathematica License Manager หรือ mathlm ก่อน  ซึ่งผมก็ได้ลง mathlm ไว้บน server อีกตัวซึ่งเป็นระบบ Windows server 2008 ที่หน่วยงานนี้เค้าใช้เป็น license server สำหรับโปรแกรมตัวอื่นๆด้วย ในการลงก็ไม่ได้ยุ่งยากอะไรครับเพียงแต่ตอบคำถามไปเรื่อยๆ 🙂  พอลงเสร็จ Mathlm มันก็จะ start ตัวมันเองอัตโนมัติครับ (ลองดูรายละเอียดเพิ่มเติมที่http://reference.wolfram.com/mathematica/tutorial/InstallingMathLM.html)

มาที่ตัว head node หรือตัวหลักของ cluster ผมก็ติดตั้ง Mathematica โดยใช้ตัวติดตั้งสำหรับ Linux  ซึ่งไฟล์ที่ผมได้มาเป็นไฟล์ขนาดประมาณ 1.2 GB ชื่อ Mathematica_8.0.4_LINUX_MachineSpecific.sh ในการติดตั้งผมก็เพียงแค่พิมพ์

./ Mathematica_8.0.4_LINUX_MachineSpecific.sh

ที่terminal ครับ จากนั้นก็ตอบคำถามไปเรื่อยโดยผมให้ตัว Mathematica นี้ติดตั้งตัวมันเองที่ /share/apps/Wofram/Mathematica/8.0 (/share/apps นี้เป็นdirectory ที่ทุกเครื่องใน cluster จะมองเห็น) และตัวคำสั่งในการเรียกใช้งาน (เช่น mathematica, math, MathKernel) ให้ติดตั้งไว้ที่ /share/apps/Wolfram/Mathematica/8.0/bin ในตอนที่ต้องใส่รหัสผมก็เลือกติดตั้งแบบ network โดยระบุชื่อของ license server ที่เราลง mathlm ไป

หลังจากนั้นเพื่อที่จะให้ users ทุกคนสามารถเรียกใช้งานได้ ผมก็สร้างไฟล์ชื่อ mathx.sh ไว้ที่ /share/apps/profile/ (จริงๆแล้วสร้างไว้ที่ไหนก็ได้ครับ) โดยในไฟล์นี้จะมีบรรทัดนี้อยู่ครับ

export PATH=”/share/apps/Wolfram/Mathematica/8.0/bin/:$PATH”

หลังจากนั้นก็ copy ไปไว้ที่ /etc/profile.d/ ของทุกเครื่องใน cluster ซึ่งการ copy ไฟล์ไปยังเครื่องลูก หรือ compute nodes นั้นในระบบของ rocks clusters เราสามารถใช้คำสั่งนี้ได้เลยครับ

rocks run host “cp /share/apps/profile/mathx.sh /etc/profile.d/”

ในการเรียกใช้งาน Mathematica เราก็เลือกจากเมนูหรือจะพิมพ์ Mathematica ที่ terminal ได้เลยครับ

 

การใช้งานคำนวณแบบ parallel หรือแบบขนานใน Mathematica นั้นไม่ยากเลยครับ คำสั่งหลักๆก็พวกที่ขึ้นต้นด้วย Parallel ทั้งหลายครับ ตัวอย่างที่ผมทดลองด้านล่างนี้ผมก็เอามาจากตัวอย่างใน Mathematica ครับ โดยอันแรกนี้ทดลองเรียกใช้งานโดยใช้คำสั่ง ParallelEvaluate ซึ่งมันจะโหลด Mathematica kernel เพื่อรันในแต่ล่ะ cpu core ของตัว head node ของ cluster หรือ local ซึ่งมี 8 cpu cores (Mathematica เรียก kernel ที่ถูกรันบนแต่ละ core ของ CPU แบบนี้ว่า subkernel ครับ โดยที่ตัว kernel หลักหรือ master kernel จะมี KernelID=0 ครับ)

การคำนวณแบบ parallel บนระบบของ cluster อย่างเช่น Rocks clusters นี้เราต้องทำการโหลด subkernel ไปไว้บนทุกๆ cpu cores ในแต่ละ compute node (เครื่องลูก) ที่เราต้องการใช้งาน ตัวอย่างอันที่สองนี้ผมทดลองเรียก subkernel โดยใช้ คำสั่ง LaunchKernels[RemoteMaching[]] จาก package ชื่อ SubKernels`RemoteKernels ซึ่งมากับ Mathematica (รายละเอียดสามารถดูได้จาก help ของ Mathematica เองครับ) เพื่อรัน subkernel จำนวนทั้งหมด 96 subkernels ในเครื่อง compute nodes จำนวน 8 เครื่องโดยมีจำนวน subkernels ที่ต้องการแตกต่างกันไปในแต่ล่ะเครื่อง

ซึ่งพอหลังจากที่เราโหลด subkernel เรียบร้อยแล้วเราก็สามารถใช้คำสั่งพวก parallel ทั้งหลายได้ครับ

ส่วนในกรณีที่จะใช้งานในแบบ text mode ผ่าน SGE ก็สามารถทำได้ง่ายๆตามนี้ครับ
ก็สร้างไฟล์ SGE สำหรับไว้ส่งไปรันเช่น run.job

#!/bin/bash
#$ -pe mpich 16
#$ -S /bin/bash
#$ -cwd
#$  -j y
cp -v $TMPDIR/machines TMP_machines
/share/apps/Mathematica/8.0/bin/math -run “<< testrun.math”

 

โดยที่ testrun.math ก็คือ Mathematica codes ที่ต้องการคำนวณ เช่น

Needs[“SubKernels`RemoteKernels`”]

$RemoteCommand= “ssh `1` -n -l `3` \”/share/apps/Mathematica/9.0/bin/math -mathlink -linkmode Connect `4` -linkname `2` -subkernel -noinit >& /dev/null &\””

hosts=Import[“TMP_machines”,”List”]

imin=2;
imax=Length[hosts];

Table[
Print[“starting Kernel: “,i,” on “,hosts[[i]]];
LaunchKernels[RemoteMachine[hosts[[i]]]];,
{i,imin,imax}]

id=ParallelEvaluate[$ProcessID];
AppendTo[$Echo,”stdout”]
Print[“Kernels: “, id//Length]
Print[“Prime Number Test – Parallel”]

data=Parallelize[Table[PrimeQ[n! + 1],{n,400,550}]]//AbsoluteTiming;

data2=Table[PrimeQ[n! + 1],{n,400,550}]//AbsoluteTiming;

Print[“Parallel: “,data[[1]]]
Print[“Not Parallel; “,data2[[1]]]

Exit[]

ซึ่งในกรณีของตัวอย่างนี้ Mathematica จะรันตัว subkernel เองอัตโนมัติบน CPU ที่ SGE กำหนด ตามจำนวนที่เราต้องการ ด้วยคำสั่ง LaunchKernels[n]  โดยที่ n นี้ก็คือจำนวน subkernels ที่เราต้องการใช้ในการคำนวน ซึ่งจะต้องเท่ากับจำนวน CPU ที่เรากำหนดในบรรทัด

#$ -pe mpich n