웹사이트 검색

Python의 분산 병렬 프로그래밍 : MPI4PY


이 페이지에서

  1. 1 소개
  2. 2 메시지 보내기 및 받기
    1. 2.1 send() 소개
    2. 2.2 recv() 소개
    3. 2.3 간단한 send() 및 recv() 예제\n
    4. 2.4 참고 사항\n
    5. 2.5 동적으로 보내고 받기
    6. 2.6 동적 데이터 송수신 예시

    1. 3.1 예

    1. 4.1 예

    1. 5.1 예

    1. 6.1 예

    1. 소개

    MPI는 메시지 전달 인터페이스를 나타냅니다. MPICH" 또는 OpenMPI와 같은 MPI 구현은 분산 메모리가 있는 Linux 클러스터와 같은 분산 시스템에서 병렬 프로그램을 작성하기 위한 플랫폼을 만드는 데 사용됩니다. 일반적으로 구축된 플랫폼은 MPI 표준을 사용하여 C로 프로그래밍할 수 있습니다. 따라서 순서대로 이 환경에서 Python으로 병렬 프로그램을 실행하려면 "Python용 MPI"를 의미하는 MPI4py라는 모듈을 사용해야 합니다. 이 모듈은 프로세서 순위 가져오기, 메시지 송수신과 같은 작업을 수행하는 표준 기능을 제공합니다. /클러스터에 있는 다양한 노드의 데이터 노드 사이에 전달되는 메시지와 함께 프로그램을 병렬로 실행할 수 있습니다.시스템에 MPIch2 및 MPI4py가 설치되어 있는 것이 중요합니다.따라서 MPI4Py를 설치하지 않은 경우 다음 2가지 가이드를 참조하십시오. MPI4PY에서 샘플 프로그램을 설치, 빌드 및 테스트하는 방법은 을 참조하십시오.

    https://seethesource.wordpress.com/2015/01/05/raspberypi-hacks-part1/
    https://seethesource.wordpress.com/2015/01/14/raspberypi-hacks-part2/
    

    MPI4PY가 설치되면 프로그래밍을 시작할 수 있습니다. 이 튜토리얼은 송수신 메시지, 분산수집 데이터, 브로드캐스팅과 같은 MPI4PY에서 제공하는 다양한 중요한 기능을 다룹니다. 예제를 제공하여 메시지 및 사용 방법. 이러한 정보를 사용하여 Python에서 확장 가능하고 효율적인 분산 병렬 프로그램을 구축할 수 있습니다. 그럼 시작하겠습니다.

    2 메시지 송수신

    mpi4py의 통신은 send() 및 he recv() 메서드를 사용하여 수행됩니다. 이름에서 알 수 있듯이 각각 노드에서 메시지를 보내고 받는 데 사용됩니다.

    2.1 send() 소개

    이 함수의 일반 구문은 다음과 같습니다. comm.send(data,dest)

    여기서 "data"는 다른 노드로 보내야 하는 모든 데이터/메시지가 될 수 있으며 "dest"는 그것을 보낼 노드(들)의 프로세스 순위를 나타냅니다.

    예: comm.send((rank+1)*5,dest=1).
    이는 "(rank+1)*5" 메시지를 프로세스 rank=1인 노드로 보냅니다. 따라서 해당 노드만 수신할 수 있습니다.

    2.2 recv() 소개

    이 함수의 일반 구문은 다음과 같습니다. comm.recv(source)

    이것은 "source" 매개변수에 언급된 순위를 가진 프로세스에서만 데이터/메시지를 수신하도록 특정 프로세스에 지시합니다.

    예: comm.recv(source=1)
    rank=1인 프로세스에서만 메시지를 받습니다.

    2.3 간단한 send() 및 recv()의 예

    if rank==0 :
    	    data= (rank+1)*5
    	    comm.send(data,dest=1)
    if rank==1:
    	    data=comm.recv(source-0)
    	    print data
    

    2.4 참고 사항

    • 노드가 recv() 메서드를 실행할 때 예상 소스에서 일부 데이터를 받을 때까지 기다립니다. 일부 데이터를 수신하면 프로그램의 나머지 부분을 계속 진행합니다.\n
    • 여기서 send()의 "dest" 매개변수와 recv()의 "source" 매개변수는 상수 값(또는 순위)만 가질 필요가 없으며 표현식일 수 있습니다.\n
    • "comm" 개체의 "size" 멤버는 send() 및 receive() 메서드를 조건화하는 좋은 방법이며 이로 인해 메시지를 동적으로 보내고 받을 수 있습니다.\n

    2.5 동적으로 보내고 받기

    데이터의 동적 전송은 한 번에 여러 노드에서 데이터를 주고 받을 수 있고 특정 상황에 따라 전송 여부를 결정할 수 있으므로 유연성이 크게 향상되므로 훨씬 유용합니다.

    2.6 동적 데이터 송수신 예시

    comm.send(data_shared,dest=(rank*2)%size)
    comm.recv(source=(rank-3)%size)
    

    위의 두 문은 동적으로 발생하는 rank 및 size 로 대체된 값에 따라 전송할 데이터와 누구에게 전송해야 하는지에 따라 달라지므로 값을 하드 코딩할 필요가 없습니다. 그러나 recv() 메서드는 많은 메시지를 받을 자격이 있음에도 불구하고 하나의 메시지만 수신하므로 수신한 첫 번째 메시지만 서비스하고 프로그램의 다음 문으로 계속 진행합니다.

    3 태그된 send() 및 recv() 함수

    send() 및 recv()에 태그를 지정하면 메시지 수신 순서를 보장할 수 있으므로 한 메시지가 다른 메시지보다 먼저 전달되는지 확인할 수 있습니다.

    데이터를 동적으로 전송하는 동안 일종의 동기화를 달성하기 위해 특정 recv()와 일치시키기 위해 특정 send()가 필요한 상황이 발생합니다. 이것은 send()와 recv() 모두에서 "tag" 매개변수를 사용하여 수행할 수 있습니다.

    예를 들어 send()는 다음과 같습니다. comm.send(shared_data,dest=2,tag=1) 위의 명령문과 일치하는 recv()는 다음과 같습니다. recv(소스=1,태그=1)

    따라서 이 구조는 데이터 전송의 동기화로 이어지는 일치를 강제합니다. 태깅의 장점은 recv()가 예상 태그가 있는 해당 send()에서 데이터를 수신할 때까지 대기하도록 만들 수 있다는 것입니다. 하지만 교착 상태로 이어질 수 있으므로 매우 주의해서 사용해야 합니다.

    3.1 예

      If rank==0:
    	shared_data1 = 23
    	comm.send(shared_data1,dest=3,tag=1)
    	shared_data2 = 34
    	comm.send(shared_data2,dest=3,tag=2)
      if rank==3:
    	recv_data1 = comm.recv(source=0,tag=2)
    	print  recv_data1
    	recv_data2 = comm.recv(source=0,tag=1)
    	print  recv_data2
    

    결과는 다음과 같습니다.

    34
    23
    

    따라서 Shared_data1이 먼저 전송되었지만 첫 번째 recv()가 tag=2로 send()를 기다렸다가 데이터를 수신하고 인쇄한 후 다음 recv() 메서드로 전달했음을 알 수 있습니다.

    4 방송

    브로드캐스트를 통해 사용자는 병렬 프로그래밍에 동적 속성을 추가할 수 있습니다. 여기서 마스터에서 생성된 일부 데이터는 모든 노드에 브로드캐스트될 수 있습니다. 이렇게 하면 모든 노드에 데이터를 보내는 반복적인 절차를 피할 수 있습니다. 마스터/루트 노드에서 이 노드에서 데이터를 생성하고 다른 모든 노드로 보냅니다.

    4.1 예

       if rank == 0
           data = {'a':1,'b':2,'c':3}
       else
           data = None
       data = comm.bcast(data,root=0)
       print  "rank", rank, data
    

    위의 프로그램에서 bcast() 메서드에서 첫 번째 매개변수 "data"는 브로드캐스트해야 하는 대상을 나타내고 두 번째 매개변수 "root=0"은 데이터를 가져오는 위치를 나타냅니다. 이것을 실행하면 5개의 프로세스를 사용하는 프로그램의 경우 출력은 다음과 유사해야 합니다.

    rank 0 {'a':1,'b':2,'c':3}
    rank 4 {'a':1,'b':2,'c':3}
    rank 3 {'a':1,'b':2,'c':3}
    rank 1 {'a':1,'b':2,'c':3}
    rank 2 {'a':1,'b':2,'c':3}
    

    5 산란

    분산은 데이터를 분해하고 각 부분을 다른 노드로 보내거나 배포하는 프로세스입니다. 예를 들어 목록을 분해하고 각 목록 요소를 다른 노드로 보내는 것입니다.

    5.1 예

       comm = MPI.COMM_WORLD
       size=comm.get_size()
       rank-comm.get_rank()
       if rank == 0: 
           data = [(x+1) ** x for x in range (size)]
           print 'scattering data',data
       else:
           data = None
       data = comm.scatter(data,root=0)
       print 'rank',rank,'has data: ', data
    

    이 프로그램의 출력은 다음과 같습니다.

    scattering data : [1,2,9,64,625]
    
    rank 0 has data : 1
    rank 1 has data : 2
    rank 2 has data : 9
    rank 3 has data : 64
    rank 4 has data : 625
    

    여기서 데이터의 크기는 예상할 수 있는 데이터의 수와 같아야 합니다. 즉, 데이터에 10개의 요소가 있고 프로세스가 5개만 있으면 오류가 발생합니다.

    6 모으다

    수집은 분산의 반대입니다. 다양한 노드에서 데이터를 수집하여 하나로 저장하는 데 사용됩니다. 예를 들어 다양한 노드에서 요소를 수집하고 그 중 하나의 목록을 만드는 것입니다.

    6.1 예

    예: (산포에 대한 이전 예와 동일하지만 몇 가지 추가 사항이 있음에 유의하십시오.)

     comm = MPI.COMM_WORLD
       size=comm.get_size()
       rank-comm.get_rank()
       if rank == 0: 
           data = [(x+1) ** x for x in range (size)]
           print 'scattering data',data
       else:
           data = None
       data = comm.scatter(data,root=0)
       print 'rank',rank,'has data: ', data
         
       new_data = comm.gather(data, root=0)
       if rank == 0:
           print  'master collected: ', new_data
       
    

    이 프로그램의 출력은 다음과 같습니다.

    rank 0 has data : 1
    rank 1 has data : 2
    rank 2 has data : 9
    rank 3 has data : 64
    rank 4 has data : 625 
    master collected:  [ 1, 2, 3, 9,64, 625]  
    

    위의 출력에서 마지막 줄은 수집 때문입니다. 할 수 있는 또 다른 일은 데이터가 흩어지자마자, 즉 각 노드가 흩어진 데이터의 일부를 수신했을 때 데이터를 변경하는 것입니다. 예: data= data+1
    따라서 수집이 발생하면 데이터는 전송된 데이터와 동일하지 않지만 변경된 패턴을 유지하므로 올바르게 작동함을 증명합니다.

    7 결론

    이 게시물에서는 파이썬 프로그래밍 언어를 사용하여 분산 환경을 위한 병렬 프로그램을 작성하는 데 도움이 되는 mpi4py의 다양한 프로그래밍 구조를 소개하고 사용했습니다. 이들은 대부분의 프로그램에서 위에 표시된 개별 구성이지만 모두 또는 대부분이 함께 사용됩니다. mpi4py를 사용하여 빌드할 수 있는 일부 응용 프로그램을 공유하고 싶습니다.

    • 자동 텍스트 요약 - 여러 텍스트 문서를 한 번에 요약하기 위해 분산 프로그램을 작성할 수 있는 자연어 처리의 한 분야입니다.\n
    • 정렬 및 검색 - 정렬 또는 검색할 데이터를 분할하여 대량의 데이터를 짧은 시간에 처리할 수 있도록 분산 환경을 활용할 수 있습니다.\n
    • 수학적 문제 해결 - 독성 분포와 같은 문제는 병렬 환경에서 훨씬 빠르게 해결할 수 있습니다.\n

    따라서 모든 종류의 분야에 대한 병렬 프로그램을 작성하고 Python이 제공하는 이점을 사용할 수 있습니다.