Microsoft Word - cover.docx

Save this PDF as:
 WORD  PNG  TXT  JPG

Size: px
Start display at page:

Download "Microsoft Word - cover.docx"

Transcription

1 Parallel Programming using MPICH2

2 차 례 1. Parallel Programming 환경구축 Parallel Programming using MPICH 병렬처리예제프로그램 참고자료 - 23

3 1. Parallel Programming 환경구축병렬프로그래밍을위하여널리사용되는 Message Programming Interface인 MPICH2를 Windows 에서사용하기위하여아래와같이환경설정을하고, MPICH2를설치한다. MPICH2가하나의문제를여러컴퓨터로처리하게하기위해서는아래와같은환경이필요하다. 작업에참여하는총 n대의컴퓨터는 1. 동일한작업그룹에속해있음 2. 동일한계정이름과비밀번호를사용 3. 방화벽이없어야한다. 4. MPICH2가설치되어있다. a. Windows 작업그룹설정 MPICH2를이용하여여러대의컴퓨터를하나의시스템처럼사용하기위해서는각컴퓨터들은동일한작업그룹에속해있어야한다. 아래메뉴를통하여작업에참여할모든컴퓨터들의작업그룹을동일한이름으로설정한다. [ 참고 ] MPICH2를설치한후작업에참여할컴퓨터들을설정할때이곳에설정되어있는컴퓨터이름을이용하기때문에가급적이면컴퓨터이름을식별하기쉬운이름으로설정하는것이좋다. 아래메뉴를따라작업그룹과컴퓨터이름을설정하자. 시작 -> 제어판 -> 네트워크연결 -> 고급 -> 네트워크식별 -> 변경 < 작업그룹, 컴퓨터이름설정화면 > 1

4 예를들어 PC1, PC2, PC3, PC4, PC5의이름을가진다섯대의컴퓨터를동일한작업그룹으로설정했다면 내네트워크환경 -> 작업그룹컴퓨터보기 에서각각의컴퓨터들의컴퓨터이름을확인할수있어야정상적으로작업그룹이설정된것이다. b. Windows 계정생성 MPICH2를이용한병렬처리작업에참여할모든컴퓨터는동일한계정과비밀번호를사용해야한다. 예를들면, MPICH2의작업에참여하는 5대의컴퓨터 PC1~PC5는 계정 : mpich2, 비밀번호 : campich2 와같이동일한계정과비밀번호를사용해야한다. 아래메뉴에서 MPICH2를위한새로운계정과비밀번호를생성한다. 시작 -> 제어판 -> 사용자계정 -> 새계정만들기 <MPICH2 의사용을위한사용자계정생성 > [ 주의 ] 새로생성한계정은필수적으로비밀번호를사용해야한다. 비밀번호를사용하지않는컴퓨터는 MPICH2에서사용될수없다. 2

5 c. MPICH2 설치이제 1.b 에서새로생성한계정에로그인하여아래주소의웹사이트에접속하여윈도우용 MPICH2 프로그램을다운받고설치하자. MPICH2 웹사이트 MPICH2 다운로드 MPICH2가정상적으로설치되기위해서는아래두프로그램이미리설치되어있어야한다. -Microsoft Visual C Redistributable Package (x86) -Microsoft.NET Framework Version 2.0 Redistributable Package (x86) 위두프로그램이설치되어있지않아 MPICH2가설치되지않으면구글에서위의문장으로검색을하여해당프로그램을다운로드한다. 위두프로그램을설치하였으면 MPICH2를아래와같이설치하자. (1) 기본적인안내메시지들은 Next 를클릭하여넘어간다. 3

6 4

7 (2) Passphrase 설정 Passphrase를설정하는부분은작업에참여할모든컴퓨터들이동일한 passphrase를사용해야하므로주의하자. (3) MPICH2의사용권한설정이컴퓨터내의모든계정에서이프로그램을사용할수있게할것인지, 혹은현재이인스톨러를실행중인계정에서만사용할수있게할것인지설정하는부분이다. Everyone을선택하자. 5

8 (4) 설치시작 Next 를클릭하면설치가시작된다. 설치가완료되면 Close 를클릭하여인스톨러를종료한다. 6

