2017-12-05 26 views
0

은은의 숫자는 때때로 잘못 아래 내 프로젝트에 일하고 나는 test1,2,3 루틴과 이상한 병렬 데 문제가 약간 변경 코드입니다 :OMP와의 병렬 오버랩 및 포트란에서의 백 업데이트 어레이?

integer, parameter :: N=6 
    integer, parameter :: chunk_size=3 
    integer, dimension(1:N) :: a,b,c 

contains 

    subroutine array_setup 
    implicit none 
    integer :: i 

    do i=1,N 
     a(i)=2*i 
     b(i)=i*i 
     c(i)=i*i-i+2 
    end do 

    return 
    end subroutine array_setup 

    subroutine test1 
    implicit none 
    integer :: i 

    !$OMP parallel do private(i) shared(a,b,c) schedule(static,chunk_size) 
    do i=2,N 
     a(i-1)=b(i) 
     c(i)=a(i) 
    end do 
    !$OMP end parallel do 

    return 
    end subroutine test1 

    subroutine test2 
    implicit none 
    integer :: i 

    !$OMP parallel do private(i) shared(a,b,c) schedule(static,chunk_size) 
    do i=2,N 
     a(i-1)=b(i) 
     a(i)=c(i) 
    end do 
    !$OMP end parallel do 

    return 
    end subroutine test2 

    subroutine test3 
    implicit none 
    integer :: i 

    !$OMP parallel do private(i) shared(a,b,c) schedule(static,chunk_size) 
    do i=2,N 
     b(i)=a(i-1) 
     a(i)=c(i) 
    end do 
    !$OMP end parallel do 

    return 
    end subroutine test3 

end program vectorize_test 

이 아래는 나는 1 위에서 스레드 수를 증가시킬 때

after setup 
      1   2   1   2 
      2   4   4   4 
      3   6   9   8 
      4   8   16   14 
      5   10   25   22 
      6   12   36   32 
after test1 
      1   4   1   2 
      2   9   4   4 
      3   16   9   6 
      4   25   16   8 
      5   36   25   10 
      6   12   36   12 
after test2 
      1   4   1   2 
      2   9   4   4 
      3   16   9   8 
      4   25   16   14 
      5   36   25   22 
      6   32   36   32 
after test3 
      1   2   1   2 
      2   4   2   4 
      3   8   4   8 
      4   14   8   14 
      5   22   14   22 
      6   32   22   32 

, 내가 오전, 출력이 잘못된 만드는 각 컬럼에 변화 이상한 숫자를 얻을 : 올바른 OMP_NUM_THREADS = 1 출력 샘플 이 문제가 생기면 어떻게해야합니까? 당신이

!$OMP parallel do private(i) shared(a,b,c) schedule(static,chunk_size) 
do i=2,N 
    a(i-1)=b(i) 
    c(i)=a(i) 
end do 
!$OMP end parallel do 

을 수행 할 때

+0

환영합니다. [둘러보기]를 읽고 [질문]을 읽으십시오. 모든 포트란 질문에 [태그 : 포트란]을 사용하십시오. 특정 버전의 questio에 특정 버전 태그를 추가 할 수는 있지만 일반적으로 2017 년에는 오래되고 쓸모없는 Fortran 90으로 제한하고 싶지 않습니다. 코드는 Fortran 버전과 전혀 관련이 없습니다. –

답변

2

당신이 다른 스레드에 예정되어 있기 때문에 아직 계산되지 않은 a(i)의 하나 개의 스레드 판독 값을 가질 수 있습니다. 루프 반복은 이전 루프에 따라 다릅니다. 이 방법으로는 병렬 처리 할 수 ​​없습니다. 하나의 스레드가 다른 스레드가 방금 쓰는 동일한 a(i) 위치를 읽을 수도 있습니다. 이는 또한 오류 (경쟁 조건)입니다. 루프

!$OMP parallel do private(i) shared(a,b,c) schedule(static,chunk_size) 
do i=2,N 
    a(i-1)=b(i) 
    a(i)=c(i) 
end do 
!$OMP end parallel do 

반복이 됨

는 독립이 아니다. a(i)의 위치는 다음 반복에서 덮어 쓰게됩니다. 이 두 작업이 수행되어야하는 순서로 두 스레드가 충돌 할 수 있습니다. Yiu 안전하게

a(1) = b(2) 
!$OMP parallel do private(i) shared(a,b,c) schedule(static,chunk_size) 
do i=2,N 
    a(i)=c(i) 
end do 
!$OMP end parallel do 

같이 제 3 고리

!$OMP parallel do private(i) shared(a,b,c) schedule(static,chunk_size) 
do i=2,N 
    b(i)=a(i-1) 
    a(i)=c(i) 
end do 
!$OMP end parallel do 

제 루프와 동일한 문제를 갖고이를 다시 쓸 수있다. 각 반복은 이전 반복의 값에 따라 다릅니다. 이것은 쉽게 병렬 처리 될 수 없습니다. 반복을 서로 의존하지 않도록 알고리즘을 다시 작성하는 방법을 찾아야합니다.

각 서브 루틴의 return에는 nead가 없습니다. 상위 범위에있는 경우 각 서브 루틴에 implicit none이 필요하지 않습니다.