2014-10-14 2 views
0

과정 작업을 실현하는 동안 PDE 연속체 역학을 해결하기 위해 MPI 프로그램을 작성해야합니다. 다음MPI 집단 출력 특수한 형태의 인접하지 않은 3D 배열

병렬 프로그램의
do i=1,XX 
    do j=1,YY 
     do k=1,ZZ 
      write(ifile) R(i,j,k) 
      write(ifile) U(i,j,k) 
      write(ifile) V(i,j,k) 
      write(ifile) W(i,j,k) 
      write(ifile) P(i,j,k) 
     end do 
    end do 
end do 

, I는 동일한 물품 : /병렬은 축 X/

따라 일어나는 다음 시퀀스 프로그램 파일 (FORTRAN)

는 기입

call MPI_TYPE_CREATE_SUBARRAY(4, [INT(5), INT(ZZ),INT(YY), INT(XX)], [5,ZZ,YY,PDB(iam).Xelements], [0, 0, 0, PDB(iam).Xoffset], MPI_ORDER_FORTRAN, MPI_FLOAT, slice, ierr) 
call MPI_TYPE_COMMIT(slice, ierr) 

call MPI_FILE_OPEN(MPI_COMM_WORLD, cFileName, IOR(MPI_MODE_CREATE, MPI_MODE_WRONLY), MPI_INFO_NULL, ifile, ierr) 

do i = 1,PDB(iam).Xelements 
    do j = 1,YY 
     do k = 1,ZZ 
      dataTmp(1,k,j,i) = R(i,j,k) 
      dataTmp(2,k,j,i) = U(i,j,k) 
      dataTmp(3,k,j,i) = V(i,j,k) 
      dataTmp(4,k,j,i) = W(i,j,k) 
      dataTmp(5,k,j,i) = P(i,j,k) 
     end do 
    end do 
end do 

call MPI_FILE_SET_VIEW(ifile, offset, MPI_FLOAT, slice, 'native', MPI_INFO_NULL, ierr) 
call MPI_FILE_WRITE_ALL(ifile, dataTmp, 5*PDB(iam).Xelements*YY*ZZ, MPI_FLOAT, wstatus, ierr) 
call MPI_BARRIER(MPI_COMM_WORLD, ierr) 

잘 작동합니다. 하지만 배열 dataTmp 사용에 대해 잘 모르겠습니다. 어떤 솔루션이 더 빠르고 정확합니까? 전체 프로그램에서 dataTmp와 같은 4D 배열을 사용하는 것은 어떻습니까? 아니면 다른 displacemet을 사용하여 5 개의 특수 mpi_type을 만들어야합니다.

답변

0

I/O 속도가 문제가되어 옵션을 사용할 수있는 경우 파일 형식을 변경하거나 메모리에 데이터를 배치하는 방법을 변경하는 것이 좋습니다. 직렬 코드 이 전치와 인터리브 방식으로 데이터를 기록 매우 느리게 될 것입니다 :

program testoutput 
implicit none 

integer, parameter :: XX=512, YY=512, ZZ=512 
real, dimension(:,:,:), allocatable :: R, U, V, W, P 
integer :: timer 
integer :: ifile 
real :: elapsed 
integer :: i,j,k 

allocate(R(XX,YY,ZZ), P(XX,YY,ZZ)) 
allocate(U(XX,YY,ZZ), V(XX,YY,ZZ), W(XX,YY,ZZ)) 

R = 1.; U = 2.; V = 3.; W = 4.; P = 5. 

open(newunit=ifile, file='interleaved.dat', form='unformatted', status='new') 
call tick(timer) 
do i=1,XX 
    do j=1,YY 
     do k=1,ZZ 
      write(ifile) R(i,j,k) 
      write(ifile) U(i,j,k) 
      write(ifile) V(i,j,k) 
      write(ifile) W(i,j,k) 
      write(ifile) P(i,j,k) 
     end do 
    end do 
end do 
elapsed=tock(timer) 
close(ifile) 

print *,'Elapsed time for interleaved: ', elapsed 

