我想在两个程序之间共享数组中的数据。在another question中,我被建议使用未格式化的文件,但尝试此操作时遇到问题。
当我加入
时OPEN(UNIT=10,FILE='all_paths.direct',FORM='UNFORMATTED', ACCESS='sequential', STATUS='unknown')
在代码中,我得到了分段错误?
编辑:这是程序:
PROGRAM POSS_PATHS
use omp_lib
IMPLICIT NONE
INTERFACE
RECURSIVE SUBROUTINE bridge(start, goal, combined, a, b, interm, first)
USE hash_integer
USE locs_table
IMPLICIT NONE
INTEGER, DIMENSION(1:2), INTENT(IN) :: start, goal
INTEGER, DIMENSION(:,:), INTENT(INOUT) :: combined
INTEGER, DIMENSION(100), INTENT(INOUT) :: interm
INTEGER, INTENT(INOUT) :: a
INTEGER, INTENT(IN) :: b
INTEGER :: c
INTEGER :: i, k, j
INTEGER, DIMENSION(1:2) :: remainder, exact
INTEGER, DIMENSION(1:6) :: next, dflt
LOGICAL, INTENT(IN) :: first
END SUBROUTINE bridge
END INTERFACE
INTEGER, DIMENSION(1:8) :: beginning, ending
INTEGER, DIMENSION(1:2) :: start, goal
INTEGER, DIMENSION(100, 300000) :: combined
INTEGER, DIMENSION(100) :: interm
INTEGER :: i, j, k, l, a, b
OPEN(UNIT=33, FILE='all_paths', FORM='UNFORMATTED', ACCESS='sequential', STATUS='unknown')
DATA (beginning(i), i=1, 7) / 1, 2, 3, 4, 5, 6, 7 /
DATA (ending(i), i=1, 8) / 217, 225, 226, 227, 228, 231, 232, 233 /
a = 0
!$omp parallel
!$omp do
DO i=1, 7
DO j = 1, 7
DO k = 1, 8
DO l = 1, 8
a = a + 1
b = 1
start(1) = beginning(i)
start(2) = beginning(j)
goal(1) = ending(k)
goal(2) = ending(l)
combined(1:2,a) = start
CALL bridge(start, goal, combined, a, b, interm, .TRUE.)
END DO
END DO
END DO
END DO
!$omp end do
!$omp end parallel
WRITE(33, '(100I3)') combined
CLOSE(UNIT=10)
END PROGRAM
RECURSIVE SUBROUTINE bridge(start, goal, combined, a, b, interm, first)
USE hash_integer
USE locs_table
IMPLICIT NONE
INTEGER, DIMENSION(1:2), INTENT(IN) :: start, goal
INTEGER, DIMENSION(:,:), INTENT(INOUT) :: combined
INTEGER, DIMENSION(100), INTENT(INOUT) :: interm
INTEGER, INTENT(INOUT) :: a
INTEGER, INTENT(IN) :: b
INTEGER :: c
INTEGER :: i, k, j
INTEGER, DIMENSION(1:2) :: remainder, exact
INTEGER, DIMENSION(1:6) :: next, dflt
LOGICAL, INTENT(IN) :: first
remainder(1)= mod(start(1),8)
exact(1) = start(1) / 8
remainder(2) = mod(start(2),8)
exact(2) = start(2) / 8
DATA (dflt(i), i=1, 6) / 1000, 1000, 1000, 1000, 1000, 1000 /
c = b + 2
CALL hash_get(remainder, next, dflt)
DO k=1, 6, 2
next(k) = next(k)+(exact(1)*8)
next(k+1) = next(k+1)+(exact(2)*8)
IF((next(k) > goal(1) .AND. next(k+1) > goal(2)) .OR. next(k) > 233 .OR. next(k+1) > 233) THEN
CYCLE
END IF
interm(c:c+1) = next(k:k+1)
IF (next(k) == goal(1) .AND. next(k+1) == goal(2)) THEN
combined(1:c+1,a) = interm(1:c+1)
a = a + a
ELSE IF (next(k) > goal(1) .OR. next(k+1) > goal(2)) THEN
IF (first) THEN
CALL bridge(next(k:k+1), goal, combined, a, c, interm, .FALSE.)
ELSE
CYCLE
END IF
ELSE
CALL bridge(next(k:k+1), goal, combined, a, c, interm, .TRUE.)
END IF
END DO
END SUBROUTINE bridge
在另一个测试程序中使用相同的开始语句不会导致段错误
答案 0 :(得分:4)
此声明
INTEGER, DIMENSION(100, 300000) :: combined
可能会超出平台对静态数组的限制。代码将编译,但是一旦程序开始执行,运行时将在绝望中抛出,这看起来好像它发生在第一个可执行语句中。但open
语句不会导致分段错误,试图获取更多堆栈(我认为)比平台提供的(默认情况下)是这里的问题。
一种选择是调整编译器选项和环境设置,有关详细信息,请参阅平台文档。另一种选择是制作数组allocatable
INTEGER, DIMENSION(:,:), ALLOCATABLE :: combined
并在运行时分配它。
如果你这样做,你会发现执行该行的运行时阻碍
WRITE(33, '(100I3)') combined
您尝试将格式化输出写入为未格式化输出打开的文件。
答案 1 :(得分:0)
该代码中存在许多与OpenMP相关的错误。由于差的变量共享属性导致的数据访问越来越多,可能会发生分段错误。 j
,k
和l
用作私有循环计数器但未声明为私有,因此可能达到高于循环上限值的值,并且从beginning
读取垃圾ending
个数组。另外a
的增量不受ATOMIC
构造的保护,更不用说bridge
似乎也修改了a
。 start
和goal
也必须是私密的。
首先修复j
,k
和l
的共享属性:
!$omp parallel do private(j,k,l,b,aa,start,goal)
DO i=1, 7
DO j = 1, 7
DO k = 1, 8
DO l = 1, 8
!$omp atomic capture
a = a + 1
aa = a
!$omp end atomic
b = 1
start(1) = beginning(i)
start(2) = beginning(j)
goal(1) = ending(k)
goal(2) = ending(l)
combined(1:2,aa) = start ! aa holds the captured value of a
CALL bridge(start, goal, combined, aa, b, interm, .TRUE.)
END DO
END DO
END DO
END DO
!$omp end parallel do
我不确定bridge
如何修改a
的值以及它在每次迭代中如何与递增a
进行交互,但在上面的代码中捕获了值在一个私有变量中,这可能不是你想要的。如果重要的是a
返回的bridge
的修改值应该在下一次迭代中使用,那么最内层循环的整个主体应该放在critical
构造中。这有效地使代码串行 - 这种算法几乎不可并行。