[클러스터] Globus 1.1.4 사용자 가이드

UserGuide – Globus 1.1.4

작성자: 권오경 (okkwon@kisti.re.kr)

최종 수정 날짜: 2002-05-08

이 문서는 Globus 1.1.4 툴킷을 리눅스 PC에 설치한후 사용하는 방법을 설명한다.

RedHat Linux 7.1(Linux 커널 버젼은 2.4.2)을 기준으로 설명하였으며,

Linux 표준 쉘인 bash 쉘을 이용한다고 가정하였다.

‘#’는 root 프롬프트를 의미하고, ‘$’는 사용자 프롬프트를 의미한다.

globus version: 1.1.4

example hostname: sdd47.hpcnet.ne.kr(localhost), sdd113.hpcnet.ne.kr

OS: RedHat 7.1

kernel version: 2.4.2-2

gcc version: 2.96

목차

설정이 제대로 되었나?

Proxy 생성

Hello World 1

Hello World 2

Hello World 3

Hello World 4

GASS를 사용해보자.

MPICH-G2를 사용해보자.

참고문서

——————————————————————————–

설정이 제대로 되었나?  [[목차]]

$/opt/globus/sbin/globus-setup-test

Checking certificate directory ……….done.

Checking user certificate setup ………done.

Checking user key setup ……………..done.

Creating proxy certificate …………..

.Enter PEM pass phrase:

verify OK

…+++++

….+++++

…………………………………..done.

Checking user proxy setup ……………done.

Searching MDS for contact strings …….done

Testing “jobmanager” service  on sdd47.hpcnet.ne.kr

Authentication test …………………Success!

Submission test …………………….Success!

Testing Completed!

globus-setup-test가 성공적으로 마쳐지면 이제 이용을 할수 있는 준비가 된것이다.

각 자원이 제대로 사용할 수 있는지 알기 위해서 다음과 같은 명령어를 사용해 본다.

$ globusrun -a -r localhost

$ globusrun -a -r sdd113.hpcnet.ne.kr

localhost에 대해서 다음과 같은 에러가 발생할것이다.

globusrun: Error initializing GRAM: authentication with the remote server failed

인증을 받아서 사용할려면 다음과 같이 Proxy를 만들어야 한다.

Proxy 생성  [[목차]]

Globus를 시작 할때마다 사용자는 Proxy를 먼저 만들어야 한다.

grid-proxy-init

Proxy는 필요할때 Globus에 대한 certificate를 제공한다.

사용자는 한번 Proxy를 만들면 더이상 암호를 입력할 필요가 없다.

하지만 이 Proxy는 정해진 시간에만 유효하다. 기본적으로 12시간을 주고

-hours 옵션을 사용해서 시간을 재조정할 수 있다.

grid-proxy-info

Proxy가 얼마나 유효한지에 대한 정보를 알수 있는 명령어이다.

-all 옵션을 사용해서 유효한 시간 뿐아니라 다른 정보에 대해서 알수 있다.

subject  : /O=Grid/O=Globus/OU=hpcnet.ne.kr/CN=gfk/CN=proxy

issuer   : /O=Grid/O=Globus/OU=hpcnet.ne.kr/CN=gfk

type     : full

strength : 512 bits

timeleft : 0:00:00

grid-proxy-destory

grid-proxy-init를 통해 만들어진 Proxy를 소멸 시키는 명령어이다.

/tmp/x509up_… 형태로 생성이 된 Proxy 파일을 제거시키게 된다.

$ globusrun -a -r localhost

GRAM Authentication test successful

위와 같은 메세지를 받았으면 이제 그리드를 이용해보자.

Hello World 1   [[목차]]

job을 실행하기 위해서 두가지 방법이 있다.

첫번째 방법은 globus-job-run을 사용해서 결과를 바로 얻는 것이다.

문법 :

$ globus-job-run <hostname> </path/executable> <arguments>

