본문 바로가기
Backend MLOps/On-premise setting

[MPI] 멀티노드로 병렬연산, 분산컴퓨팅 처리하기

by SteadyForDeep 2023. 9. 3.
반응형

멀티노드로 병렬연산 처리를 해보자.

 

우선은 MPI를 위한 라이브러리들을 설치해야한다.

MPI는 Message Passing Interface의 약자인데

프로세스와 프로세스간에 데이터 전송의 프로토콜을 말한다.

 

가장 대표적인 라이브러리로는 OpenMPI와 MPICH가 있는데

가벼운 목적으로는 MPICH가 더 적합하다고 한다.

 

1. MPICH 설치 

# MPICH 설치
sudo apt-get update
sudo apt-get install -y mpich libmpich-dev


# 설치 확인
mpicc --version
mpiexec --version

 

간단하다.

 

2. 싱글노드에서 병렬 연산 구현하기

 

싱글노드에서 병렬연산을 구현하는 방법은 다음과 같다.

우선은 hello world 코드를 작성한다.

#include <stdio.h>
#include <mpi.h>

int main(int argc, char** argv) {
    int rank, size;

    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);

    printf("Hello world from process %d of %d\n", rank, size);

    MPI_Finalize();
    return 0;
}

C 로 작성된 코드이고 

rank는 현재 프로세스가 몇번째 프로세스인지 나타낸다.

size는 전체 프로세스가 몇개인지 나타낸다.

MPI_COMM_WORLD는 mpi.h 에 포함되어 있는 전체 프로세스 통신자에 해당한다.

 

# 컴파일
mpicc hello_mpi.c -o hello_mpi

# 실행
mpirun -np 4 ./hello_mpi

위와 같이 컴파일하고 실행하는 것이 가능하다.

 

마스터 노드에서 40개의 프로세스를 실행하였고 아래와 같은 응답을 얻었다.

그라파나를 통해서도 하나의 노드만 실행된 것을 볼 수 있다.

출력의 순서를 보면 병렬적으로 진행된 것이 맞고 4개의 코어를 모두 사용했음을 알 수 있다.

 

3. 분산 병렬연산 구현하기

 

이번에는 분산 병렬연산을 구현해 본다.

192.168.0.11:4
192.168.0.12:4
192.168.0.13:4
192.168.0.14:4

 

위와같이 호스트와 관련된 내용이 적힌 텍스트 파일을 만들고 저장해 준다.

각 행은 <연산을 할당할 노드의 ip>:<해당 노드에서 사용할 프로세서의 수> 로 정의된다. 

마스터노드 또한 함께 적어주었다.

이제 이 호스트파일의 위치와 함께 돌려주면 된다.

 

여기서 주의할 점은 모든 노드에 동일한 실행파일이 있어야 한다는 것이다.

나는 미리 구축해둔 nfs를 통해서 모든 노드에 동일한 실행파일을 뿌려주었다.

 

사전 준비를 해 보자.

우선 mpi는 ssh를 통해 서로 소통하기 때문에

ssh로 통신하는데있어 비밀번호가 적용되면 안된다.

그래서 서로 공유키를 주고 받은 상태로 만들어 줘야 한다.

ssh-keygen

ssh-copy-id pi@192.168.0.12
ssh-copy-id pi@192.168.0.13
ssh-copy-id pi@192.168.0.14

ssh pi@192.168.0.12 -t "ssh-keygen && ssh-copy-id pi@192.168.0.11"
ssh pi@192.168.0.13 -t "ssh-keygen && ssh-copy-id pi@192.168.0.11"
ssh pi@192.168.0.14 -t "ssh-keygen && ssh-copy-id pi@192.168.0.11"

 

이런식으로 서로 키를 주고 받게 할 수 있다.

노드가 너무너무 많으면 pssh 과 같은 툴을 사용할 수도 있다.

 

commands="
    if [[ \$(pwd) == \$(echo \$HOME) ]];
    then
            echo \"True\";
            mkdir -p ./multi-node-MPI/clang/hello-world/;
    else
            echo \"False\";
    fi;

    sudo mount 192.168.0.10:/home/manager/nfs/shared/mpi/clang ./multi-node-MPI/clang
"


eval $commands
ssh pi@192.168.0.12 -t $commands
ssh pi@192.168.0.13 -t $commands
ssh pi@192.168.0.14 -t $commands

위의 쉘스크립트는 굉장히 중요한데 마스터노드와 워커노드들에 동일한 위치를 생성하고 

그 위치를 모두 같은 nfs에 마운트하는 작업을 스크립트화한 것이다.

이렇게 모든 실행파일이 노드에 상관없이 동일한 절대주소를 가지고 있어야 한다.

 

그리고 아래와 같이

실행해 주면 호스트파일에 등록된 호스트들에 프로세스를 만들면서 동일한 동작을 병렬적으로 처리한다.

 

그라파나로 확인한 cpu 사용량을 보면 모든 CPU 프로세서가 한번에 실행된 것을 볼 수 있다.

 

반응형

댓글