是否可以让 Fortran 源代码检测编译器标志?
Posted
技术标签:
【中文标题】是否可以让 Fortran 源代码检测编译器标志?【英文标题】:Is that possible to let Fortran source code detect compiler flags? 【发布时间】:2022-01-19 05:30:52 【问题描述】:这个问题的灵感来自OpenMP with BLAS
动机是,我希望 Fortran 源代码对与串行/并行 BLAS 相关的编译器选项具有灵活性。我可以在Makefile
中为mkl
指定-mkl=parallel
或为lopenblas
指定USE_OPENMP=1
。
我可以使用make ifort
或make gfortran
或make blah blah
来切换Makefile
中的库。
但是,
a) 如果我在Makefile
中使用-mkl=parallel
,我需要在源代码中设置call mkl_set_num_threads(numthreads)
,
b) 如果我使用OpenBLAS
和USE_OPENMP=1
,我可能需要在源代码中使用openblas_set_num_threads(num_threads)
https://rdrr.io/github/wrathematics/openblasctl/man/openblas_set_num_threads.html#:~:text=threads%20to%20use.-,Details,t%20simply%20call%20R%27s%20Sys.
c) 暂时如果只有lblas
和/或-mkl=sequential
,我必须手动配置dgemm
线程(作为一种块分解),不管OMP_NUM_THREADS
。没关系,但我需要使用if
来控制源代码以这种方式运行,如果源代码有 a) 和 b) 行
c) 中的手动编程dgemm
线程在某种程度上是通用的。当我想利用库中的并行 blas 时,事情可能会很复杂,以至于我不知道如何切换有关编译器选项的源代码。
添加环境文件中的OMP_NUM_THREADS
.bashrc
是不可取的。 (对不起,我应该在前面提到这一点)源代码读取指定正在使用的核心数量的输入文件,并使用omp_set_num_thread
设置目标核心数量,而不是从环境文件中。
Addition2,根据我对MKL
的测试,OMP_NUM_THREADS
不能超过call mkl_set_num_threads
。也就是说,我必须指定 call mkl_set_num_threads
才能使用 -mkl=parallel
标志。
【问题讨论】:
有什么原因不能只设置环境变量OMP_NUM_THREADS
?如果没有,您可能需要某种形式的预处理。
this question 有一些关于将变量从 makefile 传递到 Fortran 预处理器的信息。
同意@IanBush:大多数现代 BLAS 库都遵循 OpenMP 环境变量。一般不需要设置源中的线程数。
关于我不得不处理的OMP_NUM_THREADS
方法的唯一陷阱是当变量设置为 not 时大多数实现使用所有内核的愚蠢默认设置.在这种情况下,您可以使用get_environment_variable
来检查OMP_NUM_THREADS
,如果不存在,请使用omp_set_num_threads
将默认线程数设置为合理的值,即1 - 所有这些都是可饮用的。
我真的不明白你的意思。如果 MKL 或 OPENBLAS 不可用,您是否拥有自己的 openmp 线程 BLAS?如果是这种情况,OMP_NUM_THREADS
将受到尊重 - 使用 that 作为设置您使用的线程数的主要方式,如果您对OMP_NUM_THREADS
的情况感到偏执,请仅使用omp_set_num_threads
没有设置,即大多数代码从不关心它。总之,如果您使用环境变量,几乎总是可以编写出不需要需要预处理的代码,而与 BLAS 实现无关。
【参考方案1】:
至少有两种方法。
预处理器变量
如在例如this question 和 this question 等,您可以将变量从 Makefile 直接传递到适当的预处理器。
例如,在您设置-mkl=parallel
的Makefile 分支中,您也可以设置-DMKL_PARALLEL
。然后,在您的源代码中,您可以有一个类似于
#ifdef MKL_PARALLEL
call mkl_set_num_threads(numthreads)
#endif
如果您使用适当的预处理器编译您的代码,这允许您将任意信息从您的 Makefile 传递到您的源代码。
单独的文件
您可以不使用预处理器,而是拥有同一个文件的多个副本,每个副本都有一组不同的选项,并且只为项目编译正确的文件。
一个更好的方法是有一个模块文件,无论选项如何,它总是相同的,以及多个submodules,每个都包含一组选项。这减少了由多个文件引起的错误空间,并在您需要更改选项时减少了编译时间。
【讨论】:
以上是关于是否可以让 Fortran 源代码检测编译器标志?的主要内容,如果未能解决你的问题,请参考以下文章
用于 Ivy Bridge 架构的 GNU Fortran 编译器优化标志
cmake可以自动添加fortran预处理器-cpp标志吗?