Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Allocatable arrays in subroutines

haminin
Beginner
592 Views

I have got a problem in allocating arrays in subroutines and transferring data from them to the program to use them in other subroutines. I would very much appreciate your comments.

The following code is simplified example for this purpose.

PROGRAM TESTPROG

IMPLICIT NONE

INTEGER, ALLOCATABLE :: A(:)

INTEGER I, N

N = 10

CALL TESTSUB(A,N)

DO 2I = 1, N

2 PRINT*, A(I)

END PROGRAM TESTPROG

SUBROUTINE TESTSUB(A,N)

INTEGER, ALLOCATABLE, INTENT(INOUT) :: A(:)

INTEGER, INTENT(INOUT) :: N

INTEGER I

ALLOCATE (A(N))

DO 5I = 1, N

5 A(I) = I

RETURN

END SUBROUTINE TESTSUB

The code can be compiled with Visual Fortran Compiler but the following error occurs when it runs:

forrtl: severe (157): Program Exception - access violation

I don't know what's wrong, but could solve it putting the procedure in a module as bellow:

MODULE TESTMODULE

IMPLICIT NONE

INTEGER, ALLOCATABLE :: A(:)

CONTAINS

SUBROUTINE TESTSUB(N)

IMPLICIT NONE

INTEGER, INTENT(INOUT) :: N

INTEGER I

ALLOCATE(A(N))

DO 12I = 1, N

12 A(I) = I

RETURN

END SUBROUTINE TESTSUB

END MODULE TESTMODULE

PROGRAM TESTPROG

USE TESTMODULE

IMPLICIT NONE

INTEGER I, N

N = 10

CALL TESTSUB(N)

DO 15I = 1, N

15 PRINT *, A(I)

END PROGRAM TESTPROG

It works, but I am not happy with the solution as I prefer to write a program first and all subroutines after that, not possible in this way. I also don't know if there is a better solution as the program seems to run slowly.

Kind regards

Hamid

0 Kudos
2 Replies
TimP
Honored Contributor III
592 Views
If you allocate in an external subroutine, it is deallocated automatically at exit, so is no longer available when you reach PRINT. If you move TESTSUB out of the module, and put USE TESTMODULE in the subroutine and main program, and move the allocation into the main, ahead of TESTSUB, it should work OK. You might add a check to see if your array is allocated when used, as a debugging tool.
The time spent on allocate and deallocate may be similar to the time spent on filling the array, up to around N==100 for stack allocation, and larger for heap, so you can expect measurable performance reduction unless the allocation is larger.
0 Kudos
haminin
Beginner
592 Views
Quoting - tim18
If you allocate in an external subroutine, it is deallocated automatically at exit, so is no longer available when you reach PRINT. If you move TESTSUB out of the module, and put USE TESTMODULE in the subroutine and main program, and move the allocation into the main, ahead of TESTSUB, it should work OK. You might add a check to see if your array is allocated when used, as a debugging tool.
The time spent on allocate and deallocate may be similar to the time spent on filling the array, up to around N==100 for stack allocation, and larger for heap, so you can expect measurable performance reduction unless the allocation is larger.

Thank you very much for your comment. As you said I moved TESTSUB out of the module and added USE TESTMODULE to the program. But I didn't move the allocation as it is more convenient to be in my subroutine. The program is now in the following form and it works.

If you see something suspicious in the code please let me know.

Many thanks

Hamid

MODULE TESTMODULE

IMPLICIT NONE

INTEGER, ALLOCATABLE :: A(:)

END MODULE TESTMODULE

PROGRAM TESTPROG

USE TESTMODULE

IMPLICIT NONE

INTEGER I, N

N = 10

CALL TESTSUB(N)

DO 15I = 1, N

15 PRINT *, A(I)

END PROGRAM TESTPROG

SUBROUTINE TESTSUB(N)

USE TESTMODULE

IMPLICIT NONE

INTEGER, INTENT(INOUT) :: N

INTEGER I

ALLOCATE(A(N))

DO 12I = 1, N

12 A(I) = I

RETURN

END SUBROUTINE TESTSUB

0 Kudos
Reply