9 d. MPICH2 환경설정 MPICH2를모든컴퓨터에설치한후에 MPICH2가설치된각컴퓨터들이실제로연결이되는지확인하자. 아래메뉴를통하여 MPICH2 환경설정프로그램을실행한다. 시작 -> 모든프로그램 -> MPICH2 -> wmpiconfig.exe (1) 계정과비밀번호등록 MPICH2 환경설정프로그램을처음실행하면계정과비밀번호를물어보는창이나온다. 이때이전단계 1. b 에서생성했던윈도우계정이름과, 비밀번호를입력하고 Register를클릭한다. 다시한번강조하지만지금단계에서입력하는계정이름과비밀번호를이용하여다른모든컴퓨터들에접속하기때문에모든컴퓨터들의계정과비밀번호는동일해야한다. < 윈도우계정이름과비밀번호를입력 > 계정과비밀번호를입력하고 Register를클릭한후 wmpiconfig.exe 프로그램이아래그림과같이나타나야한다. 7

10 <wmpiconfig.exe 실행화면 > 8

11 (2) MPICH2 환경설정 <wmpiconfig.exe 의화면구성 > MPICH2 환경설정프로그램은위의그림과같이크게세가지창이있는데, 각각의용도는아래와같다. (a) 작업에참여할컴퓨터들의작업그룹을설정한다. (b) (a) 에서선택한작업그룹에존재하는 Host의 list가나타나는창이다. (c) 해당호스트의 MPICH2 현재설정상태를표시하고, 사용자가수정할수있게하는창이다. 우선 1.a에서설정한작업그룹내에있는컴퓨터들간의연결상태를체크하기위하여위그림에서 a로표시된부분에서 Domain을이전에설정한작업그룹의이름으로선택하고, Get Hosts 버튼을클릭하여작업그룹내의컴퓨터목록을생성한다. 9

12 <Domain 을작업그룹으로설정하고 Get Hosts 버튼을클릭한모습 > 이시스템에서는 WORKGROUP 작업그룹내에서 PC1, PC2, PC10, PC11, PC12 총 5대의컴퓨터에 MPICH2가모두설치되어있고, 사용자계정과비밀번호가모두동일하게설정되어있는상태이다. 이 5대의컴퓨터들이올바로설정되고연결상태가정상적인지확인하기위하여 Scan Hosts 버튼을클릭한다. 10

13 <Scan Hosts 버튼을클릭한모습 > 지금까지해온방법으로미리설정을해둔 5대의컴퓨터가올바로설정되었음을컴퓨터이름에연두색으로표시하여나타내고있다. MPICH2가연결할수없는컴퓨터는회색으로나온다. 연두색으로표시된컴퓨터는현재이작업을수행하는컴퓨터에서 MPICH2를이용하여병렬처리작업에이용할수있는컴퓨터이다. 만약이때설정한컴퓨터가연두색으로표시되지않는다면앞의과정을다시꼼꼼히읽어본후다시시도해본다. 지금까지의과정으로 MPICH2 의환경설정은모두끝났다. 11

14 (3) 이문서작성에사용된시스템의구성 -총 6대의컴퓨터 PC1, PC2, PC10, PC11, PC12, jaykim_clsab( 이문서를작성할때사용한컴퓨터 ) -작업그룹이름 WORKGROUP -6대의컴퓨터의사용자계정과비밀번호계정 : mpich2 비밀번호 : 방화벽사용안함 -작업그룹내에다른컴퓨터들도있지만 MPICH2가설치되지않았고 mpich2 사용자계정이없기때문에 MPICH2의작업에참여할수없음 12

15 2. Parallel Programming Using MPICH2 이제 Parallel Programming을위한환경구축이모두끝났으니간단한예제를실행해본다. 이예제를실행하는과정에서 MPICH2를이용한프로그램을컴파일하는방법, 컴파일된실행프로그램을다수의컴퓨터에서실행하는방법등을알수있을것이다.. a. 예제프로그램, test.c test.c #include <stdio.h> #include "mpi.h" #define MAX_DATA 100 main(int argc, char **argv){ int rank; int size; char processor_name[mpi_max_processor_name]; int namelen; char buff[max_data]; int i; MPI_Status status; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &size); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Get_processor_name(processor_name, &namelen); if(rank==0){ printf("### Process %d from %s ###\n", rank, processor_name); fflush(stdout); for(i=1;i<size;i++){ MPI_Recv(buff, MAX_DATA, MPI_CHAR, i, 0, MPI_COMM_WORLD, &status); printf("%s\n", buff); fflush(stdout); else{ sprintf(buff, "### Process %d from %s ###", rank, processor_name); fflush(stdout); MPI_Send(buff, MAX_DATA, MPI_CHAR, 0, 0, MPI_COMM_WORLD); MPI_Finalize(); b. 소스컴파일위예제는 MPI 의가장기초적인예제이다. 이를컴파일하고단일컴퓨터상에서실행해보고동작을확인하고, 다수의컴퓨터에서실행해보자. MPICH2 를이용하여작성한프로그램을 Visual Studio 를이용하여컴파일하고실행할때는아래와같은절차가필요하다. (1) 프로젝트를생성한다. (2) include 파일경로에 mpich2\include 를추가한다. (3) library 파일경로에 mpich2\lib 를추가한다. (4) link 명령어에 mpi.lib 를추가한다. (5) 생성한실행파일을실행할모든컴퓨터의동일한위치에복사한다. 13

