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

Conditional Compilation for different versions of MKL

Angus_M_
Beginner
391 Views

Hi,

I would like to be able to compile the same source code on platforms with different versions of MKL.  I have come up against several problems:

1.  The compiler will not accept an "include" directive before a "use" statement.  I therefore cannot include the header file mkl.fi and then use values from it to select which library calls to make.  I read about making a new module to wrap the include statement here:  https://software.intel.com/en-us/forums/intel-fortran-compiler-for-linux-and-mac-os-x/topic/534697

2.  Using the separate module approach, I came up with some preprocessor directives which would determine which library calls to make according to which compiler/MKL version was being used.  The macros didnt seem to be defined using this approach though.  Code is below:

A little module which has the include in it

module MKLVersion
include '/opt/intel/mkl/include/mkl.fi'
end module MKLVersion


And then the calling code

use MKLVersion
 
!DEC$ IF DEFINED (INTEL_MKL_VERSION)
use MKL95_LAPACK, only : ggevx, geevx, sygvd
!DEC$ END IF

The calling code is in a module, and it doesnt make the call to use lapack. 

I would be grateful for any information about how I might be doing this wrong, or if there is a better approach to getting what I want. 

 

Thanks, Angus.

0 Kudos
6 Replies
Yuan_C_Intel
Employee
391 Views

Hi, Angus

It seems you are mixing the F77 routine header and F95 interfaces.

What's MKL version you used? I don't think there's a MKL95_LAPACK module in composer edition 2016. Could you try use module lapack95 instead?

USE lapack95, ONLY: GGEVX, SYGVD

You can find more examples calling those f95 interfaces from installation folder: mkl/examples

Hope this helps.

Thanks.

0 Kudos
Angus_M_
Beginner
391 Views

Hi Yuan,

Thank you for replying.  What you said is correct - my code compiles if I call "lapack95" without the DEC directives.  However, my issue is that INTEL_MKL_VERSION seems not to be defined - if I change the snippet above to use lapack95 it still doesn't compile because the call gets ignored.   Am I doing something wrong or is it not supposed to work in the way I am trying to use it?

 

Thanks, Angus

0 Kudos
Steven_L_Intel1
Employee
391 Views

Preprocessor symbols aren't inherited through USE. Why can't you do the conditional use inside your "MKLVERSION" module?

0 Kudos
Angus_M_
Beginner
391 Views

Hi Steve, and thank you for your reply.

I didn't realise that the preprocessor symbols are not inherited through USE.  I have been trying to get the conditional USE statements to work in the MKLVERSION module but a similar problem persists: the INTEL_MKL_VERSION macro seems not to be defined.  When I make the library call in the MKLVERSION module on its own it works.  The following does not work:

module MKLVersion

#ifdef INTEL_MKL_VERSION
use LAPACK95, only : ggevx, geevx, sygvd
#endif

include '/opt/intel/mkl/include/mkl.fi'

end module MKLVersion

So what is happening here?  I know the GNU compiler says it effectively replaces an include statement with the source text the statement references.  I tried substituting the code in manually - no dice.  Now that I have moved the header file code into my module, if I move the statement which defines INTEL_MKL_VERSION above the definition check then it works.  Presumably because the include statement is after the definition check then the macro isn't defined until after the check? 

And if that is the case, then is it all possible to:

  1. get the version number of MKL
  2. use the version number to make a decision about which library call to make
  3. execute a USE statement to call the correct library

My experience so far tells me no - compilation will abort if a USE statement is present after an include statement.  The header file containing the version number has to be included in the source code before any USE statements can be chosen, and this all combines to create a catch 22.  I also feel like this is the kind of thing which must have come up before at some point, and which might have a workaround.

Thanks, Angus

0 Kudos
Steven_L_Intel1
Employee
391 Views

You're right that the order of definitions matter. It's not that USE after INCLUDE is itself a problem, but that the file being included contains statements (INTERFACE) not permitted to come before a USE.

Is there a way to solve this without needing to know the MKL version? For example, you could create your own mkl_lapack95 module that does a USE LAPACK95 and put it in a directory at the end of the -I (Include) list. If compiled on a system with the old MKL, that version's module will get picked up, otherwise yours will be.

I am disappointed that MKL keeps changing its API in incompatible ways from release to release. As a long-time library developer (going back into the 1970s), that's anathema to me.

0 Kudos
Angus_M_
Beginner
392 Views

Hi Steve,

Thanks for your replies, here and on SO (http://stackoverflow.com/questions/39251927/can-i-do-conditional-selection-of-use-statements-using-preprocessor-directives-w/39347871#39347871).  I found out from an old intel article (https://software.intel.com/en-us/articles/blas-and-lapack-fortran95-mod-files) that there are library calls compatible with older and newer versions of MKL:

"Notes:
     *  f95_precision.mod, mkl95_lapack.mod and mkl95_precision.mod files will be removed in one of the future releases. The current version supports two USE statements - so you can choose or "USE MKL95_LAPACK" or " USE LAPACK95 ". For the future compatibility we recommend using "USE LAPACK95" statement."

 After getting an older version of mkl running in a docker container (which also took a while to figure out), I found that I can just replace USE MKL95_LAPACK with USE LAPACK95.  I agree with your sentiment on changing API compatibility.  Hopefully 2017 won't bring another reshuffle. 

 

Thanks, Angus

0 Kudos
Reply