1

我正在编写一个用于对三个循环内核进行基准测试的 fortran 代码:

       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

我在 C 源文件中编写的虚拟函数如下

#include "dummy.h"

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

dummy.h 只包含函数原型。

我制作了一个 dummy.o 目标文件,并尝试使用英特尔 ifort 编译器将其与我的 fortran 源代码链接。不幸的是,我在函数MAIN__':bench.f90:(.text+0x8ca): undefined reference todummy_ 中遇到错误

每次调用虚拟函数时。有什么建议吗?提前致谢。

4

3 回答 3

3

与 Fortran 交互的现代方式是与 C 和iso_c_binding模块的互操作性,正如本网站多次讨论的那样。

从 C 调用 FORTRAN 子例程

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

于 2013-04-29T21:12:59.287 回答
3

在 Fortram 程序中,符号dummy被视为具有隐式接口的子程序。自然,Fortran 编译器的子程序将成为 Fortran 子程序,并将适当地安排参数传递、链接器名称修改等。

因为dummy过程是 C 函数而不是 Fortran 子例程,所以肯定会出现问题。

如果 Fortran 编译器被明确告知虚拟符号是 C 函数,那么它将进行适当的更改。在主程序的规范部分:

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

健壮的代码将进一步适当地设置数组参数的类型。

于 2013-04-29T21:16:11.817 回答
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.

于 2013-04-29T17:35:27.080 回答