16 (6) mpiexec 명령어를이용하여프로그램을실행한다. * MPICH2 의기본설치폴더는 C:\Program Files\MPICH2 이다. Visual Studio 를이용하여프로젝트를생성하고위예제를컴파일해보자. (1) 프로젝트를생성한다. 프로젝트파일을임의의디렉토리, C:\MPICH2_Working\test 에저장한다. 14

17 (2) include, library 파일경로에 mpich2\include, mpich2\lib 를추가한다. Visual Studio 메인메뉴 -> Tools -> Options -> Directories 위그림과같이 MPICH2 의 include 파일의위치를추가한다. 15

18 Show directories for: 메뉴에서 Library files 를선택하고위그림과같이 MPICH2 의 lib 파일의위치를추가한다. (3) link 명령어에 mpi.lib 를추가한다. Visual Studio 메인메뉴 -> Project -> Settings -> Link Link 탭의 Object/library modules: 텍스트입력창의가장뒤쪽에 mpi.lib 를타이핑하여추가한다. (4) 컴파일환경설정완료이과정을마치면 MPICH2 를이용하여작성한프로그램을컴파일할수있다. 컴파일을하여실행파일을생성하자. * 생성한실행파일의위치를잘기억하도록하자. 여기서는생성한실행파일의위치를 c:\mpich2_working\test\debug 폴더로가정한다. 16

19 c. 실행 MPICH2 를이용하여작성한프로그램은실행할때별도의프로그램이필요하다. MPICH2 의기본설치폴더내에는 bin lib include examples 등의폴더가있다. 우선 MPICH2 로작성한프로그램을실행하기위해필요한프로그램은 bin 폴더내에위치한다. Console 프로그램을열고, cd c:\program files\mpich2\bin 명령어를입력하여 MPICH2 폴더로이동하고아래명령어를입력한다. [ 참고 ] 환경변수설정에서 MPICH2 의 bin 폴더를 path 에추가해두면 mpiexec 명령어를편하게사용할수있다. C:\Program Files\MPICH2\bin>mpiexec n 5 c:\mpich2_working\test\debug\test.exe < 실행결과 > MPICH2 로작성한프로그램을실행시켜주는 mpiexec 명령어를이용하여위에서작성한예제를실행하였다. 여기서사용한 n 5 파라미터는이프로그램을 5 개의프로세스로생성하라는의미이다. 즉, 이명령어가수행되면 test.exe 프로그램의프로세스가 5 개가생성되는것이다. 이렇게생성된프로세스는 smpd.exe 에의하여관리되기때문에서로통신 (Message Passing) 이가능하다. 그리고각프로세스마다고유한 ID 도할당받기때문에각각의프로세스를구분할수있다. 자세한사항은소스분석을통하여설명하도록하겠다. 17

20 d. 소스분석 test.c #include <stdio.h> #include "mpi.h" #define MAX_DATA 100 main(int argc, char **argv){ int rank; int size; char processor_name[mpi_max_processor_name]; int namelen; char buff[max_data]; int i; MPI_Status status; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &size); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Get_processor_name(processor_name, &namelen); /* 여기까지모든프로그램이동일하게수행된다. rank 는각프로세스를구별하기위해 사용된다. 주로 rank 0 은특별한용도로사용된다.*/ /* 이부분부터프로세스의 rank 에따라수행할코드가달라진다. */ // rank 가 0번인프로세스가수행할코드 if(rank==0){ printf("### Process %d from %s ###\n", rank, processor_name); fflush(stdout); for(i=1;i<size;i++){ MPI_Recv(buff, MAX_DATA, MPI_CHAR, i, 0, MPI_COMM_WORLD, &status); printf("%s\n", buff); fflush(stdout); //rank가 0이아닌프로세스가수행할코드, 이경우에는 rank 가 1~4 인경우 else{ sprintf(buff, "### Process %d from %s ###", rank, processor_name); fflush(stdout); MPI_Send(buff, MAX_DATA, MPI_CHAR, 0, 0, MPI_COMM_WORLD); MPI_Finalize(); 위소스중주요 MPICH2 Function 과기능은아래와같다. MPI_Init(); MPI_Comm_size(); MPI_Comm_rank(); MPI_Recv(); MPI_Send(); MPI_Finalize(); 이예제와같은프로그래밍 Model 을 SMPD(Single Program Multiple Data) 이라한다. 즉, 같은소스코드의프로그램을이용하여여러개의프로세스를생성하는것이다. 동일한소스코드로다수의프로세스가생성되기때문에각각의프로세스를구분할수있어야각프로세스별로작업을달리할당하거나하는일을할수있을것이다. 18