예제:

$ globus-job-run localhost /bin/echo “Hello World”

Hello World

$ globus-job-run sdd113 /bin/echo “Hello World”

Hello World

이때 path는 실행 파일(executable)이 있는 곳의 절대 경로를 적어야 한다.

두번째 방법은 globus-job-submit을 사용(batch 작업)해서 결과를 간접적으로 얻는 방법이다.

$ globus-job-submit localhost /bin/echo “Hello World”

https://sdd47.hpcnet.ne.kr:37973/26741/1019356045/

실행을 하고 나면 위와 같은 URL주소를 나타낸다.

즉 작업에 대한 결과는 위의 URL주소를 통해 얻을 수 있다.

위의 https주소는 Globus에서 제공하는 GASS서버의 주소로서

다음과 같이 작업의 상태(진행중인지 마쳤는지)를 먼저 알아야 한다.

$ globus-job-status https://sdd47.hpcnet.ne.kr:37973/26741/1019356045/

DONE

위와 같이 작업이 마쳤는지 확인이 끝나면 이제 작업의 stdout결과를 얻어와야 한다.

$ globus-job-get-output https://sdd47.hpcnet.ne.kr:37973/26741/1019356045/

Hello World

참고 : 여기서 gass-cache 관련 에러가 발생하면 설치과정에서 문제가 발생한 것이다.

Hello World 2  [[목차]]

Hellow World를 실행하는 shell script를 다음과 같이 만들어 보자.

$ vi hello.sh

#!/bin/sh

echo “Hello World from $1”

:wq

$ chmod +x hello.sh

위와 같이 globus-job-run을 사용해서 로컬 기계(sdd47)에서 실행 시켜보자.

$ globus-job-run localhost hello.sh globus

Hello World from globus

위의 Hello World가 성공 했다면 이것 또한 쉽게 성공할 수 있을 것이다.

이제 sdd113에서 실행을 해보자.

$ globus-job-run sdd113 hello.sh globus

GRAM Job submission failed because the executable does not exist (error code 5)

위의 Hello World 예제는 localhost와 sdd113각 기계에 /bin/echo이

설치가 되어 있어서 sdd113의 기계를 원격적으로 실행할 수 있다.

하지만 a.sh은 sdd113에 있지 않기 때문에 바로 실행이 안된다.

a.sh을 sdd113으로 옮길 수 있어야 한다. 그래서 -stage 옵션을 통해서

실행 파일인 a.sh이 원격지에 자동으로 옮겨지게 된다.

다음을 실행해보자.

$ globus-job-run sdd113 -stage hello.sh globus

Hello World from globus

참고 : globus-job-submit 또한 stage를 지원하지만 globus-1.1.4 버전에서는 stage 옵션에 관한 버그로 인해 실행이 안된다.

Hello World 3  [[목차]]

이번에는 globusrun이라는 프로그램을 이용해서 Hello World를 호출한다.

globusrun은 Globus Resource Specification Langauge(RSL)로 작성된 스크립트를 작동시키는데 사용된다.

그러면 RSL로 만들어진 script를 하나 만들어보자.

$ vi hello.rsl

& (executable=/bin/echo)

(arguments=”Hello Globus World”)

:wq

$ globusrun -s -r sdd113 -f hello.rsl

Hello Globus World

RSL에서 executable은 실행되는 파일의 절대 경로, arguments는 인자들이다.

globusrun에서 -f 옵션를 통해서 RSL 파일을 정하고, -r 옵션을 통해서 실행되는 리소스를 정한다.

-s 옵션은 GASS 서버를 실행시키는 옵션이다. 자원이 원격지에서 실행되었을때 stdout과 stderr를

GASS 서버를 통해 가져온 뒤 로컬의 stdout과 stderr로 전달해주게 된다.

이번에는 위의 hello.sh를 RSL로 만들어 보자.

$ vi hello2.rsl

