1

I am writing a fortran code for benchmarking three loop kernels:

       program Kernel_benchmark

       implicit none

       double precision,dimension (:),save,allocatable:: a,b,c,d,x,y
       double precision s
       double precision,dimension (:,:),save,allocatable:: mat
       double precision wcs,wce,ct,runtime, total
       integer k,iter,r,i,j,N


       do k = 3, 20
          N = INT(2.5**k)
          allocate (a(N),b(N),c(N),d(N))
          do i=1,N
             a(i) = 1.2
             b(i) = 1.2
             c(i) = 1.2
             d(i) = 1.2
          end do
          iter = 1
          runtime = 0.0
          do while(runtime < 0.2)
            call timing(wcs,ct)
            do r =0, iter
                    do i=1,N
                            a(i) = b(i) + c(i) * d(i)
                    end do
                    if(a(ISHFT(N,-1)) < 0.0) then
                             call dummy(a)
                    end if
            end do
            call timing(wce,ct)
            runtime = wce - wcs
            iter = iter * 2
        end do
        iter = iter / 2
        open(unit=1, file = 'vector_triad.dat',status = 'unknown')
        write(1,*) N, (N * iter* 2) / (runtime * 1e-6)
        close(1)
        deallocate(a,b,c,d)
     end do

     do k = 3, 20
       N = INT(2.5**k)
       allocate(a(N))
       do i = 1, N
            a(i) = 1.2
       end do
       s = 2.2
       iter = 1
       runtime = 0.0
    do while(runtime < 0.2)
            call timing(wcs,ct)
            do r = 0, iter
                    do i = 1, N
                            a(i) = s * a(i)
                    end do
                    if(a(ISHFT(N,-1)) < 0.0) then
                             call dummy(a)
                    end if
            end do
            call timing(wce,ct)
            runtime = wce - wcs
            iter = iter * 2
    end do
    iter = iter / 2
    open (unit = 2, file = 'vector_update.txt', status = 'unknown' )
    write(2,*) N, (N * iter) / (runtime * 1e-6)
    close(2)
    deallocate(a)
  end do

  do k = 10, 22
      N = INT(1.5**k)
      allocate (mat(N,N),x(N),y(N))
      do i = 1, N
            do j = 1, N
                    mat(i,j) = 1.2
            end do
            y(i) = 1.2
            x(i) = 1.2
      end do
      iter = 1
      runtime = 0.0
      do while(runtime < 0.2)
            call timing(wcs,ct)
            do r = 0, iter
                    do i = 1, N
                            y(i) = 0.0      
                            do j = 1, N
                                    y(i)     = y(i) + (mat(i,j) * x(i))
                            end do
                    end do
                    if(y(ISHFT(N,-1))< 0.0) then
                            call  dummy(y)
                    end if
            end do
            call timing(wce,ct)
            runtime = wce - wcs
            iter = iter * 2
      end do
      iter = iter / 2
      open (unit = 3, file = 'matrix_vector.txt', status ='unknown')
      write(3,*) N, (2 * N * N * iter) / (runtime * 1e-6)
      close(3)
      deallocate(mat,x,y)
    end do

end program Kernel_benchmark

The dummy function I have written inside a C source file as follows

#include "dummy.h"

void  dummy(double *array){
    printf ("Well if its printing this then you're pretty much screwed.");
}

and dummy.h simply contains the function prototype.

I made an dummy.o object file and I'm trying to link it with my fortran source code using an intel ifort compiler. Unfortunately, I'm getting an error In function MAIN__':bench.f90:(.text+0x8ca): undefined reference todummy_'

every time the dummy function is called. Any suggestion? Thanks in advance.

vaultah
  • 44,105
  • 12
  • 114
  • 143
gmajal
  • 51
  • 1
  • 7

3 Answers3

3

The modern way to interface with Fortran is the interoperability with C and the iso_c_binding module, as discussed many times on this site.

Calling a FORTRAN subroutine from C

https://stackoverflow.com/search?tab=votes&q=iso_c_binding

Community
  • 1
  • 1
3

Inside the Fortram program, the symbol dummy is taken to be a subroutine with an implicit interface. Naturally the Fortran compiler things that subroutine will be a Fortran subroutine and will arrange argument passing, linker name mangling, etc appropriately.

Because dummy procedure is a C function and not a Fortran subroutine, problems ensure.

If the Fortran compiler is explicitly told that the dummy symbol is a C function, then it will make the appropriate changes. In the specification part of your main program:

INTERFACE
  SUBROUTINE dummy(array) BIND(C, NAME='dummy')
    IMPLICIT NONE
    DOUBLE PRECISION :: array(*)
  END SUBROUTINE 
END INTERFACE

Robust code would further set the kind of the array argument appropriately.

IanH
  • 21,026
  • 2
  • 37
  • 59
0

If you use GNU compilers, note that the name mangling is a little bit different for C and Fortran. If your fortran programm call subroutine xyz then the corresponding C subroutine should be named xyz_.

So in your case it is enough to rename dummy into dummy_ in the C sources. You may also need to link with -lg2c if I remember correctly.

begemotv2718
  • 868
  • 6
  • 14
  • I'm using an intel Ifort compiler, but let me try the compiler switch that you have suggested maybe there's a problem in linking. – gmajal Apr 29 '13 at 17:44
  • Are you sure that's a correct switch because my compiler doesn't seem to recognize it? I'm using it like icc -O3 -xHost -fno-alias dummy.c -lg2c is that correct? – gmajal Apr 29 '13 at 17:53
  • Well, I answered about gcc compiler, not an intel one. Hower, for intel compiler you still need to add the underscore in the C source. Using -lg2c may be not necessary (but here I'm not sure). You can also try to do all the linking with the fortran compiler, not C compiler, then you do not need -lg2c for sure. – begemotv2718 Apr 29 '13 at 18:05
  • I have tried changing the name of the function as well but it still doesn't seem to work. I checked out some example problems of this sort,this error might happen due to have spelling errors and I checked my code for them but everything so far seems consistent. – gmajal Apr 29 '13 at 18:07
  • Perhaps I might have a problem with linking. This is what I'm trying to do so far: 1) I make an object file dummy.o: icc -O3 -xHost -fno-alias dummy.c -c 2) Then I'm trying to link them with the fortran code as follows: ifort -O3 -xHost -fno-alias bench.f90 dummy.o timing.o -o bench Maybe I don't fully understand what you're trying to say but instead of -o do you mean I use -lg2c or is the above line correct? – gmajal Apr 29 '13 at 18:11
  • Well, if you changed the name of the `dummy` function to `dummy_` but still have the same error, please check if you recompiled the object file dummy.o correctly, may be the problem is there. Your compiler options looks correct to me. – begemotv2718 Apr 29 '13 at 18:22
  • You may use `nm` program on the object files to check what symbols are defined inside them. Try to run `ifort -O3 -xHost -fno-alias bench.f90 -c` and then run `nm bench.o`. It should display the list of unreferenced symbols in the object file (You will have something like `U dummy_` in the output. Then make sure that `nm dummy.o` defines exactly the same symbol (you should have something like `T dummy_`) in the output. – begemotv2718 Apr 29 '13 at 18:36
  • Thanks a lot for your help, my code is compiling now. The nm program was useful. I was supposed to write the dummy function inside the fortran code without the underscore character and inside my c code I defined two functions dummy and dummy_, where dummy_ simply calls dummy. – gmajal Apr 29 '13 at 19:36