You have a number of problems with your code:
In Fortran you can't mix executable statements such as call omp_set_num_threads(4)
with the variable declarations. Actually this is probably the cause of most of your (unreported) errors
Don't use kind = 8
. It is not portable, not required to be supported by your compiler, and may not do what you expect. I suggest learning about Fortran kinds, and see the code below for a better way - and also how you should deal with constants.
You are misusing omp parallel do
. In fact I suggest you never use this construct, I think it is a major source of confusion for beginners in the language, and in fact a mistake it is included in OMP at all. Why do I think this? Well it is important to understand that there are two stages when parallelizing via OpenMP. First you create the (non-master) threads with !$omp parallel
. The second stage is to divide the work up between the threads with a worksharing construct such as !$omp do
. The method you are using conflates the two, and blurs this important separation which in my experience leads to confusion and hence incorrect and inefficient code. I strongly recommend you always separate the two stages in your code - as I have done below.
I would also recommend you use default( none )
for scoping variables in the parallel region, it forces you to think about whether a variable should be shared or private, and also to avoid call omp_set_num_threads
and use the environment variable OMP_NUM_THREADS instead, as you can then change the number of threads without having to recompile.
Fixing these leads me to the following code, which I think does what you want:
ijb@ijb-Latitude-5410:~/work/stack$ cat omp.f90
Program test
Use iso_fortran_env, Only : wp => real64, stdout => output_unit
!$ use omp_lib
Implicit None
Integer :: i
Integer, Parameter :: dimen = 5
! Note
! 1) Kind = 8 is not portable and should not be used
! 2) Real constants are single precision unless otherwise specified
Real (kind = wp), Dimension(dimen, dimen) :: tstarr = 0.0_wp
!.....................................................................
! Later I will have to fill the elements of the following matrix in the same way
! real (kind = wp), dimension(:,:), allocatable :: tstarr2
! allocate(tstarr2(2 * dimen, 2 * dimen))
!.....................................................................
! Note in Fortran executable statements can not be mixed with declarations
! However I wouldn't do it this way - use the environment variable OMP_NUM_THREADS, you don't have
! to recompile just to change the number of threads. Hence I have commented it out.
!!!$ call omp_set_num_threads(4)
! First create the threads. I also strongly recommend default( none )
!$omp parallel default( none ) shared( tstarr ) private( i )
! Report how many threads we are using
!$omp single
!$ Write( stdout, '( "Using ", i0, " threads" )' ) omp_get_num_threads()
!$omp end single
! Now share out the work for each loop
!$omp do
Do i = 1, dimen
tstarr(i,i) = 3.0_wp
End Do
!$omp end do
!$omp do
Do i = 1, dimen - 1
tstarr(i + 1, i) = 2.0_wp
tstarr(i, i + 1) = 2.0_wp
End Do
!$omp end do
!$omp do
Do i = 1, dimen - 2
tstarr(i + 2, i) = 4.0_wp
tstarr(i, i + 2) = 4.0_wp
End Do
!$omp end do
!$omp do
Do i = 1, dimen - 3
tstarr(i + 3, i) = 5.0_wp
tstarr(i, i + 3) = 5.0_wp
End Do
!$omp end do
! And end the parallel region
!$omp end parallel
! Report the matrix - prettily
Do i = 1, dimen
Write( stdout, '( *( f3.1, 2x ) )' ) tstarr(i,:)
End Do
End Program test
ijb@ijb-Latitude-5410:~/work/stack$ gfortran-12 --version
GNU Fortran (GCC) 12.2.0
Copyright © 2022 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
ijb@ijb-Latitude-5410:~/work/stack$ gfortran-12 -fopenmp -Wall -Wextra -fcheck=all -std=f2018 -Werror -g omp.f90
ijb@ijb-Latitude-5410:~/work/stack$ export OMP_NUM_THREADS=4
ijb@ijb-Latitude-5410:~/work/stack$ ./a.out
Using 4 threads
3.0 2.0 4.0 5.0 0.0
2.0 3.0 2.0 4.0 5.0
4.0 2.0 3.0 2.0 4.0
5.0 4.0 2.0 3.0 2.0
0.0 5.0 4.0 2.0 3.0
ijb@ijb-Latitude-5410:~/work/stack$ ./a.out
Using 4 threads
3.0 2.0 4.0 5.0 0.0
2.0 3.0 2.0 4.0 5.0
4.0 2.0 3.0 2.0 4.0
5.0 4.0 2.0 3.0 2.0
0.0 5.0 4.0 2.0 3.0
ijb@ijb-Latitude-5410:~/work/stack$ export OMP_NUM_THREADS=12
ijb@ijb-Latitude-5410:~/work/stack$ ./a.out
Using 12 threads
3.0 2.0 4.0 5.0 0.0
2.0 3.0 2.0 4.0 5.0
4.0 2.0 3.0 2.0 4.0
5.0 4.0 2.0 3.0 2.0
0.0 5.0 4.0 2.0 3.0
ijb@ijb-Latitude-5410:~/work/stack$ ./a.out
Using 12 threads
3.0 2.0 4.0 5.0 0.0
2.0 3.0 2.0 4.0 5.0
4.0 2.0 3.0 2.0 4.0
5.0 4.0 2.0 3.0 2.0
0.0 5.0 4.0 2.0 3.0
ijb@ijb-Latitude-5410:~/work/stack$ ./a.out
Using 12 threads
3.0 2.0 4.0 5.0 0.0
2.0 3.0 2.0 4.0 5.0
4.0 2.0 3.0 2.0 4.0
5.0 4.0 2.0 3.0 2.0
0.0 5.0 4.0 2.0 3.0
ijb@ijb-Latitude-5410:~/work/stack$