Search code examples
fortranopenmpblasintel-mklopenblas

Is that possible to let Fortran source code detect compiler flags?


The question is inspired by OpenMP with BLAS

The motivation is, I want the Fortran source code to be flexible to the complier options related to serial/parallel BLAS. I may specify -mkl=parallel for mkl or USE_OPENMP=1 for lopenblas in the Makefile. I may do make ifort or make gfortran or make blah blah to switch the libaries in the Makefile. But,

a) If I use -mkl=parallel in the Makefile, I need to set call mkl_set_num_threads(numthreads) in the source code,

b) If I use OpenBLAS with USE_OPENMP=1, I may need openblas_set_num_threads(num_threads) in the source code https://rdrr.io/github/wrathematics/openblasctl/man/openblas_set_num_threads.html#:~:text=threads%20to%20use.-,Details,t%20simply%20call%20R%27s%20Sys.

c) for the time being if there is only lblas and/or with -mkl=sequential, I have to manually configurate dgemm threads (as kind of block decomposition), regardless OMP_NUM_THREADS. That's ok, but I need to use if to control the source code goes in that way, if the source code has lines for a) and b)

The manually programming dgemm threads in c) is somehow universal. When I would like to exploit parallel blas from libraries, things can be complicated it seems such that I don't know how to switch in source code regarding the compiler options.

Addition, OMP_NUM_THREADS from enviroment file, .bashrc, is not preferable. (Sorry I should have mentioned this point earlier) The source code read an input file which specify the number of cores being used, and use omp_set_num_thread to set the targeted number of cores, than from the enviroment file.

Addition2, from my test on MKL, OMP_NUM_THREADS cannot surpress call mkl_set_num_threads. Namely, I have to specify call mkl_set_num_threads to work with -mkl=parallel flag.


Solution

  • There are at least two approaches to this.

    Preprocessor variables

    As explained in e.g. this question and this question, among others, you can pass variables from a Makefile directly to an appropriate preprocessor.

    For example, in the branches of the Makefile where you set -mkl=parallel you could also set -DMKL_PARALLEL. Then, in your source code you could have a block which looks something like

    #ifdef MKL_PARALLEL
      call mkl_set_num_threads(numthreads)
    #endif
    

    Provided you compile your code with an appropriate preprocessor, this allows you to pass arbitrary information from your Makefile to your source code.

    Separate files

    Instead of using a preprocessor, you can have multiple copies of the same file, each with a different set of options, and only compile the correct file for the project.

    A slightly nicer way of doing this is to have one module file, which is always the same regardless of options, and multiple submodules, each of which contains one set of options. This reduces the room for error arising from multiple files, and reduces compilation time if you need to change the options.