2014-09-02 3 views
1

다른 서브 루틴을 포함하는 서브 루틴을 포함하는 모듈이 있습니다. 외부 서브 루틴에는 내부 서브 루틴을 호출하는 병렬 OpenMP 영역이 있습니다. 코드가 컴파일되지 않고 오류없이 실행되지만 결과가 올바르지 않습니다.OpenMP 지역에서 내부 서브 루틴 호출

module my_module 
contains 
    subroutine a(...) 
     *...some variables* 
     !$OMP PARALLEL DO DEFAULT(PRIVATE) SHARED(...) 
     *...do some work* 
     call b(...) 

     !$OMP END PARALLEL DO 
    contains 
     subroutine b(...) 
      *...some variables* 
      *...do some work* 
     end subroutine b 
    end subroutine a 
end my module 

내가 인텔 디버거 idb를 실행하는 경우, 그것은 나에게 subroutine b 내부 SIGSEGV를 표시합니다. 이제 subroutine a 안에있는 subroutine b의 내용을 수동으로 바꾸고 OMP 절을 그대로 유지하면 SIGSEGV 오류가 발생하지 않고 결과가 정확합니다.

편집 : 전체 코드는 여기에 있습니다 : https://github.com/mikolchon/cfd/blob/master/cfd2/calcRHS.f90 그것은 오일러 유체 방정식을 해결하기 위해 서브 루틴을 포함하는 모듈입니다. 나는 idb를 실행하면, 다음을 줄 것이다 :

<code>idb</code> message

EDIT2을 : 그냥이 오류를 재현 작은 예를 작성하는 관리 :

module some_module 
    implicit none 
contains 
    subroutine sub0() 
     real :: a(5) 
     integer :: i 
     a(:) = 0 
     !$OMP PARALLEL DO DEFAULT(PRIVATE) SHARED(a) 
     do i = 1, 5 
      call sub1() 
     end do 
     !$OMP END PARALLEL DO 
     print*, a(:) 
    contains 
     subroutine sub1() 
      a(i) = a(i) + 1 
     end subroutine sub1 
    end subroutine sub0 
end module some_module 

program main 
    use some_module 
    implicit none 
    call sub0() 
end program main 

이 프로그램은 1.000000 1.000000 1.000000 1.000000 1.000000을 인쇄해야합니다. OpenMP를

ifort name.f90 -openmp -check bounds -traceback -O0없이 잘 작동 - - (컴파일러 14.0.2 ifort입니다)

ifort name.f90 -check bounds -traceback -O0 바운드에서 배열 인덱스를 제공합니다 다음은 서로 다른 컴파일 플래그 나는 시도했다.

ifort name.f90 -openmp -check bounds -traceback

는 - 내가 -O0를 사용할 때 오류가 표시됩니다, 그래서 기본적으로

을 작동합니다. 그렇다고해서 -O0을 사용하지 않으면 오류가 없다는 것을 의미하지는 않습니다 (원래 코드가 잘못된 결과를 나타 내기 때문에이 말을합니다). 내가 명시 적으로 인덱스 i를 전달하는 경우 또한, 즉 :

.... 
call sub1(i) 
.... 
contains 
    subroutine sub1(i) 
     integer i 
.... 

다음 -O0 컴파일, 다시 작동합니다. 그래서 내 질문에 OpenMP가 변수 i을 하위 서브 루틴에 상속하는 데 어려움을 겪고 있다는 것입니다.

+2

나머지 코드를 추가하지 않으면 대답 할 수 없습니다. 어쩌면'b'는 실 금고가 아니지만 누가 알 수 있습니다. –

+1

어림짐작은 코드가 어떻게 보이는지 몇 문장으로 설명해야한다면, 설명하지 말고 코드를 게시하십시오. –

+0

컴파일러 옵션은 무엇입니까? '-openmp'는'재귀 적 (recursive) '을 시행해야하지만 다른 옵션들도이를 망칠 수 있습니다. –

답변

3

OpenMP 사양에서 허용되는지 확실하지 않습니다. 이 스레드 https://software.intel.com/en-us/forums/topic/297424에는 또한 약간의 의혹이있다. 어쩌면 인텔 포트란이 잘못 구현 한 것일 수도 있지만 공식 사양을주의 깊게 읽어야합니다.

귀하의 경우에도 내가 시도한 것처럼 루프에 직접 프로 시저 코드를 붙여 넣어 호스트 연결의 필요성을 피할 수 있습니다.

다른 옵션은 참조 된 스레드에서 제안 된 것처럼 임시 변수로 개인 변수를 전달하는 것으로 호스트 연결을 피할 수도 있습니다.

충분히 높은 최적화 수준 만 사용하면 도움이되는지 확실하지 않습니다. 인라인을 필요로하는 것은 안전하지 않을 수 있습니다.

FWIW Oracle Solaris Studio 12.4beta에서도 같은 오류가 발생합니다.


IanH에 따르면.

"내부 루틴 내부 I에 참조 영역에 있지만 구성체에있는 난 지칭되는 여부 일본어 나 구성 않는 종래 병렬이고 또는 개인용 사본이 OpenMP 4.0 및 이전 버전에서 "지정되지 않음"으로 호출됩니다. " 이것은 이러한 사용은 피해야한다 수단

The corresponding original list item. Inside the construct, all references to the original 
list item are replaced by references to the new list item. In the rest of the region, it is 
unspecified whether references are to the new list item or the original list item. 

:

specifiction의 관련 섹션 (. OpenMP를 4.0 2.14.3.3 14)이다.

+0

설명 주셔서 감사합니다. –

+0

이것은 매우 도움이되었습니다. 감사! – Michael