2011-12-21 2 views
0

У меня есть гибридный код mpi-openmp, который выходит из строя с ошибкой сегментации, плохой ошибкой завершения. Я компилирую с помощью mpif90/ifort и использую mpich2. Вот строка компиляции, которые я использую и получаю ошибки:Ошибка сегментации mort-openmp ifort

mpif90.mpich2 -f90=ifort -DAMD64_LNX -openmp -o jack_openmp.exe laplace.f 

При использовании этой команды, если я бегу от одного узла, указывающий на файл машин, который включает другой узел, я получаю ошибки сегментации:

===================================================================================== 
= BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES 
= EXIT CODE: 11 
= CLEANING UP REMAINING PROCESSES 
= YOU CAN IGNORE THE BELOW CLEANUP MESSAGES 
===================================================================================== 
APPLICATION TERMINATED WITH THE EXIT STRING: Segmentation fault (signal 11) 

Однако, если я запускаю это из определенного узла (например, node1) и имеет только «node1» в файле машин, он выполняется, как ожидалось, используя нужное количество потоков на узел (скажем, если был указан «node1» дважды в файле машин, а команда mpiexec была похожа на «mpiexec -np 2 ...»).

Вторая вещь, которую я пробовал, вместо ссылки «-openmp», я ссылаюсь на «-liomp5». Когда я это делаю, код компилируется и запускается даже через узлы. Однако он не работает в любом поточном смысле. «Omp_get_num_threads» вернет 8 потоков на узел (что правильно), но он будет запускать только один поток на узел, указанный в файле машин, тем самым не выполняя фактической потоковой передачи.

Я использую последний компилятор ifort (12.1.2) и mpich2, как указано. Размер стека неограничен, проверен через «ulimit -a» и считается неограниченным.

Исходный код файла laplace.f следующим образом:

 program lpmlp 
     include 'mpif.h' 
     include "omp_lib.h" 

     integer imax,jmax,im1,im2,jm1,jm2,it,itmax 
     parameter (imax=10001,jmax=10001) 
     parameter (im1=imax-1,im2=imax-2,jm1=jmax-1,jm2=jmax-2) 
     parameter (itmax=100) 
     real*8 u(imax,jmax),du(imax,jmax),umax,dumax,tol,pi 
     parameter (umax=10.0,tol=1.0e-6,pi=3.14159) 
! Additional MPI parameters 
     integer istart,iend,jstart,jend 
     integer size,rank,ierr,istat(MPI_STATUS_SIZE),mpigrid,length 
     integer grdrnk,dims(1),gloc(1),up,down,isize,jsize 
     integer ureq,dreq 
     integer ustat(MPI_STATUS_SIZE),dstat(MPI_STATUS_SIZE) 
     real*8 tstart,tend,gdumax 
     logical cyclic(1) 
     real*8 uibuf(imax),uobuf(imax),dibuf(imax),dobuf(imax) 
! OpenMP parameters 
     integer nthrds,nthreads  

! Initialize 
     call MPI_INIT_THREAD(MPI_THREAD_FUNNELED,IMPI_prov,ierr) 
     call MPI_COMM_RANK(MPI_COMM_WORLD,rank,ierr) 
     call MPI_COMM_SIZE(MPI_COMM_WORLD,size,ierr) 
! 1D linear topology 
     dims(1)=size 
     cyclic(1)=.FALSE. 
     call MPI_CART_CREATE(MPI_COMM_WORLD,1,dims,cyclic,.true.,mpigrid 
    +  ,ierr) 
     call MPI_COMM_RANK(mpigrid,grdrnk,ierr) 
     call MPI_CART_COORDS(mpigrid,grdrnk,1,gloc,ierr) 
     call MPI_CART_SHIFT(mpigrid,0,1,down,up,ierr) 
     istart=2 
     iend=imax-1 
     jsize=jmax/size 
     jstart=gloc(1)*jsize+1 
     if (jstart.LE.1) jstart=2 
     jend=(gloc(1)+1)*jsize 
     if (jend.GE.jmax) jend=jmax-1 
     nthrds=OMP_GET_NUM_PROCS() 
     print*,"Rank=",rank,"Threads=",nthrds 
     call omp_set_num_threads(nthrds) 

