2017-09-13 2 views
0

다른 쪽보다 선호되는 "일반 규칙"이 있습니까?호스트 협회 대 포트란에서 협회 사용

이 질문의 문맥은 다음과 같습니다. 어제 호스트 연결에 관한 다른 질문을했습니다. (link) 및 의견에서 호스트 연결을주의해서 사용하는 것이 좋습니다. 호스트 연결을 통해 서브 루틴이 모듈에서 선언 된 모든 변수에 대한 제한없는 액세스를 가지기 때문에 부주의하게 변수를 수정하는 것이 쉬운 이유입니다.

module mod 
implicit none 

real :: x 

contains 

subroutine sub(y) 
    use other_mod, only: a 

    real, intent(out) :: y 

    y = a + x 
    a = a + 1. 
    x = x + 1. 
end subroutine sub 

end module mod 
모두 a

xsub에서 수정 :

는이를 설명하기 위해 다음 코드 예제를 사용합니다. 그러나 x의 경우이를보기 위해 모든 코드를 검토해야합니다. 그 sub에서 a이 사용되고 (가능하게 수정 된) sub의 선언 부분을 보면 쉽게 알 수 있습니다. (필요한 경우 다음 사용된다)

  1. 모듈 또는 유일한 변수 선언을 포함하는 모듈만을 절차를 포함
  2. 모듈이 의미에서

    , 모듈의 두 종류가 바람직 보인다 매개 변수 선언은 있지만 변수 선언은 사용하지 않습니다.

이렇게하면 변수에 대한 호스트 연결이 모두 제거됩니다.

그러나 이것은 여러 가지 이유로 실천하지 않는 것 :

  • 내가 하나 개의 모듈에서 같은 변수를 사용하여 (및 수정) 다스 서브 루틴이있을 수 있습니다. 을 사용하면이 변수가 매번 코드를 혼란스럽게 만듭니다. 특히 많은 코드가있는 경우 (몇 백 개 정도) 특히 그렇습니다. 이 실제로 사용되는 곳에서 변수의 선언을 구분을
  • 코드가 덜 이해 할 것 같다
    • 하나, 하나는 모든 선언을 포함하는 하나 개의 거대한 제어 파일을 만듭니다. 코드가 크고 많은 변수를 사용하는 경우 이는 매우 혼란 스러울 수 있습니다.
    • 또는 모든 모듈 (또는 동일한 콘텐츠에 의존하는 모듈 그룹)에 대해 별도의 제어 파일을 만듭니다. 이것은 을 사용하여을 사용하기 때문에 코드 자체가 더 잘 이해할 수있게합니다. 그러나 코드의 구조가 복잡해지면서 훨씬 복잡한 파일 구조 (및 수반되는 종속 구조)가 만들어집니다. 이 (가 사용되는 동일한 모듈 변수의 선언을 넣어 분별들은 호스트 연계하여 사용되도록하면 : 결국

이 모두 귀결) 선언을 별도의 모듈로 외주 처리하는 것이 더 현명합니까 (변수가 필요할 때 사용 연관을 통해 사용되도록)?

일반적인 지침이 있습니까? 아니면 사례별로 결정해야합니까?그리고 경우에 따라 다르다면, 서로를 위해 갈 이유는 무엇입니까?

+0

굵은 글씨로 자신의 질문에 답을 얻지 못했습니까? 즉, 변수가 (또는 주로) 동일한 모듈에서 선언 된 루틴에 의해 사용되는 경우 * host-association *을 사용하고 많은 모듈에서 사용할 변수를 정의 할 때 * use-association *을 사용합니까? 그리고'public'과'private' 속성을 사용하여 변수를 포함한 모듈 엔티티에 대한 액세스를 제한 할 수 있다는 것을 잊지 마십시오. –

+0

호스트 연관의 일부 측면, 특히 일부 서브 루틴이 부주의하게 변수를 수정할 수도 있기 때문에 굵은 텍스트가 질문에 답하지 않는다고 생각합니다. 그래서 예를 들어, 매개 변수에만 호스트 연결을 사용해야하는지 잘 모르겠습니다. 그러나 그 접근법에 대한 몇 가지 주장이 있습니다 (질문 참조). 대체로, 나는 무엇을 해야할지, 언제 할 것인지를 쉽게 모르며, 다른 사람들이 어떻게 보는지에 대한 약간의 정보를 얻기를 바라고 있습니다. 좀 더 이해하기 쉽지만 위험한 경로를 선택하거나 안전한 옵션을 찾으십시오. – ConfusedProgrammer

+0

귀하의 이전 질문에 대한 내 의견은 내부 절차를 피하기위한 조언으로 해석되어서는 안됩니다. 나의 목표는 당신이 알고있는 명확하지 않았기 때문에 호스트 변수의 어떤 것도 args리스트에 선언 된 것뿐만 아니라 액세스 될 수 있다는 것을 지적하기 위해서였다. BTW,이 페이지의 오른쪽에있는 "관련"링크에 유용한 팁이 있습니다 ... –

답변

1

Fortran은 메인 프로그램, 외부 프로 시저 및 모듈 등 다양한 "프로그램 단위"간에 데이터를 작성, 저장, 사용 및 전달하는 여러 가지 방법을 제공합니다. 아시다시피 각 프로그램 단위에는 호스트 연결을 통해 호스트에 포함 된 변수 나 프로 시저에 액세스 할 수있는 내부 절차가 포함될 수 있습니다. 이것은 종종 장점으로 간주됩니다. 그의 의견에 @HighPerformanceMark 이미 언급 한 바와 같이, 호스트 협회 또는 사용-연결을 사용하는 경우에 대한 일반적인 지침은 다음에 선언 된 루틴 만 (또는 주로) 사용되는 변수가된다

