问题
I need to initialize an static array in a Fortran subroutine
double precision A(56136,8)
like so:
A(1,1)=0.999950528145
A(1,2)=0.99982470274
A(1,3)=0.999987006187
.
.
.
A(56136,7)=0.933468163013
A(56136,8)=0.0668926686049
The latter is generated by another program.
Compilation with ifort 13.0 ifort file.f -O0 takes very long (around 30 minutes).
Q1: What is the reason for this and how can I avoid it?
I have no handle on the main program, the subroutine is linked to third party files. The subroutine is called very often, so file access is not desirable.
Q2: Can I put the initialization outside the subroutine, without having a main program, avoiding the initialization every time the subroutine is called?
Edit
It is constant. Initializing it in the declaration statement would look like this?
double precision A(56136:8)=reshape(/*
& #, #, #, #, #, #, #, #,
& #, #, #, #, #, #, #, #,
:
& */,(56136,8))
This does not work because there are too many newlines.
回答1:
I did a test with 10000 integers and it compiles in seconds when using a DATA statement. My array holds 50000 integers but wanted to see if I can assign them in blocks of 10000.
program Console1
implicit none
! Variables
integer A(50000)
data A(1:10000) / & ! 1000 lines of 10 numbers each to follow:
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, &
31, 37, 41, 43, 47, 53, 59, 61, 67, 71, &
73, 79, 83, 89, 97, 101, 103, 107, 109, 113, &
127, 131, 137, 139, 149, 151, 157, 163, 167, 173, &
179, 181, 191, 193, 197, 199, 211, 223, 227, 229, &
233, 239, 241, 251, 257, 263, 269, 271, 277, 281, &
...
104087,104089,104107,104113,104119,104123,104147,104149,104161,104173, &
104179,104183,104207,104231,104233,104239,104243,104281,104287,104297, &
104309,104311,104323,104327,104347,104369,104381,104383,104393,104399, &
104417,104459,104471,104473,104479,104491,104513,104527,104537,104543, &
104549,104551,104561,104579,104593,104597,104623,104639,104651,104659, &
104677,104681,104683,104693,104701,104707,104711,104717,104723,104729 /
! Append the first 10000 elements to the remaining array
A(10001:50000) = [A(1:10000),A(1:10000),A(1:10000),A(1:10000)]
print *, A(9998:10002)
end program Console1
Edit 1
Here is how do use a DATA statement with a COMMON block to set the values inside a subroutine. Note that use of common blocks is nearly deprecated.
subroutine A_Fill()
implicit none
integer :: A(10)
common /vals/ A
data A/ 1,2,3,4,5,6,7,8,9,10 /
end subroutine
program Console1
implicit none
! Variables
integer :: A(10)
common /vals/ A
call A_Fill()
print *, A
end program Console1
Edit 2
Another solution that uses a function to copy the saved array into a secondary working copy.
function A_Fill() result(B)
implicit none
integer :: B(10)
integer,save :: A(10)
data A/ 1,2,3,4,5,6,7,8,9,10 /
B = A
end function
program Console1
implicit none
interface
function A_Fill() result(B)
implicit none
integer :: B(10)
end function
end interface
! Variables
integer :: A(10)
A = A_Fill()
print *, A
end program Console1
来源:https://stackoverflow.com/questions/45709501/why-does-fortran-90-compilation-takes-very-long-when-large-static-array-are-init