!$OMP PARALLEL DEFAULT(SHARED) PRIVATE(i,j) 
! Initialize -- done in parallel to force "first-touch" distribution 
! on ccNUMA machines (i.e. O2k) 
!$OMP DO 
     do j=jstart-1,jend+1 
     do i=istart-1,iend+1 
      u(i,j)=0.0 
      du(i,j)=0.0 
     enddo 
     u(imax,j)=umax*sin(pi*float(j-1)/float(jmax-1)) 
     enddo 
!$OMP END DO 
!$OMP END PARALLEL 

! Main computation loop 
     call MPI_BARRIER(MPI_COMM_WORLD,ierr) 
     tstart=MPI_WTIME() 
     do it=1,itmax 
! We have to keep the OpenMP and MPI calls segregated... 
     call omp_set_num_threads(nthrds) 

!$OMP PARALLEL DEFAULT(SHARED) PRIVATE(i,j) 
!$OMP MASTER 
     dumax=0.0 
!$OMP END MASTER 
!$OMP DO REDUCTION(max:dumax) 
     do j=jstart,jend 
      do i=istart,iend 
       !nthreads = OMP_GET_NUM_THREADS() 
       !print*,"Jack",rank,nthreads,nthrds 
       du(i,j)=0.25*(u(i-1,j)+u(i+1,j)+u(i,j-1)+u(i,j+1))-u(i,j) 
       dumax=max(dumax,abs(du(i,j))) 
      enddo 
     enddo 
!$OMP END DO 
!$OMP DO 
     do j=jstart,jend 
      do i=istart,iend 
       u(i,j)=u(i,j)+du(i,j) 
      enddo 
     enddo 
!$OMP END DO 
!$OMP END PARALLEL 
! Compute the overall residual 
     call MPI_REDUCE(dumax,gdumax,1,MPI_REAL8,MPI_MAX,0 
    +  ,MPI_COMM_WORLD,ierr) 

! Send phase 
     if (down.NE.MPI_PROC_NULL) then 
      j=1 
      do i=istart,iend 
       dobuf(j)=u(i,jstart) 
       j=j+1 
      enddo 
      length=j-1 
      call MPI_ISEND(dobuf,length,MPI_REAL8,down,it,mpigrid, 
    +   dreq,ierr) 
     endif 
     if (up.NE.MPI_PROC_NULL) then 
      j=1 
      do i=istart,iend 
       uobuf(j)=u(i,jend) 
       j=j+1 
      enddo 
      length=j-1 
      call MPI_ISEND(uobuf,length,MPI_REAL8,up,it,mpigrid, 
    +   ureq,ierr) 
     endif 
! Receive phase 
     if (down.NE.MPI_PROC_NULL) then 
      length=iend-istart+1 
      call MPI_RECV(dibuf,length,MPI_REAL8,down,it, 
    +   mpigrid,istat,ierr) 
      call MPI_WAIT(dreq,dstat,ierr) 
      j=1 
      do i=istart,iend 
       u(i,jstart-1)=dibuf(j) 
       j=j+1 
      enddo 
     endif 
     if (up.NE.MPI_PROC_NULL) then 
      length=iend-istart+1 
      call MPI_RECV(uibuf,length,MPI_REAL8,up,it, 
    +   mpigrid,istat,ierr) 
      call MPI_WAIT(ureq,ustat,ierr) 
      j=1 
      do i=istart,iend 
       u(i,jend+1)=uibuf(j) 
       j=j+1 
      enddo 
     endif 
     write (rank+10,*) rank,it,dumax,gdumax 
     if (rank.eq.0) write (1,*) it,gdumax 
     enddo 
     call MPI_BARRIER(MPI_COMM_WORLD,ierr) 
     tend=MPI_WTIME() 
     if (rank.EQ.0) then 
     write(*,*) 'Calculation took ',tend-tstart,'s. on ',size, 
    +  ' MPI processes' 
    +  ,' with ',nthrds,' OpenMP threads per process' 
     endif 
     call MPI_FINALIZE(ierr) 
     stop 
     end 

При запуске -liomp5 связанного в сборе, видно, что:

call omp_set_num_threads(nthrds) 