사용 호스트 연결시 동일한 모듈을 사용하고 여러 모듈에서 사용할 변수를 정의하려는 경우 use-association을 사용하십시오.

주 프로그램의 대부분 또는 모든 호스트 변수가 각 내부 프로 시저 (약 12 개 정도의 서브 루틴). 그렇다면 호스트 연관성이 매우 합리적인 옵션처럼 보이고 각 서브 루틴에 명시 적으로 인수를 전달할 필요가 없습니다. 다른 한편, 각 서브 루틴이 실제로 변수의 서브 세트만을 사용한다면, 서브 루틴에 대해 더 명확히하는 것이 합리적 일 수 있습니다.

필자와 마찬가지로 일반적으로 인수 목록에서 선언되지 않은 프로 시저 내에서 변수를 사용하는 것은 불편합니다. 이것은 부분적으로 args 목록이 자체 문서화하는 방식을 좋아하고 코드와 데이터가 조작되는 방식에 대해 추론하는 데 도움이되기 때문입니다. 다른 직원과 공동 작업을하거나 코드에서 약간의 시간을 보내고 내 기억이 희미 해지면 더욱 그렇습니다. 그러나 호스트 연계를 피하는 이유가 거의 없다는 것을 알았습니다. 호스트 연계가 어떻게 작용하고 전략이 있는지 알고있는 한.

실제로 내부 프로 시저와 호스트 연결을 자주 사용하는 경향이 있습니다 (특히 짧은 함수/서브 루틴의 경우). 느슨하게 호스트를 "객체"로, 변수를 "속성"으로, 그리고 모든 내부 절차를 작업을 수행하는 객체의 "메소드"와 매우 비슷하게 생각하면 도움이됩니다. 물론, 이는 단순화하는 것이지만, 실제로 그것은 요점입니다.

더 복잡한 프로그램의 경우 "주"프로그램 자체에서 호스트 연결의 양을 줄입니다.이 주 프로그램은 주로 적절한 순서와 컨텍스트로 다양한 서브 루틴을 호출하기 위해 존재합니다. 이 경우 use-association을 활용하고이를 필요로하는 프로그램 단위 내에서 직접 (예 : 절차, 변수, 유형, 매개 변수) use 모듈 엔티티를 선택할 수 있습니다. only:으로 필요한 모듈 엔티티에만 액세스를 추가로 제한 할 수 있습니다. 이렇게하면 가독성이 향상되고 데이터 흐름이 명확하게 표시됩니다. 나중에 코드를 업데이트하는 것이 더 간단합니다. 상속, 캡슐화, 기타 ...하지만 포트란 스타일. 어느 것이 실제로 꽤 좋다.

다음은 저와 Fortran에서 작업 한 중간 규모 프로젝트에서 작동하는 예제 프로그램 구조입니다. 필자는 널리 사용되는 (정적) 매개 변수를 별도의 모듈 (또는 함수에 따라 그룹화 된 경우 모듈)에 보관하고 싶습니다. 파생 된 유형 및 유형 바인드 프로 시저를 다른 별도 모듈에 보관합니다. 유용 할 경우 특정 모듈 엔티티를 다른 프로그램 단위에서 액세스 할 수 없도록 private으로 만듭니다. 그리고 나는 그것이라고 생각한다.

module params 
    implicit none 
    public    !! All items public/accessible by default. 
    integer, parameter :: dp = kind(0.d0) 
    integer, parameter :: nrows = 3 
    real(dp), parameter :: one=1.0_dp, two=2.0_dp 
    ... 
end module params 

module types 
    use params, only: dp, nrows 
    implicit none 
    public    !! Public by default. 
    private :: dim2 
    ... 
    integer, parameter :: dim2 = 3 
    ... 
    type :: A 
     integer :: id 
     real(dp), dimension(nrows,dim2) :: data 
     contains 
     procedure, pass :: init 
    end type A 
    ... 
    contains 
    subroutine init(self, ...) 
     ... 
    end subroutine init 
    ... 
end module types 

module utils 
    implicit none 
    private    !! Private by default. 
    public :: workSub1, workSub2, subErr 
    ... 
    integer,save :: count=0 !! Accessible only to entities in this module. 
    ... 
    contains 
    subroutine workSub1(...) 
     ... 
    end subroutine workSub1 

    subroutine workSub2(...) 
     ... 
    end subroutine workSub2 

    subroutine subErr(...) 
     ... 
    end subroutine subErr 

end module utils 


program main 
    !! An example program structure. 
    use params, only: dp 
    implicit none 
    real(dp) :: xvar, yvar, zvar 
    integer :: n, i 
    logical :: rc 

    call execute_work_subroutines() 

    contains    !! Internal procs inherit all vars declared or USEd. 
    subroutine execute_work_subroutines() 
     use types, only: A 
     type(A) :: DataSet 
     !! begin 
     call DataSet%init(i) 
     do i = 1,n 
      call workSub1(xvar,yvar,zvar,A,i,rc) 
      if (rc) call subErr(rc) 
      call workSub2(A,rc) 
      if (rc) call subErr(rc) 
     enddo 
    end subroutine execute_work_subroutines 
end program main 

1이 또한 서브 모듈,하지만 난 그들과 함께 익숙하지 오전 정보 오해의 소지가주고 싶지 않습니다. 그들은 논리적으로 큰 모듈을 분리하는 데 유용하게 보입니다.