open(newunit=ifile, file='noninterleaved.dat', form='unformatted',status='new') 
call tick(timer) 
write(ifile) R 
write(ifile) U 
write(ifile) V 
write(ifile) W 
write(ifile) P 
elapsed=tock(timer) 
close(ifile) 

print *,'Elapsed time for noninterleaved: ', elapsed 

deallocate(R,U,V,W,P) 
contains 

subroutine tick(t) 
    integer, intent(OUT) :: t 

    call system_clock(t) 
end subroutine tick 

! returns time in seconds from now to time described by t 
real function tock(t) 
    integer, intent(in) :: t 
    integer :: now, clock_rate 

    call system_clock(now,clock_rate) 

    tock = real(now - t)/real(clock_rate) 
end function tock 

end program testoutput 

실행이 물건에 대한 몇 가지 더 알고 롭 레이 텀로서

$ gfortran -Wall io-serial.f90 -o io-serial 
$ ./io-serial 
Elapsed time for interleaved: 225.755005  
Elapsed time for noninterleaved: 4.01700020 

을 제공합니다,라고 당신의 병렬 버전의 변환은 괜찮습니다. 인터리빙과 트랜스 포 메모리에서 명시 적으로 노래를 부르면 훨씬 빠른 속도로 재생되고 디스크로 불어납니다. IO가 얻는만큼 빠릅니다.

MPT_File_write_all 루틴을 통해 디스크로 나가는 동안 사용자가 조판/인터리빙을 수행 할 하나 또는 다섯 개의 개별 데이터 유형을 작성하여 dataTmp 배열을 확실히 피할 수 있습니다. 그러면 메모리 사용과 성능면에서 균형이 잡히게됩니다. 빅 3-D 배열을 명시 적으로 정의하지는 않지만, MPI-IO 코드는 공정한 비트 버퍼링을 수행함으로써 개별 요소에 대한 루핑보다 성능을 향상시킵니다. 즉, 특정 양의 메모리가 효율적으로 쓰기. 좋은 소식은 Info 변수에 MPI-IO 힌트를 설정하여 균형을 조정할 수 있다는 것입니다. 나쁜 소식은 코드가 지금 가지고있는 것보다 덜 분명 할 것입니다.

+0

대답 해 주셔서 감사합니다. 하지만 불행히도 파일 형식을 변경할 수 없습니다. 나는이 형식이 불편하다는 것을 분명히 이해하고 있지만 나는 할 수 없다. 저는 MPI에서 newbee입니다. 당신이 묘사 한 것에 대한 간단한 예를 보여줄 수 있습니까? (개별 데이터 타입 등) – Vasiliy

+0

제 대답을 올렸을 때, @ Jonathan Dursi가 아직 답을 제공하지 않은 이유가 궁금합니다. 분명히 그는 StackOverflow의 King이라는 타이틀을 유지하기 위해 약간의 노력을 기울이고있었습니다. –

+0

@Vasiliy, 아마도 사전 처리 및 사후 처리를 고려하여 파일을 원하는 형식으로 가져와 성능을 향상시킬 수 있습니까? 물론 변환 단계는 신속하게 이루어질 수 있지만, 충분히 큰 데이터 세트의 경우 연속되는 사전 또는 사후 변환이 불가능한 지점이 있습니다. –

1

메모리 공간이 있으면 dataTmp를 사용하는 것이 좋습니다. MPI_FILE_WRITE_ALL 호출은이 코드에서 가장 비싼 부분입니다.

어려운 부분은 MPI-IO 파일보기로 설정 한 것입니다. dataTmp를 없애고 싶다면 배열을 기술 할 MPI 데이터 유형을 만들 수 있습니다 (아마도 MPI_Type_hindexed와 MPI_Get_address를 사용합니다). 그런 다음 MPI_BOTTOM을 메모리 버퍼로 사용하십시오.

+0

감사합니다. 내가이 배열을 사용하는 방식보다 dataTmp가 빠르거나 빠르다는 것입니다. 속도가 느리면 나에게 맞지 않습니다. big-endian 시스템에서 리틀 엔디안 파일의 MPI-IO에 대한 다른 질문을 찾아보십시오. – Vasiliy