21 가장먼저, MPI_Comm_rank 함수는 mpiexec 프로그램을이용해생성된다수의프로세스를식별할수있는고유번호를할당해준다. 즉, mpiexec n 5 test.exe 명령어를이용하여 5 개의프로세스를생성한다면 0~4 의 rank 가진프로세스가생성되는것이다. MPI_Comm_size 함수는 mpiexec 명령어를이용해몇개의프로세스가생성되었는지를알려준다. mpiexec n 5 test.exe 로실행한경우에는 size 의값이 5 가된다. MPI_Send 함수는목적지프로세스의고유번호 (rank) 와전송할데이터에관한정보들을파라미터로받아해당목적지프로세스에게메시지를전달하는함수이다. 즉, 이함수를통하여같은영역 (MPI_COMM_WORLD) 내에있는다른프로세스에게메시지를전달하는것이다. MPI_Recv 함수는메시지를보내는프로세스의정보와수신된메시지를저장할변수를파라미터로입력받고, 메시지를보내는프로세스가 Send 함수를이용하여메시지를전송하면전송받은데이터를지정한변수 ( 버퍼 ) 에저장한다. MPI_Init 함수는 MPI 를이용하기전에항상호출해야하는함수이다. MPI_Finalizer 함수는 MPI 를이용한프로그램이종료되기전에항상호출해야한다. 위와같은 MPI 함수를이용하여이예제프로그램은, rank 가 0 인프로세스 ( 프로세스 0) 는 4 개의프로세스로부터메시지가전송되기를기다리고, 프로세스 1 ~ 프로세스 4 는프로세스 0 에게메시지를전송한다. 프로세스 0 이프로세스로부터메세지를받은후수신한메세지내용을출력하는동작을하고있다. 여기서중요한사실은각각의프로세스들이동일한소스프로그램을이용하여생성된다는점과 (SMPD Model), 각프로세스는하나의컴퓨터내의메모리에모두생성될수도있고, 여러대의독립적인컴퓨터의메모리에서각각생성될수도있다. 각각의프로세스가하나의컴퓨터내의메모리에생성하는경우는방금해보았고, 이번에는 5 개의프로세스를각각 5 대의별도의컴퓨터의메모리에생성해보겠다. 이렇게생성한프로세스들역시 Send, Recv 함수를이용하여서로통신할수있다. 이런경우에는 MPICH2 의환경설정프로그램을이용하여설정을변경해줘야한다. 19

22 e. 여러대의컴퓨터에프로세스를생성하기위한환경설정 Wmpiconfig.exe 을실행한다. 위와같은화면이나오면가운데에위치한창의메뉴중 hosts 의정보를변경해줘야한다. 이메뉴를이용하여 MPICH2 를이용하여프로세스를생성할때참여할컴퓨터들을정할수있다. 미리설정해둔 5 대의컴퓨터이름을아래와같이추가기입하고 Apply 버튼을클릭하여설정을저장한다.. (ex, PC1 PC2 PC10 PC11 PC12) 20

23 이제다수의프로세스를다수의컴퓨터에서생성할수있게된다. console 에서아래명령어를입력하고실행해보자. 5 개의프로세스들이각각다른컴퓨터에서생성되고서로통신하는모습을볼수있다. 이러한 Message Passing 을이용하여병렬처리를수행할수있다. 21

