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

Not including mkl.fi

Daniel_L_
Beginner
1,856 Views

I'd actually like to ask about why I'm able to compile this example program. Obviously, this isn't an issue for the system I'm on right now, but I hope to not run into compiling issues when I'm working on a different system. The example program is very simple, it calls the LAPACK axillary function dzsum1. Here it is:

program dzsum1_test

integer, parameter :: WP = selected_real_kind(15,307)
complex(WP) :: a(5)
real(WP) :: res
real(WP) :: dzsum1
external :: dzsum1

a(1) = cmplx(1.d0,1.d0)
a(2) = cmplx(1.d0,1.d0)

res = dzsum1(5,a,1)
write(*,*) res

end program

Now, I can compile and run this program successfully with

ifort dzsum1_test.f90 -mkl
  1. Why does this work? Specifically, why don't I need to put
    include "mkl.fi"
    anywhere in my program? That is an include file for this function that's listed in the MKL Reference and I thought that I would need to make sure dzsum1 was declared in my file before I declared it as external. Whether I put the include line before or after the program statement, the compilation doesn't work. I'm assuming this has something to do with the behavior of "-mkl" but I can't find anything in the MKL user guide, MKL reference, or ifort man pages that talk about this switch doing anything except linking libraries, which I thought wasn't sufficient for an external declaration.
  2. If it is in fact the "-mkl" switch that makes all this possible, is there a way to print out what it's doing?

Sorry for such a simple question, any help would be appreciated.

0 Kudos
1 Solution
mecej4
Honored Contributor III
1,856 Views

The answer is quite simple. You used a straightforward F-77 style call, and the types and kinds of the subroutines just happened to be right  -- they match the declarations in the source code of dzsum1, if you care to check at https://software.intel.com/en-us/node/521193. In such cases (we always write correct code, don't we?) the subroutine interface is not necessary, and the "implicit interface" is correct.

Now try changing the last argument from 1 to 1.0, and run the modified (and now incorrect) program with and without the interface file included.

The -mkl switch makes it easy for the compiler to search for files needed to compile and link source files that use MKL, and is not directly related to your question. You can try the -# flag, but the verbose output will probably not help you.

View solution in original post

0 Kudos
4 Replies
mecej4
Honored Contributor III
1,857 Views

The answer is quite simple. You used a straightforward F-77 style call, and the types and kinds of the subroutines just happened to be right  -- they match the declarations in the source code of dzsum1, if you care to check at https://software.intel.com/en-us/node/521193. In such cases (we always write correct code, don't we?) the subroutine interface is not necessary, and the "implicit interface" is correct.

Now try changing the last argument from 1 to 1.0, and run the modified (and now incorrect) program with and without the interface file included.

The -mkl switch makes it easy for the compiler to search for files needed to compile and link source files that use MKL, and is not directly related to your question. You can try the -# flag, but the verbose output will probably not help you.

0 Kudos
mecej4
Honored Contributor III
1,856 Views

The include file 'mkl.fi' includes another eleven include files, so it takes the compiler a while to process all the interfaces. However, there is a simple fix for this. Create a three-line Fortran source file containing

      module mymkl
      include 'mkl.fi'
      end module mymkl

and compile this file. A module file, 'mymkl.mod', will be generated. Place this module file in a place along the include/module search path.

That having been done, in your sources, wherever you would include mkl.fi, write "USE MYMKL" instead. Note that the USE statement should be placed before any declarations.

0 Kudos
Daniel_L_
Beginner
1,856 Views

That is perfect. Thank you so much!

I remember using the same trick when I was using fftw, but the importance of it didn't hit me then. For anyone else reading this in the future, here is a (very) simple project setup with a makefile that will make this whole process streamlined. Simply type make to compile the project, the module will only be compiled if it needs to be. Type "make clean" to delete your program executable, and "make distclean" to delete your program executable along with the .mod file and module object file.

dzsum1_test.f90

program dzsum1_test

use mymkl

integer, parameter :: WP = selected_real_kind(15,307)
complex(WP) :: a(5)
real(WP) :: res

a(1) = cmplx(1.d0,2.d0)
a(2) = cmplx(1.d0,1.d0)

res = dzsum1(5,a,1)
write(*,*) res

end program

mymkl.f90

module mymkl
include 'mkl.fi'
end module mymkl

Makefile

all: mymkl.mod
	ifort dzsum1_test.f90 -mkl

mymkl.mod:
	ifort -c mymkl.f90

clean:
	rm a.out

distclean:
	rm mymkl.mod mymkl.o a.out

 

0 Kudos
Daniel_L_
Beginner
1,856 Views

Yikes! Thanks so much for the response. I'll be sure to use the interface file :) The compile takes much longer now though, I don't suppose there is a way to speed this up?(see edit below) I know that for many BLAS and LAPACK functions there is a precompiled fortran90 module that works well, but I don't think this includes anything for dzsum1.

I think I was thrown off by the dot_main example in the MKL reference guide, which seems like it could benefit from an interface file (either mkl.fi or mkl_blas.fi). I think I have a better grasp of what the interface file is for now -- if I'm understanding it correctly, it's not to provide the actual functions, but just information for the compiler about the arguments and return values of the function that's been linked in a library by "-mkl".

Thanks again!

Edit: It seems like this is the way to write the program in the original post that will compile the fastest and still have an interface file (much faster way in reply to this post). This include file is listed with the general LAPACK docs, but the larger include file is listed for the actual function.

program dzsum1_test

include "mkl_lapack.fi"

integer, parameter :: WP = selected_real_kind(15,307)
complex(WP) :: a(5)
real(WP) :: res

a(1) = cmplx(1.d0,1.d0)
a(2) = cmplx(1.d0,1.d0)

res = dzsum1(5,a,1)
write(*,*) res

end program

 

0 Kudos
Reply