fpm icon indicating copy to clipboard operation
fpm copied to clipboard

Build-in dependencies for fpm: OpenMP

Open awvwgk opened this issue 5 years ago • 10 comments

OpenMP is probably one of the easiest non-fpm compatible dependency fpm could provide. OpenMP is usually shipped with the compiler. For the current scope of GCC we only have to add -fopenmp to both compile and link arguments and are done, therefore it might be a useful prototype to explore the usage of built-in dependencies for fpm.

Following the current scheme an empty table would do the trick and is flexible enough to allow customization for other build-in dependencies later.

[dependencies]
openmp = {}

Relevant discussion regarding package name conflicts: https://github.com/fortran-lang/fpm-registry/issues/8, in case a package wants to call itself openmp.

awvwgk avatar Sep 05 '20 07:09 awvwgk

I agree this is should be a simple area to prototype such features, however I'm not a fan of the proposed manifest syntax. IMO, this seems to be more of compiler feature that needs enabling rather than a 'dependency' that needs satisfying.

Perhaps:

[compiler]
openmp = true

Also in the same vein:

[compiler]
lto = true             # link-time optimisation
acc = true             # OpenACC support
fflags = "-fopt-info"  # Appended to built-in flags list
lflags = "-lblas"

fpm will then have a supported list of compilers for which it implements any compiler-specific syntax under the hood. What do you think?

LKedward avatar Sep 07 '20 10:09 LKedward

True, it usually feels like a compiler command when using it, but there is a lot automation for us hidden in the compiler.

I thought of it more like a dependency since it is handled in conda like one (see https://conda-forge.org/docs/maintainer/knowledge_base.html#openmp). Also meson is handling it usually as a dependency rather than a compiler command (see https://mesonbuild.com/Dependencies.html#openmp).

Having a dependency model that allows propagating linker and compiler flags would be well suited for OpenMP as well in fpm. OpenMP would be useful as simple prototype if dependencies require to export link or compile flags to a dependent project. Projects using OpenMP must propagate at least the linker flag, possibly also the library with the OpenMP implementation to dependent projects to allow correct linking.

awvwgk avatar Sep 07 '20 18:09 awvwgk

It would be good to get this implemented so that we can self-bootstrap Fortran fpm with parallel builds enabled.

I am however still opposed to the treatment of OpenMP as a dependency in the manifest syntax; OpenMP isn't just an additional library for linking, it changes the way the compiler behaves in processing sources and in generating code. Similarly the invocation flag and link libraries are different for each compiler. Hence why I think an entry like openmp=true in the existing [build] table is more appropriate (#112). What do other people think?

Having a dependency model that allows propagating linker and compiler flags would be well suited for OpenMP as well in fpm.

Agreed, but I see no reason to conflate the manifest syntax for OpenMP with that of package dependencies.

LKedward avatar Jan 04 '21 11:01 LKedward

I think we should get #112 working first, this would allow us to define flags on a per package basis (optimization) and global flags that propagate in the dependency tree (fast-math). Based on this we can easily implement OpenMP as either a build.openmp entry or a dependency.

awvwgk avatar Jan 04 '21 11:01 awvwgk

I am however still opposed to the treatment of OpenMP as a dependency in the manifest syntax; OpenMP isn't just an additional library for linking, it changes the way the compiler behaves in processing sources and in generating code. Similarly the invocation flag and link libraries are different for each compiler.

Keep in mind that OpenMP is versioned as well, how do we deal with the fact that a program requires OpenMP version 4.5 or newer if the compiler used only provides OpenMP 3.x?

Another important thing is linking against the OpenMP runtime, if you use LLVM and GCC toolchains on your system you can link GCC applications with the LLVMs OpenMP runtime library and vice versa, depending on the features used. Same holds true for Intel OpenMP which can safely be linked into GCC compiled application instead of the GCC OpenMP runtime library.

Creating an OpenMP dependency, which exports compiler flags to the dependent projects would allow to safely support various OpenMP implementation including versioning and also gives you the freedom to overwrite the OpenMP dependency by creating a mock fpm-package to export your special OpenMP setup.

awvwgk avatar Jan 04 '21 12:01 awvwgk

Can these cases not also be specified in the [build] table, e.g.:

[build]
openmp = true
openmp-version = "^4.5"
openmp-library = "iomp5"

We will already need logic for correctly exporting compiler options to dependents, why not use the same model for OpenMP?

Perhaps I am misunderstanding you; is your intention that there is no special code for handling OpenMP and that the OpenMP dependency is processed internally in exactly the same way as any other dependency?

LKedward avatar Jan 04 '21 12:01 LKedward

I would prefer to extend the current dependency model to support OpenMP on equal footing with normal fpm dependencies. With a solution for #112 we should be able to create an fpm package that will enable OpenMP support in its dependents.

Supporting OpenMP with this approach wouldn't require any special entries in build and allows to test if this is a suitable model for OpenMP before implementing a special shortcut with build.openmp in the package manifest. I'm not opposed to create a build.openmp entry, but I wouldn't make it the first step for supporting OpenMP.

awvwgk avatar Jan 04 '21 13:01 awvwgk

... we should be able to create an fpm package that will enable OpenMP support in its dependents.

Ah I see, I understand what you mean now. Thanks for explaining (and for your patience ;)). This is an elegant approach.

So a hypothetical default OpenMP package manifest might look something like this then:

name="OpenMP"

[build]
compile-args.gfortran= ["-fopenmp"] # append
compile-args.ifort= ["-qopenmp"]
# etc...

or, to introduce a possible general syntax, perhaps:

name="OpenMP"

[build]
[[compiler-arg]]
gfortran= ["-fopenmp"]
ifort= ["-qopenmp"]
# ...
export = "link"         # export arg to linker command only
# export = "dependents" # export arg up to dependent packages only
# export = "all"        # export arg to entire project

LKedward avatar Jan 04 '21 14:01 LKedward

@perazz

minhqdao avatar Feb 23 '23 15:02 minhqdao

Thank you for tagging me on this issue - I'm definitely willing to help.

Can you please help me understand what you're suggesting to accomplish @LKedward @awvwgk :

  • openmp is never really built as a library but I understand one may want to use the LLVM vs the GNU implementation. Do the two libraries have the same API?

  • Then I would see openmp as a "metapackage", i.e. represent it as a special dependency that has no source or object files, but that propagates additional compile flags (-fopenmp) from the first branch it's used into upstream.

  • I would start simple and just enable each compiler's own openmp library where available.

Does that make sense? Or, you were thinking to use openmp as a testbench to propagate package-specific (possibly source-specific) compiler flags?

perazz avatar Mar 01 '23 15:03 perazz