выполняется с nthrds = 8, проверяется через операторы печати, однако при немедленной проверке:

nthreads = OMP_GET_NUM_THREADS() 

итоговый nth reads = 1. Однако в случае, когда завершается ссылка в -openmp при компиляции (все тот же узел в файле машин, при запуске запуска с одного и того же узла), nthreads = 8.

Если я укажу, имя заголовка сначала в файле машины дольше, говоря:

===================================================================================== 
= BAD TERMINATION OF ONE OF YOUR APPLICATION PROCESSES 
= EXIT CODE: 11 
= CLEANING UP REMAINING PROCESSES 
= YOU CAN IGNORE THE BELOW CLEANUP MESSAGES 
===================================================================================== 
[proxy:0:[email protected]] HYD_pmcd_pmip_control_cmd_cb (./pm/pmiserv/pmip_cb.c:906): assert (!closed) failed 
[proxy:0:[email protected]] HYDT_dmxu_poll_wait_for_event (./tools/demux/demux_poll.c:77): callback returned error status 
[proxy:0:[email protected]] main (./pm/pmiserv/pmip.c:226): demux engine error waiting for event 
[[email protected]] HYDT_bscu_wait_for_completion (./tools/bootstrap/utils/bscu_wait.c:70): one of the processes terminated badly; aborting 
[[email protected]] HYDT_bsci_wait_for_completion (./tools/bootstrap/src/bsci_wait.c:23): launcher returned error waiting for completion 
[[email protected]] HYD_pmci_wait_for_completion (./pm/pmiserv/pmiserv_pmci.c:189): launcher returned error waiting for completion 
[[email protected]] main (./ui/mpich/mpiexec.c:397): process manager error waiting for completion 

Много информации, но, надеюсь, не слишком много. Спасибо за любую помощь.

+0

мои рекомендации: (1) смешивание MPI и OpenMP, я бы начал практиковать с простым образцом кода (http://www.slac.stanford.edu/comp/unix/farm/mpi_and_openmp.html). (2) Попробовал ли отладчик выяснить, где именно в вашем коде происходит segfault? – steabert

+1

@KyleKanos Я выполнил ретрансляцию из-за [этого запроса по мета] (http://meta.stackexchange.com/a/226446/158100). Если вы недовольны этим, поделитесь своими идеями. – rene

ответ

0

Попробуйте запустить программу под номером Valgrind (обязательно для перекомпиляции с -g для отладки символов). Нечто подобное, вероятно, будет полезно:

% mpiexec -n 2 valgrind -q ./jack_openmp.exe 

Если он сообщает никаких предупреждений/ошибок в программе (а не только какую-то библиотеку случайной системы), то есть почти наверняка ошибки в коде, которые вам нужно исправить. Посмотрите на указанную трассировку стека и выясните, почему Valgrind жалуется.

+0

Обновление результатов. После многих поисков неисправностей я обнаружил, что существует чувствительность к размеру объявленных статических массивов. Если статические массивы малы, код работает нормально, если они «слишком большие», код выходит из строя с ошибками нечетной сегментации, перечисленными выше. В случае примера fortran-программы магическое число равно 720. То есть, если imax = jmax = 720, то код подходит к завершению правильно. Если imax = jmax> = 721, код выходит из строя с ошибками seg. – jackd

+0

В качестве догадки я переопределял статические массивы одинакового размера, но динамически выделялся, и все отлично работает независимо от того, насколько велик массив. У меня нет хорошего понимания разницы между тем, как обрабатываются статически и динамически распределенные массивы, но это, по-видимому, является ключом к проблеме. Это не решает мою проблему (просто переустановка динамического распределения), так как этот код является всего лишь тестовым примером для гораздо большего кода. Мне все еще нужно выяснить, какие параметры компилятора и/или Ubuntu необходимо изменить, чтобы все работало. – jackd

1

Возможно, размер стека в OpenMP слишком мал. Вы пробовали установить OMP_STACKSIZE с большим размером?

% export OMP_STACKSIZE=512m # may be another value: 32m, 64m, 128m, 256m ... 

Каждый OpenMP поток использует собственную память стека, размер стека по умолчанию 2MB в IA-32 и 4MB в архитектуре Intel64.

Смежные вопросы