1

I want to share data in an array between two programs. In another question I was advised to use an unformatted file for this, but I run into a problem when attempting this.

When I include this

OPEN(UNIT=10,FILE='all_paths.direct',FORM='UNFORMATTED', ACCESS='sequential', STATUS='unknown') 

in the code, I get a Segmentation fault?

EDIT: Here the programme:

    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

Using the same opening statement in another test programme does not cause a segfault

10
  • Why do you think you would get Segmentation fault? Commented Mar 19, 2014 at 12:55
  • I was told to make this a new question by Vladimir F, so I did. I think it causes a Segmentation fault because when I run it, I get a segmentation fault. When I run it in gdb, it tells me that the fault occurred in that line. If the answer helped, I wouldn't still need help, would I? The focus is, when I follow what I was being told by the two users in the other question, I get a segmentation fault. What's wrong. Commented Mar 19, 2014 at 13:07
  • Please write a minimal (builable) example that shows the segfault. It is very likely that you just use OPEN command in a wrong way, and not that OPEN command is buggy. Commented Mar 19, 2014 at 13:14
  • I've tried to clean up the question, but there still is not enough information to answer it. Commented Mar 19, 2014 at 13:14
  • Added the complete code now Commented Mar 19, 2014 at 13:25

2 Answers 2

4

This declaration

INTEGER, DIMENSION(100, 300000) :: combined

is likely to exceed your platform's limits for static arrays. The code will compile but the run-time will throw up its hands in despair as soon as the program starts to execute, and this will look as if it happens at the first executable statement. But the open statement is not causing a segmentation fault, trying to grab more stack (I think) than the platform provides (by default) is the issue here.

One option would be to fiddle with compiler options and environment settings, see your platform documentation for details. The other option would be to make the array allocatable

INTEGER, DIMENSION(:,:), ALLOCATABLE :: combined

and allocate it at run-time.

If you do this you'll find that the run-time baulks at executing the line

WRITE(33, '(100I3)') combined

where you make an attempt to write formatted output to a file opened for unformatted output.

Sign up to request clarification or add additional context in comments.

2 Comments

That would make sense. I just don't understand how allocate would solve the problem? The array would still have to be that big.
You need to learn about stack and heap and how the operating system and a program interact wrt the provision of memory. In general platforms provide a restricted amount of memory in a static allocation plus access to a dynamic allocation of more memory. Using allocate changes where your program asks for memory from the platform.
0

There a lots of OpenMP-related bugs in that code. The segmentation fault probably occurs because of out-of-bound array access due to poor variable sharing attributes. j, k, and l are used as private loop counters but not declared private and therefore might reach values above the loop upper value and garbage is read from the beginning and ending arrays. Also increments to a are not protected by an ATOMIC construct, not to mention that bridge also seems to modify a. start and goal also have to be private.

Start by fixing the sharing attributes of j, k, and 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

I'm not sure how exactly bridge modifies the value of a and how that interacts with incrementing a in each iteration, but in the code above the value is captured in a private variable, which might not be what you want. If it is important that the modified value of a as returned by bridge should be used in the next iteration, the whole body of the innermost loop should be put in a critical construct. This effectively will make the code serial - such algorithms are hardly parallelisable.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.