& (executable=$(GLOBUSRUN_GASS_URL) # “/home/gfk/hello.sh”)

(arguments=”globus”)

:wq

$ globusrun -s -r sdd113 -f hello2.rsl

Hello Globus World from globus

globusrun은 -s 옵션을 통해 GASS 서버를 실행시킨 다음에 GLOBUSRUN_GASS_URL 변수에

GASS 서버의 주소를 할당하게 된다. executable자체는 로컬시스템의 파일 뿐아니라 위와 같이

GASS서버의 주소까지 사용할 수 있다. 그러면 원격 자원의 HOME

directory에 hello.sh를 복사를 한뒤 실행이 이루어진다.

(실행되는 디렉토리는 directory라는 rsl문법을 통해 설정가능하다.)

다 끝나면 지우는 역할까지 globusrun에서 이루어진다.

참고 : globus-job-run은 RSL 스크립트를 만든 다음에 globusrun에 해당 스크립트를 넘겨주게 된다.

globus-job-run을 다음과 같이 -dumprsl 옵션을 사용하면 RSL을 볼 수 있다.

$ globus-job-run -dumprsl sdd113 -stage hello.sh globus

  &(executable=$(GLOBUSRUN_GASS_URL) # “/home/gfk/hello.sh”)

   (arguments= “globus”)

즉 -stage 옵션을 사용하면 GASS서버를 띄워서 원격지로 실행파일을 옮기게 된다.

globus-job-submit 프로그램도 RSL 스크립트를 만든 다음에 globusrun에 넘겨준다.

$ vi submit.rsl

&(executable=”/bin/ls”)

(stdout=x-gass-cache://$(GLOBUS_GRAM_JOB_CONTACT)stdout anExtraTag)

(stderr=x-gass-cache://$(GLOBUS_GRAM_JOB_CONTACT)stderr anExtraTag)

:wq

$ globusrun -b -r sdd113 -f submit.rsl

https://sdd113.hpcnet.ne.kr:40558/31200/1019802180/

$ globus-job-status https://sdd113.hpcnet.ne.kr:40558/31200/1019802180/

DONE

$ globus-job-get-output https://sdd113.hpcnet.ne.kr:40558/31200/1019802180/

doc

globus

src

tmp

stdout부분에 x-gass-cache주소로 값을 넣어주면, 프로그램이 실행하는 stdout은

x-gass-cache의 주소로 값을 넣게 된다. 뒤의 anExtraTag는 tag이름이다.  

sdd113으로 가서 ~/.gass_cache/globus_gass_cache_state 파일을 확인해보자.

그리고 globus-gass-cache -list를 통해 등록이 되어 있는지 살펴보자.

이렇게 되어 있으면 globus-job-get-output는 위의 cache를 통해 값을 얻어올 수 있다.

globusrun에서 -b 옵션을 통해 batch작업이 이루어지고 GASS에 대한 URL을 얻어 온다.        

만약 위의 RSL 같이 stdout을 설정하지 않으면 GASS에 대한 URL을 얻어 오더라도

stdout의 기본설정인 /dev/null로 stdout이 날아가기 때문에

globus-job-get-output을 통해서 값을 못 얻는다.

위의 executable에 GLOBUSRUN_GASS_URL변수를 넣어서 stage를 해보자. 아마

globusrun에서 에러가 발생할 것이다. globus-job-submit에서 stage가

안된 것은 여기서의 버그 때문에 작동이 되지 않는 것이다.

Hello World 4  [[목차]]

이번에는 localhost와 sdd113에 동시에 Hello World를 호출하는 작업을 해보자.

jobA, jobB 이렇게 두개의 script를 먼저 작성 해보자.

$ vi jobA

#!/bin/csh -f

set tools_bin = `$GLOBUS_INSTALL_PATH/bin/globus-tools-path -bindir`

echo “”

echo -n “Hello World A on ” ; $tools_bin/globus-hostname

:wq

$ vi jobB

#!/bin/csh -f

set tools_bin = `$GLOBUS_INSTALL_PATH/bin/globus-tools-path -bindir`

echo “”

echo -n “Hello World B on ” ; $tools_bin/globus-hostname

:wq

$ chmod +x jobA jobB

jobA는 localhost에 jobB는 sdd113에 호출을 하기로 한다.

$ globus-job-run -: localhost ./jobA  -: sdd113  -stage ./jobB

Hello World A on sdd47.hpcnet.ne.kr

/home/globus/globus/ResourceManagement/duroc/src/control/job_monitor.c: 925: job already canceled failure 0

/home/globus/globus/ResourceManagement/duroc/src/control/job_monitor.c: 925: job already canceled failure 0

-: delimiter를 통해서 각 subjob들을 동시에 요청할 수 있게 된다.

하지만 위에서 보는것 같이 에러가 발생한다. 왜냐하면 subjob들을 동시에 요청할 때

기본적으로 DUROC을 통해서 한다. 그리고 각 subjob들을 처리하는 GRAM이 atomic하게 서로의 리소스를

제어하기 위해 DUROC은 barrier를 사용하게 된다. 그리고 각 subjob들은 job_start_barrier함수를

호출해야 한다. 여기서는 이 shell 프로그램은 barrier를 사용할 필요가 없는데

barrier를 기본적으로 사용하게 해놓아서 에러가 발생하게 된다.

위의 globus-job-run에서 생성되는 rsl 파일을 살펴보자.

$ globus-job-run -dumprsl -: localhost ./jobA  -: sdd113  -stage ./jobB > dump.rsl

$ more dump.rsl

+

( &(resourceManagerContact=”localhost”)

   (subjobStartType=strict-barrier)

   (label=”subjob 0″)

   (executable=”/home/gfk/jobA”)

)

( &(resourceManagerContact=”sdd113″)

   (subjobStartType=strict-barrier)

   (label=”subjob 1″)

   (executable=$(GLOBUSRUN_GASS_URL) # “/home/gfk/jobB”)

)

즉 기본적으로 globus-job-run프로그램이 subjob을 시작하면서

barrier를 strict로 해놓아서 문제가 생겼다.

여기서 subjobStartType=no-barrier로 고치고 globusrun을 사용해서 작업을 시작해보자.

$ more dump.rsl

+

( &(resourceManagerContact=”localhost”)

   (subjobStartType=no-barrier)

   (label=”subjob 0″)

   (executable=”/home/gfk/jobA”)

)

( &(resourceManagerContact=”sdd113″)

   (subjobStartType=no-barrier)

   (label=”subjob 1″)

   (executable=$(GLOBUSRUN_GASS_URL) # “/home/gfk/jobB”)

)

$ globusrun -s -f dump.rsl

Hello World A on sdd114.hpcnet.ne.kr

Hello World B on sdd113.hpcnet.ne.kr

GASS를 사용해보자.  [[목차]]

Globus Access to Secondary Storage(GASS)는 원격지와 로컬의 데이터에 대한 쉬운 접근과 사용을 위한 프로그램과 C API를 제공한다.

globus-rcp

파일 전송을 위한 가장 쉬운 방법이다. Unix의 rcp프로그램과 같은 기능을

제공한다. globus-rcp라는 프로그램은 다음과 같은 일을 자동으로 하는 shell 스크립트이다.

작업의 복사가 이루어질 곳에 globus-gass-server를 띄우고 globus-url-copy를 이용해서

복사가 이루어진다음 다시 GASS서버를 멈추는 일을 한다.

$ globus-rcp hello.sh sdd113:/home/globus/hello.sh

파일에 대한 주소는 다음과 같은 문법으로 나타낸다. file path가 상대

주소일 경우에 로컬 기계이면 `pwd` 디렉토리 부터이고, 원격 기계이면

원격지 계정의 HOME 계정 부터이다.

[<remote computer>:]<file path>

예제) sdd113:~globus/hello.sh, sdd113:/home/globus/hello.sh, sdd113:hello.sh

참고 : -r 옵션을 통한 재귀적 복사는 가능하지만 *, ?등은 지원이 안된다.

globus-gass-server

원격의 클라이언트에게 자원을 사용하고 있는 파일들을 사용할 수 있게 한다.

localhost(sdd47)에서 실행을 해보자.

$ globus-gass-server -t -u -r -w -c -o -e &

https://sdd47.hpcnet.ne.kr:38563

위와 같이 URL주소를 출력한다. 사용자는 위의 주소를 사용해서 자원을 얻게 된다.

https://hostname:port/~/file : a file from your home directory

https://hostname:port/./file : a file from the directory in which the globus-gass-server is running

https://hostname:port/tmp/file : a file with an absolute path

하지만 실제로 사용자가 서버를 띄우는 일보단 globus의 각 프로그램들이

자동으로 띄우는 일이 많다. 사용자가 서버를 수동으로 띄우는 경우에는

RSL 파일에서 $(GLOBUSRUN_GASS_URL) 대신 위의 주소를 직접 사용해야 된다.

즉 Hello World 3의 hello2.rsl을 다음과 같이 바꿀 수 있다.

$ more hello2.rsl

& (executable=”https://sdd47.hpcnet.ne.kr:38563/home/gfk/hello.sh”)

(arguments=”globus”)

참고 : globus-gass-server 옵션 중에서 -c는 붙이는게 좋다. 그래야, globus-gass-server-shutdown을 이용해서

GASS 서버가 중지될 수 있다. -c를 붙이지 않는 경우에는 kill을 이용해서

강제적으로 중지시켜야 한다.

만약, 위의 globus-rcp hello.sh sdd113:/home/globus/hello.sh 처럼 sdd47에서 sdd113의

GASS 서버를 이용하고 싶을때는 telnet sdd113으로 들어가서 globus-gass-server를 명령하면 안된다.

다음과 같이 globus-job-run을 이용해서 sdd47에서 실행해주어야 globus-url-copy를 이용할 수 있다.

$ globus-job-run sdd113 /usr/local/globus/tools/i686-pc-linux-gnu/bin/globus-gass-server -t -u -r -w -c -o -e &

https://sdd113.hpcnet.ne.kr:38563

sdd47에서 띄운 sdd113에 띄운 globus-gass-server를 멈추게 하기

위해선 다음과 같이 globus-gass-server-shutdown 스크립트를 이용해서

할수 있다.

$ globus-job-run sdd113 /usr/local/globus/tools/i686-pc-linux-gnu/bin/globus-gass-server-shutdown  https://sdd113.hpcnet.ne.kr:38563

globus-url-copy

GASS 서버나 http, https, 로컬 파일 시스템(1.1.4에서 제공되는 프로토콜)으로 부터 자원을 접근해서

서로간에 파일을 옮기는 일을 한다.

$ globus-url-copy https://sdd113.hpcnet.ne.kr:38563/home/globus/a.txt file:/tmp/a.txt

파일에 대한 주소는 다음과 같은 문법으로 나타낸다. ~는 사용할 수 없다.

fullpath는 절대 주소이어야 되고 상대 주소는 사용이 안된다.

file:fullpath

예제) file:/home/globus/hello.sh

위와 같이 GASS 서버를 원격에서 사용자가 띄운후에 URL주소를 사용해서 하는 것보단

아래와 같이 globusrun을 이용해서 globus-gass-server를 자동으로 띄우는게 편하다.

sdd47(localhost)에서 sdd113의 파일을 가져와 보자.

$ hostname

sdd47.hpcnet.ne.kr

$ vi a.rsl

&(executable=”/usr/local/globus/tools/i686-pc-linux-gnu/bin/globus-url-copy”)

(arguments=”file:/home/globus/a.txt” $(GLOBUSRUN_GASS_URL)/tmp/a.txt)

$ globusrun -s -r sdd113 -f a.rsl

참고 : globus-rcp hello.sh sdd113:/home/globus/hello.sh를 globus-url-copy를 이용해서 직접 사용해보자.

$ hostname

sdd47.hpcnet.ne.kr

$ pwd

/home/globus

$ globus-job-run sdd113 /usr/local/globus/tools/i686-pc-linux-gnu/bin/globus-gass-server -t -u -r -w -c -o -e &

https://sdd113.hpcnet.ne.kr:38563

$ globus-url-copy file:/home/globus/hello.sh https://sdd113.hpcnet.ne.kr:38563/home/globus/hello.sh

$ globus-job-run sdd113 /usr/local/globus/tools/i686-pc-linux-gnu/bin/globus-gass-server-shutdown \\

https://sdd113.hpcnet.ne.kr:38563

MPICH-G2를 사용해보자.   [[목차]]

두개의 머신(sdd46, sdd113)에 대해서 응답을 주고 받는 간단한 mpi프로그램을 가지고 테스트를 해보자.

$  hostname

sdd47.hpcnet.ne.kr

% pwd

/home/gfk

$ vi ring.c

#include <stdio.h>

#include <mpi.h>

/* command line configurables */

int Ntrips;  /* -t <ntrips> */

int Verbose; /* -v */

int parse_command_line_args(int argc, char **argv, int my_id)

{

    int i;

    int error;

    /* default values */

    Ntrips = 1;

    Verbose = 0;

    for (i = 1, error = 0; !error && i < argc; i ++)

    {

        if (!strcmp(argv[i], “-t”))

        {

            if (i + 1 < argc && (Ntrips = atoi(argv[i+1])) > 0)

                i ++;

            else

                error = 1;

        }

        else if (!strcmp(argv[i], “-v”))

            Verbose = 1;

        else

            error = 1;

    } /* endfor */

    if (error && !my_id)

    {

        /* only Master prints usage message */

        fprintf(stderr, “\\n\\tusage: %s {-t <ntrips>} {-v}\\n\\n”, a

rgv[0]);

        fprintf(stderr, “where\\n\\n”);

        fprintf(stderr,

            “\\t-t <ntrips>\\t- Number of trips around the ring.  ”

            “Default value 1.\\n”);

        fprintf(stderr,

            “\\t-v\\t\\t- Verbose.  Master and all slaves log each s

tep. \\n”);

        fprintf(stderr, “\\t\\t\\t  Default value is FALSE.\\n\\n”);

    } /* endif */

    return error;

} /* end parse_command_line_args() */

main(int argc, char **argv)

{

    int numprocs, my_id, passed_num;

    int trip;

    MPI_Status status;

    MPI_Init(&argc, &argv);

    MPI_Comm_size(MPI_COMM_WORLD, &numprocs);

    MPI_Comm_rank(MPI_COMM_WORLD, &my_id);

    if (parse_command_line_args(argc, argv, my_id))

    {

        MPI_Finalize();

        exit(1);

    } /* endif */

    if (Verbose)

        printf(“my_id %d numprocs %d\\n”, my_id, numprocs);

    if (numprocs > 1)

    {

        if (my_id == 0)

        {

            /* I am the Master */

            passed_num = 0;

            for (trip = 1; trip <= Ntrips; trip ++)

            {

                passed_num ++;

                if (Verbose)

                    printf(“Master: starting trip %d of %d: ”

                        “before sending num=%d to dest=%d\\n”,

                        trip, Ntrips, passed_num, 1);

                MPI_Send(&passed_num,    /* buff  */

                       1,               /* count */

                        MPI_INT,         /* type  */

                        1,               /* dest  */

                        0,               /* tag   */

                        MPI_COMM_WORLD); /* comm  */

    

                if (Verbose)

                    printf(“Master: inside trip %d of %d: ”

                        “before receiving from source=%d\\n”,

                        trip, Ntrips, numprocs-1);

                MPI_Recv(&passed_num,    /* buff   */

                        1,               /* count  */

                        MPI_INT,         /* type   */

                        numprocs-1,      /* source */

                        0,               /* tag    */

                        MPI_COMM_WORLD,  /* comm   */

                        &status);        /* status */

                printf(“Master: end of trip %d of %d: ”

                    “after receiving passed_num=%d ”

                    “(should be =trip*numprocs=%d) from source=%d

\\n”,

                    trip, Ntrips, passed_num, trip*numprocs, nump

rocs-1);

            } /* endfor */

        }

        else

        {

            /* I am a Slave */

            for (trip = 1; trip <= Ntrips; trip ++)

            {

                if (Verbose)

                    printf(“Slave %d: top of trip %d of %d: ”

                        “before receiving from source=%d\\n”,

                        my_id, trip, Ntrips, my_id-1);

                MPI_Recv(&passed_num,    /* buff   */

                        1,               /* count  */

                        MPI_INT,         /* type   */

                        my_id-1,         /* source */

                        0,               /* tag    */

                        MPI_COMM_WORLD,  /* comm   */

                        &status);        /* status */

                if (Verbose)

                    printf(“Slave %d: inside trip %d of %d: ”

                        “after receiving passed_num=%d from sourc

e=%d\\n”,

                        my_id, trip, Ntrips, passed_num, my_id-1)

;

                passed_num ++;

                if (Verbose)

                    printf(“Slave %d: inside trip %d of %d: ”

                        “before sending passed_num=%d to dest=%d\\

n”,

                        my_id, trip, Ntrips, passed_num, (my_id+1

)%numprocs);

                MPI_Send(&passed_num,       /* buff  */

                        1,                  /* count */

                        MPI_INT,            /* type  */

                        (my_id+1)%numprocs, /* dest  */

                        0,                  /* tag   */

                        MPI_COMM_WORLD);    /* comm  */

                if (Verbose)

                    printf(“Slave %d: bottom of trip %d of %d: ”

                        “after send to dest=%d\\n”,

                        my_id, trip, Ntrips, (my_id+1)%numprocs);

            } /* endfor */

        } /* endif */

    }

    else

        printf(“numprocs = %d, should be run with numprocs > 1\\n”

, numprocs);

    MPI_Finalize();

} /* end main() */

:wq

$ vi Makefile

MPICH_INSTALL_PATH    = /usr/local/mpich_G2

ring: force

        $(MPICH_INSTALL_PATH)/bin/mpicc -o ring ring.c

force:

clean:

        /bin/rm -rf *.o ring

:wq

$ make

/usr/local/mpich_G2/bin/mpicc -o ring ring.c

이제 ring이라는 실행 파일이 만들어 졌다.

mpi를 실행하기 위해서는 다음과 같이 machines 파일을 작성해야 한다.

$ vi machines

“sdd47.hpcnet.ne.kr” 2

“sdd113.hpcnet.ne.kr” 1

뒤의 숫자 2는 각 기계의 최대 노드 수이다.

이제 mpirun을 통해 RSL 파일을 만들어야 한다.

$ mpirun -np 3 -dumprsl ring > dump.rsl

$ more dump.rsl

+

( &(resourceManagerContact=”sdd47.hpcnet.ne.kr”)

   (count=2)

   (label=”subjob 0″)

   (environment=(GLOBUS_DUROC_SUBJOB_INDEX 0))

   (directory=”/home/gfk/”)

   (executable=”/home/gfk/ring”)

)

( &(resourceManagerContact=”sdd113.hpcnet.ne.kr”)

   (count=1)

   (label=”subjob 2″)

   (environment=(GLOBUS_DUROC_SUBJOB_INDEX 1))

   (directory=”/home/gfk/”)

   (executable=”/home/gfk/ring”)

)

-np 옵션은 전체 프로세서 숫자로써 machines파일을 참고해서 위와 같이 나눈다.

그런데 sdd113에는 /home/gfk/ring이라는 파일이 존재하지 않는다.

그래서 ring이라는 실행파일을 sdd113에 사용자가 수동으로 옮겨서 사용하던지

GASS를 사용해서 자동으로 옮겨야 한다.

사용자가 수동으로 실행파일을 옮긴다.

다음과 같이 dump.rsl을 수정한다.

$ globus-rcp -p ./ring sdd113:/home/globus/ring

$ more dump.rsl

+

( &(resourceManagerContact=”sdd47.hpcnet.ne.kr”)

   (count=2)

   (label=”subjob 0″)

   (environment=(GLOBUS_DUROC_SUBJOB_INDEX 0))

   (directory=”/home/gfk/”)

   (executable=”/home/gfk/ring”)

)

( &(resourceManagerContact=”sdd113.hpcnet.ne.kr”)

   (count=1)

   (label=”subjob 2″)

   (environment=(GLOBUS_DUROC_SUBJOB_INDEX 1))

   (directory=”/home/globus/”)

   (executable=”/home/globus/ring”)

)

$ mpirun -globusrsl d.rsl

Master: end of trip 1 of 1: after receiving passed_num=3 (should be =trip*numprocs=3) from source=2

위와 같이 mpirun에서 -globusrsl 옵션을 사용해서 RSL을 사용할 수 있게된다.

GASS를 사용해서 옮기기로 한다.

다음과 같이 dump.rsl을 수정한다.

$ more dump.rsl

+

( &(resourceManagerContact=”sdd47.hpcnet.ne.kr”)

   (count=2)

   (label=”subjob 0″)

   (environment=(GLOBUS_DUROC_SUBJOB_INDEX 0))

   (directory=”/home/gfk/”)

   (executable=”/home/gfk/ring”)

)

( &(resourceManagerContact=”sdd113.hpcnet.ne.kr”)

   (count=1)

   (label=”subjob 2″)

   (environment=(GLOBUS_DUROC_SUBJOB_INDEX 1))

   (executable=$(GLOBUSRUN_GASS_URL) # “/home/gfk/ring”)

)

$ mpirun -globusrsl d.rsl

Master: end of trip 1 of 1: after receiving passed_num=3 (should be =trip*numprocs=3) from source=2

참고 : RSL에서 arguments에 관련된 사항은 staging을 지원하지 않는다.

executable, stdin, stdout, stderr에 관련된 사항만 staging을 지원한다.

예를 들어 wav파일을 MP3로 인코딩하는 프로그램이 있다고 하면 wav파일을 원격지에 수동으로 옮겨야만 작동한다.

실행 파일을 작동시키는데 필요한 데이타나 설정파일 또한 staging을 사용자가 해줘야한다.

계산 되는 노드가 3개 이상이거나 실행 파일이 상당히 큰 경우에

GASS를 통해서 각각의 파일들을 옮기는건 상당한 시간이 걸리므로,

GASS를 사용하는 것보단 보단 사용자가 미리 옮겨 놓는 것을 생각해볼 수 있다.

참고문서  [[목차]]

1. Globus Toolkit 1.1.3 System Administration Guide, Dec. 2000

2. Globus Quick Start Guide for 1.1.3 and 1.1.4 June 2001

3. Mailing list discuss@globus.org

   (http://www-unix.globus.org/mail_archive/discuss/threads.html)

서진우

슈퍼컴퓨팅 전문 기업 클루닉스/ 상무(기술이사)/ 정보시스템감리사/ 시스존 블로그 운영자

You may also like...

1 Response

  1. smooth music 말해보세요:

    smooth music

페이스북/트위트/구글 계정으로 댓글 가능합니다.