I noticed a weird behaviour with gfortran, the version i am using is
GNU Fortran (MacPorts gcc5 5.2.0_0) 5.2.0
my os is OS X YOSEMITE 10.10.3 (14D136)
i run the following code
program test
implicit none
type :: mytype
real(kind=8),dimension(:,:,:),allocatable :: f
end type
type(mytype),dimension(:,:),allocatable :: tab
integer i,j
allocate(tab(3,8))
do i=1,3
do j=1,8
allocate(tab(i,j)%f(i,i,i))
enddo
enddo
call check_shapes(tab(:,1))
contains
subroutine check_shapes(arg)
integer :: n,k
type(mytype),dimension(:) :: arg
n=size(arg)
do k=1,n
print*,shape(arg(k)%f)
enddo
end subroutine
end program
The output is as expected
1 1 1
2 2 2
3 3 3
however, change the way i define dummy arguments in the subroutine
type(mytype),dimension(:) :: arg
to
class(mytype),dimension(:) :: arg
introducing a class instead of type for the dummy argument, i have the following output
2 2 2
3 3 3
1 1 1
Is this a bug? or i am missing something?
note that it works fine with ifort
version Intel(R) 64, Version 15.0.3.187 Build 20150408
I have checked the already reported bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61337
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58043
and both of them are (almost completely) fixed on the GCC trunk by a recent commit (probably https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58043 ). Your bug appears to be just a variant of these reports.
I have added the information about the recent change to the existing reports. You can expect GCC 6 to contain the fix.
Related
I asked a question about some strange behavior from a Fortran compiler here:
gfortran compiler cannot find misspelled full directory
Basically, the compiler sporadically** complains that a file is missing, but the problem is that the printed name of the file (full path, actually) is misspelled, so no wonder it's "missing". I thought that I resolved the problem by using relative paths, but it turns out that the problem was just dormant. Here's an example of one such complaint:
C:\Users\charl\Documents\GitHub\MOONS>gfortran -fopenmp -g -fimplicit-none -cpp
C:/Users/charl/Documents/GitHub/MOONS/code/globals/current_precision.f90
...
C:/Users/charl/Documents/GitHub/MOONS/code/solvers/induction/init_Bfield.f90
C:/Users/charl/Documents/GitHub
gfortran: error:
C:/Users/charl/Documents/GitHubMOONS/code/solvers/induction/init_Sigma.f90: No such file or directory
Notice that the forward slash ('/') is missing between GitHub and MOONS, and instead reads "GitHubMOONS". This path was correctly written in the makefile.
** I say sporadically because changing lines in the code sometimes results in the error disappearing. Similarly, removing some unused modules (that compile just fine) from my compilation list results in the error disappearing.
The compiler I'm using is:
GNU Fortran (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 4.9.2 Copyright (C) 2014 Free Software Foundation, Inc.
But I've seen the same problem with more recent compilers, e.g.:
x86_64-7.1.0-release-posix-seh-rt_v5-rev2
I think I am seeing a trend with when this error occurs, and it seems to occur more frequently when modules pass on public interfaces to other modules.
Question
So, my question is, given the following two modules:
module add_int_mod
implicit none
private
public :: add
interface add; module procedure add_int; end interface
contains
subroutine add_int(a,b)
implicit none
integer,intent(inout) :: a
integer,intent(in) :: b
a = a + b
end subroutine
end module
module add_all_mod
use add_int_mod
implicit none
private
public :: add
end module
What is the difference between these two programs, if any?
Program 1
program main
use add_all_mod ! only difference
implicit none
integer :: a,b
a = 0
b = 1
call add(a,b)
write(*,*) 'a = ',a
write(*,*) 'b = ',b
end program
Program 2
program main
use add_int_mod ! only difference
implicit none
integer :: a,b
a = 0
b = 1
call add(a,b)
write(*,*) 'a = ',a
write(*,*) 'b = ',b
end program
I appreciate any help/suggestions.
Firstly, I wasn't aware that bound checking was automatic when using gfortran. With the following code:
gfortran -Wno-array-bounds initial_parameters.f08 derrived_types.f08 lin_alg.f08 constitutive_models.f08 input_subs.f08 Subprograms.f08 mainprog.f08
I still receive the compile time warnings:
Warning: Array reference at (1) is out of bounds (3 > 2) in dimension 2
I am probably being silly here but from reading this, I thought that -Wno-array-bounds was supposed to suppress this warning? Compiling with -w successfully inhibits all warnings.
I don't know if it's relevant but the source of these warning are "Subprograms.f08" and "constitutive_models.f08" which are both modules containing subroutines and are used in the main program.
The same behaviour occurs if I attempt to compile an individual module with
gfortran -Wno-array-bounds -c constitutive_models.f08
I can confirm that compile warning with gfortran (4.4) with this simple code:
integer,parameter::dim=3
integer :: x(2)
if(dim.eq.1)write(*,*)x(dim)
end
Warning: Array reference at (1) is out of bounds (3 > 2) in dimension 2
this could arguably be considered a bug since one would expect the compiler to optimize out the whole if statement. Note ifort compiles this just fine.
a very simple workaround fixes this example:
integer,parameter::dim=3
integer :: x(2),dimx=dim
if(dim.eq.1)write(*,*)x(dimx)
end
of course since its just a warning, and you know its not a problem, you can choose to ignore it too !
note the use of the parameter in the logical, in case the compiler feels like optimizing it later.
So what I may suggest is to use overloaded subroutines in order to process the data - then you would have generic behavior without the need to pass the dimension argument explicitly to the function(thus getting rid of the warning). And then I would recommend you to follow Holmz's advice regarding using all warnings during testing stage and then completely turning them off during production build (-w). For now I wasn't able to find an efficient way of suppressing this warning (apart from -w) - it seems that the check for array bounds is on by default and is not overridden -fno-bounds-check or -Wno-array-bounds. But overloaded functions can be a better solution to your problem, the implementation should look like this in this case:
module functions
implicit none
interface test_dim
module procedure test_func1d, test_func2d, test_func3d
end interface ! test_dim
contains
subroutine test_func1d(input1d)
real, intent(in) :: input1d(:)
print*, "DOING 1 DIM"
print*, "SHAPE OF ARRAY:", shape(input1d)
end subroutine test_func1d
subroutine test_func2d(input2d)
real, intent(in) :: input2d(:,:)
print*, "DOING 2 DIM"
print*, "SHAPE OF ARRAY:", shape(input2d)
end subroutine test_func2d
subroutine test_func3d(input3d)
real, intent(in) :: input3d(:,:,:)
print*, "DOING 3 DIM"
print*, "SHAPE OF ARRAY:", shape(input3d)
end subroutine test_func3d
end module functions
program test_prog
use functions
implicit none
real :: case1(10), case2(20,10), case3(30, 40, 20)
call test_dim(case1)
call test_dim(case2)
call test_dim(case3)
end program test_prog
And the output produced by this function looks like this:
DOING 1 DIM
SHAPE OF ARRAY: 10
DOING 2 DIM
SHAPE OF ARRAY: 20 10
DOING 3 DIM
SHAPE OF ARRAY: 30 40 20
I have been compiling a project with modules and subroutines in different files. Each subroutine written in separate file. The same for the modules. Then, I tested compiling these files separately to object files (-c) and than linking with the optimization flags, and also using cat to merge the entire source code and applying the same procedure to this single source file. What I found is that the executable generated by compiling the single file was about 40% faster than that generated by the multiple files, despite using exactly same flags for both.
I would like to know if anyone knows why it is happening, and if there is any flag on the Intel Fortran compiler that compiles multiple files as they were a single file.
As #chw21 requested, I created a small program showing the problem:
program main
use operators
implicit none
integer :: n
real(8), dimension(:,:), allocatable :: a, b, c
integer :: i,j,k
n = 1000
allocate(a(n,n), b(n,n), c(n,n))
call random_number(a)
call random_number(b)
do j = 1, n
do i = 1, n
do k = 1, n
!c(i,j) = c(i,j) + a(k,i) * b(k,j)
c(i,j) = add(c(i,j), mul(a(k,i), b(k,j)))
enddo
enddo
enddo
write(*,*) sum(c)
end program
with module:
module operators
contains
function add(a,b) result (c)
real(8), intent(in) :: a, b
real(8) :: c
c = a + b
end function
function mul(a,b) result (c)
real(8), intent(in) :: a, b
real(8) :: c
c = a * b
end function
end module
The idea is that these functions should normally get inlined, if the compiler knows that they are so extremely small. I did three tests with -O2:
complete source in a single file
split in two files
split in two files with -ipo (or -flto)
The results for ifort 13.0.0 and gfortran 5.2.0 on different machines are:
Test | 1. | 2. | 3.
---------+-------+-------+-------
ifort | 1.3s | 15.7s | 1.9s
gfortran | 1.1s | 3.7s | 1.1s
Unfortunately, I don't know why there is still a difference between the 1st and 3rd test with ifort ... I guess, a look at the generated code would shed some light on this issue.
Update: The times were measured by executing time ./a.out which resulted in stable times. Due to the standard compilation with ifort -O2, the maximum instruction set should be SSE2 (thus, no FMA), the processor supports upto SSE4a (Opteron 6128). An additional test on a recent Intel processor (upto AVX) showed similar results.
An important thing seems to be the lack of inlining and vectorization of the inner loop, which gets applied during IPO and single-file-compilation (see --opt-report). Additionally, there seem to be some differences concerning vectorization between IPO and single-file-compilation.
I wish to change the working directory in a Fortran 90 code. Is it possible to do this in a non compiler-specific way? Here is my code:
program change_directory
integer :: ierr
call system("mkdir -p myfolder/")
!call system("cd myfolder/") !doesn't work
ierr = chdir("myfolder")
if (ierr.NE.0) then
write(*,'(A)') "warning: change of directory unsuccessful"
end if
open(unit=33,file="myfile.txt",iostat=ierr)
if (ierr.EQ.0) then
write(unit=33,fmt='(A)') "Test message"
close(unit=33)
end if
end program change_directory
Clearly, using cd myfolder/ in a system call doesn't work. The Intel reference says I need to add 'use ifport'. There's no such mention in the GCC reference, though. Leaving out 'use ifport', I can compile the above code under ifort without any trouble. When I put it in, however, it won't compile with gcc (because gcc doesn't have the ifport module)--and not only that, it won't compile under Intel Fortran either--I'm getting the following error:
$ ifort change_dir.f90 -o change_dir
change_dir.f90(5): error #6552: The CALL statement is invoking a function subprogram as a subroutine. [SYSTEM]
call system("mkdir -p myfolder/")
---------^
compilation aborted for change_dir.f90 (code 1)
So my question is the following: is there a better way to do this? I'd like to keep my code as compiler-independent as possible. At the moment, I primary use gfortran/ifort and mpif90/mpiifort.
See also Is there any way to change directory using C language? . You can make your own interface to the chdir() POSIX call to be independent of the Intel's interface. On Windows it is similar.
module chdir_mod
implicit none
interface
integer function c_chdir(path) bind(C,name="chdir")
use iso_c_binding
character(kind=c_char) :: path(*)
end function
end interface
contains
subroutine chdir(path, err)
use iso_c_binding
character(*) :: path
integer, optional, intent(out) :: err
integer :: loc_err
loc_err = c_chdir(path//c_null_char)
if (present(err)) err = loc_err
end subroutine
end module chdir_mod
program test
use chdir_mod
call chdir("/")
call system("ls -l")
end
and when run
> gfortran chdir.f90
> ./a.out
celkem 120
drwxr-xr-x 2 root root 4096 15. říj 14.42 bin
drwxr-xr-x 5 root root 4096 15. říj 14.43 boot
...
On ifort it works too as it does on sunf90.
(Note: this relies on default character being the same as c_char. That is quite a safe assumption. If it is not the case the compiler will complain and a conversion has to be made.)
I've been sitting here for a while quite baffled as to why my debugger keeps displaying an error in my code when the program runs fine. There are three parts to a very simple program that is just reading in information from a file.
My code is broken into three Fortran files given below and compiled via
ifort -o test global.f90 read.f90 test.f90
global.f90:
module global
implicit none
integer(4), parameter :: jsz = 904
end module global
read.f90:
subroutine read(kp,q,wt,swt)
implicit none
integer(4) :: i, j
integer(4), intent(in) :: kp
real(8), intent(out) :: swt, q(kp,3), wt(kp)
swt = 0.0d0; q(:,:) = 0.0d0; wt(:) = 0.0d0
open(7,file='test.dat')
read(7,*) ! Skipping a line
do i = 1, kp
read(7,1000)(q(i,j),j=1,3), wt(i)
swt = swt + wt(i)
end do
close(7)
return
1000 format(3F10.6,1X,1F10.6)
end subroutine read
test.f90:
program test
use global
integer(4) :: i, j
real(8) :: tot, qq(jsz,3), wts(jsz)
call read(jsz,qq,wts,tot)
stop
end program test
The error I keep receiving is
Breakpoint 1, read (kp=904,
q=<error reading variable: Cannot access memory at address 0x69bb80>,
wt=..., swt=6.9531436082559572e-310) at read.f90:6
This error appears right when the subroutine of read is called. In other words, I'm adding a breakpoint at the read subroutine and running the code in gdb after the breakpoint is added. The program will continue to run as expected and give the correct outputs when I include write statements in the 'test' program. However, if I use the gdb print options I receive an error of 'Cannot access memory at address 0x69bb80' for array q only. All other arrays and variables can be displayed with no problems.
As I would like the read subroutine to be a stand alone subroutine and not necessarily use any global parameters, I have not used the global module and instead called the variable kp into the subroutine. I decided to test whether using the global module would help, and if I use jsz in place of kp, I do indeed remove the error. However, since this isn't my overall goal with the subroutine, I would hopefully like to figure out how to fix this without the use of the global module. (I also tried not using the global at all and setting the parameter variable of kp in the test.f90 program directly, but this also gives the error.)
Any insight on possible reasons for this error, or suggestions to try and fix the memory addressing issue would be greatly appreciated.
I think this is an issue specific to the ifort+gdb combination that is fixed with newer gdb versions. Here's a smaller example to reproduce the issue:
$ cat test.f90
subroutine bar(arg)
integer, intent(inout):: arg
print *, 'bar argument is', arg
arg = 42
end subroutine bar
program test
integer:: param
param = 3
call bar(param)
print *, 'post-bar param:', param
end program test
$ ifort -g -O0 -o test test.f90
$ gdb --quiet test
Reading symbols from /home/nrath/tmp/test...done.
(gdb) b 4
Breakpoint 1 at 0x402bd0: file test.f90, line 4.
(gdb) r
Starting program: /home/nrath/tmp/test
[Thread debugging using libthread_db enabled]
Breakpoint 1, bar (arg=#0x2aaa00000003) at test.f90:4
4 print *, 'bar argument is', arg
(gdb) p arg
$1 = (REF TO -> ( INTEGER(4) )) #0x2aaa00000003: <error reading variable>
(gdb) quit
$ gdb --version | head -1
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-60.el6_4.1)
However, if you compile with gfortran instead of ifort, or if you use GDB 7.7.1, it works fine.
Did you add the INTERFACE statement to the end of your programme?
You need it when you call a function that is not contained in the programme.