Skip to content

Commit

Permalink
docs: add how-to for OpenMP usage
Browse files Browse the repository at this point in the history
  • Loading branch information
gnikit committed Oct 8, 2023
1 parent 1617967 commit 22f2f63
Show file tree
Hide file tree
Showing 4 changed files with 103 additions and 1 deletion.
51 changes: 51 additions & 0 deletions pages/how-to/compute-pi-openmp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Computing PI with OpenMP

This is a simple example of how to use OpenMP with fpm.
It is an adapted version of the OpenMP example that can be found
[here](https://github.com/gjbex/Fortran-MOOC/blob/master/source_code/computing_pi/compute_pi_omp.f90) under a
[CC-BY-4.0](https://github.com/gjbex/Fortran-MOOC/blob/master/LICENSE) license.

The code approximates the value of PI by performing a parallelized version of
the midpoint rule for integration over a quarter of the unit circle.
The code is structured as follows:

```{literalinclude} ../../src/how-to/copmute-pi-openmp/app/main.f90
:language: fortran
:caption: app/main.f90
```

## Using OpenMP as a dependency

To use OpenMP in your project, you need to add the `openmp` dependency to your `fpm.toml` file:

```{literalinclude} ../../src/how-to/copmute-pi-openmp/fpm.toml
:language: toml
:caption: fpm.toml
:emphasize-lines: 4-5
```

OpenMP is a _built-in dependency_ (i.e. metapackage), which means the above
syntax needs to be used. To find out more about metapackages, see [](../spec/metapackages).

## Building and running the code

To build and run the code, one can use the following commands:

```{code-block} text
❯ fpm run
Project is up to date
Iterations: 10000, PI: 3.141391477611324
Took: 0.092s, with absolute error: 2.0E-04
```

And increasing the number of iterations for the approximation while
simultaneously enabling compiler optimizations with `--profile-release`

```{code-block} text
❯ fpm run --profile-release -- 1000000000
main.f90 done.
compute-pi-openmp done.
[100%] Project compiled successfully.
Iterations: 1000000000, PI: 3.141592651589789
Took: 3.511s, with absolute error: 2.0E-09
```
4 changes: 3 additions & 1 deletion pages/how-to/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

# How-To guides

:::{note}
This section contains practical guides and recipes for solving specific problems with fpm.

:::{toctree}
compute-pi-openmp
:::
41 changes: 41 additions & 0 deletions src/how-to/copmute-pi-openmp/app/main.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
program compute_pi_openmp
use, intrinsic :: iso_fortran_env, only: dp => real64, i8 => int64, real128
implicit none
integer(kind=i8) :: i, n_iterations
real(kind=dp) :: delta, x, pi
real(kind=dp) :: start, end

pi = 0.0_dp
n_iterations = get_iterations(10000_i8)
delta = 1.0_dp / n_iterations
x = 0.0_dp

call cpu_time(start)
!$omp parallel do default(none) private(x) shared(delta, n_iterations) reduction(+:pi)
do i = 1, n_iterations
x = i * delta
pi = pi + sqrt(1.0_dp - x**2)
end do
!$omp end parallel do
call cpu_time(end)

pi = 4.0_dp * pi / n_iterations
print "(A, I16, A, F25.15)", "Iterations: ", n_iterations, ", PI: ", pi
print "(A, F8.3, A, ES8.1)", "Took: ", end - start, "s, with absolute error: ", acos(-1.0_real128) - pi

contains

integer(i8) function get_iterations(default_iterations)
integer(kind=i8), intent(in) :: default_iterations
character(len=100) :: buffer, msg
integer :: stat

get_iterations = default_iterations
if (command_argument_count() >= 1) then
call get_command_argument(1, buffer)
read (buffer, fmt=*, iostat=stat, iomsg=msg) get_iterations
if (stat /= 0) stop msg
end if
end function get_iterations

end program compute_pi_openmp
8 changes: 8 additions & 0 deletions src/how-to/copmute-pi-openmp/fpm.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name = "compute-pi-openmp"
version = "0.1.0"

[dependencies]
openmp = "*"

[[executable]]
name = "compute-pi-openmp"

0 comments on commit 22f2f63

Please sign in to comment.