24 3. 병렬처리예제프로그램 첨부한예제프로그램은특정값 (ex. 1000) 으로초기화되어있는 12X12 행렬의값을특정값 (ex. 1) 으로감산하여 0 이하가될때까지계산하는프로그램이다. 12 개의행을다수의프로세스가병렬로계산한후이결과값을 Master 프로세스 (rank 가 0 인 ) 에게돌려주고 Master 프로세스는이값을자신의행렬에반영하는방식으로동작한다. 아래그림은 12X12 행렬이 1000 으로초기화되어있고, 각행렬의값이 1 씩감소하는과정을나타낸예이다. 3 개의프로세스 ( 컴퓨터 ) 가작업에참여하고프로세스당 4개의행을계산한다. 1 cycle 에서는모든행렬의값이 1000( 초기값 ) 이고, 다음 cycle 에서각프로세스가 1을감소한값을 master process(process 1) 로전달한다. 효율적인메모리사용을위해, Master process 는 12X12 행렬의모든값을가지고있고, process2, process3 은자신의계산영역의행렬만가지고있는다. 그리고자신의계산영역의행렬원소들을계산하고그결과를 process1 에게전송하고, process1 은전달받은값을자신이가지고있는행렬에반영한다. 즉, 2 cycle 이되면 process1~process3 이가지고있는행렬의값은모두 999 가된다. 행렬의값에 1을빼는계산은프로세스 2~3 에서수행되고, 그계산의결과값이 process1 으로전달된다. 이런계산을반복하여 process1 에있는행렬의모든값이 0이하가될때까지반복한다. [ 참고 ] 각각의프로세스가행렬의값에 -1 을하는계산은너무간단한계산이기때문에병렬처리의효과를얻을수없다. 실제소스에서는보다복잡한실수연산인, 을 번빼는등의연산을하여각프로세스에게보다복잡한연산을수행하도록하였다. [ 실험결과, 소스프로그램첨부 ] 22

25 4. 참고자료 Web Sites Books Parallel Programming with MPI, Peter S. Pacheco 23

26 MPI_Example.c #include <stdio.h> #include "mpi.h" //parameter #define ROW_MAX 12 #define COL_MAX 12 #define MAX_DATA 100 int control_array(int type, double value, int row, int col); // 기본자료구조 double array[row_max][col_max]; double t_array[row_max][col_max]; //parameter double init_value = ; double subtracter = 1; int cycle_counter=0; main(int argc, char **argv){ //mpich2 int rank; int size; char processor_name[mpi_max_processor_name]; int namelen; double starttime=0.0, endtime; MPI_Status status; //mpich2 buffer int buf[max_data]; char char_buf[max_data]; // 작업분할 int divider=0; int index_i=0, index_j=0; int index_buf[max_data]; //array int local_row_start, local_row_end; int iszero=1, iszero_gather; //control int i, j, k,l; int print=1; int done=0; //mpich2 MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &size); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Get_processor_name(processor_name, &namelen); // 계산에참여하는프로세스수는 ROW_MAX 를정확히나눌수있는수이어야한다. if(row_max % size!=0){ printf("error!\n"); fflush(stdout); MPI_Finalize(); return -1; //divider 에프로세스당처리할 row 의수 divider=row_max/size; if(rank==0){ //parameter broadcasting printf("initial Value : "); fflush(stdout); scanf("%lf", &init_value); printf("subtracter : "); fflush(stdout); scanf("%lf", &subtracter); printf("print results[yes=1,no=0]? "); fflush(stdout); scanf("%d", &print); //start clock starttime=mpi_wtime(); //broadcasting MPI_Bcast(&init_value, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); MPI_Bcast(&subtracter, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); //(1) 작업분할, 각프로세스가처리할 index 의범위를할당 for(i=0;i<size*2;i+=2){ index_buf[i]=i/2*divider; Page 1 of 3

27 MPI_Example.c if(i/2 == size-1) // 마지막프로세스는나머지 Index 를다처리 index_buf[i+1]=row_max-1; else index_buf[i+1]=(i/2*divider)+(divider-1); printf("### rank[%d]-[%s] - Received Index Range = [%d] ~ [%d]\n", rank, processor_name, index_buf[0], index_buf[1]); //index할당 for(i=1;i<size;i++){ buf[0]=index_buf[i*2]; buf[1]=index_buf[i*2+1]; MPI_Send(buf, 2, MPI_INT, i, 0, MPI_COMM_WORLD); // 각프로세스에할당한 Index Range 를확인( 디버깅) for(i=1;i<size;i++){ MPI_Recv(char_buf, MAX_DATA,MPI_CHAR, i, MPI_ANY_TAG, MPI_COMM_WORLD, &status); printf("%s\n",char_buf); fflush(stdout); // 배열초기화 control_array(1, init_value, ROW_MAX, COL_MAX); //print if(print) control_array(0, 0, ROW_MAX, COL_MAX); //(2) 작업시작 local_row_start=index_buf[0]; local_row_end=index_buf[1]; // 할당받은 index 범위내의행렬값들을계산한다. while(1){ iszero=1; cycle_counter++; for(i=local_row_start;i<=local_row_end;i++){ for(j=0;j<col_max;j++){ for(k=0;k<100;k++) for(l=0;l<100;l++){ t_array[i][j] = t_array[i][j]-subtracter; if(t_array[i][j]> 0) iszero=0;// 계산값중 0 이하가아닌것이하나라도있으면 0 으로셋 // 각프로세스가계산한값을 array 에모두저장, MPI_Gather MPI_Gather(t_array, ROW_MAX/size*COL_MAX, MPI_DOUBLE, array, ROW_MAX/size*COL_MAX, MPI_DOUBLE, 0, MPI_COMM_WORLD); // 각프로세스의 iszero 값더하여종료조건계산 MPI_Reduce( &iszero, &iszero_gather, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); if(print) control_array(0, 0, ROW_MAX, COL_MAX); if(iszero_gather==size) break; printf("### rank[%d]-[%s] - Finished!!!\n", rank, processor_name); fflush(stdout); endtime=mpi_wtime(); for(i=1;i<size;i++){ MPI_Recv(char_buf, MAX_DATA,MPI_CHAR, i, MPI_ANY_TAG, MPI_COMM_WORLD, &status); printf("%s\n", char_buf); printf("\n### Time = %f\n", endtime-starttime); fflush(stdout); else{ MPI_Bcast(&init_value, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); MPI_Bcast(&subtracter, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD); // 배열초기화 control_array(1, init_value, ROW_MAX, COL_MAX); // 할당받은 Index Range 를서버에게전달( 디버깅) MPI_Recv(buf, 2,MPI_INT, 0, MPI_ANY_TAG, MPI_COMM_WORLD, &status); sprintf(char_buf, "### rank[%d]-[%s] - Received Index Range = [%d] ~ [%d]", rank,processor_name, buf[0], buf[1]); MPI_Send(char_buf, MAX_DATA, MPI_CHAR, 0, 0, MPI_COMM_WORLD); local_row_start = buf[0]; Page 2 of 3

28 MPI_Example.c local_row_end = buf[1]; while(done!=1){ // 할당받은 index 범위내의행렬값들을계산한다. iszero=1; for(i=0;i<row_max/size;i++){ for(j=0;j<col_max;j++){ for(k=0;k<100;k++) for(l=0;l<100;l++){ array[i][j] = array[i][j]-subtracter; if(array[i][j] > 0) iszero=0;// 계산값중 0 이하가아닌것이하나라도있으면 0 으로셋 MPI_Gather(array, ROW_MAX/size*COL_MAX, MPI_DOUBLE, array, ROW_MAX/size*COL_MAX, MPI_DOUBLE, 0, MPI_COMM_WORLD); MPI_Reduce( &iszero, &iszero_gather, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); done=iszero; sprintf(char_buf, "### rank[%d]-[%s] - Finished!!! ", rank, processor_name); MPI_Send(char_buf, MAX_DATA, MPI_CHAR, 0, 0, MPI_COMM_WORLD); MPI_Finalize(); return 1; int control_array(int type, double value, int row, int col){ //type==0 : print //type==1 : initialize with the value of the parameter, value int i,j; if(type==0) printf("### %d Cycle\n", cycle_counter); for(i=0;i<row;i++){ for(j=0;j<col;j++){ if(type==0) { printf("%.2lf ", array[i][j]); fflush(stdout); else if(type==1) { array[i][j]=value; t_array[i][j]=value; else return -1; if(type==0) { printf("\n"); fflush(stdout); if(type==0) { printf("\n"); fflush(stdout); return 1; Page 3 of 3

29 프로세스수에의한계산시간의변화 계산에걸린시간 ( 초단위 ) 프로세스의수 subtracter

30 X축 : 계산에사용한감수 ( 이수를이용하여행렬의초기값에서 0이될때까지뺀다 ) Y축 : 계산에참여한프로세스 ( 컴퓨터 ) 의수, ( 프로세스수가 6이상일경우는 1대의컴퓨터에 2개이상의프로세스를생성하여처리함 )