0

Is it possible to assign a variable once and only once at the start of a loop iteration via some kind of pattern in Fortran? Similar to the pseudocode below. What I have now is an If statement that checks if a flag is set and if it is we execute the if statement. Then we unset it, since my program is parallel I would like to avoid conditional branching in my innermost loop. From what I have seen it is possible to do in C++, but I wonder if I can achieve the same thing in Fortran somehow.

What I am looking for:

!$OMP DO PRIVATE(variable)
DO i = 0, N = 100000

<Set Variable to a fixed value once and only once at the start of the iteration>

<CODE>

END DO
!$END OMP DO

What I have

!$OMP DO PRIVATE(variable)
DO i = 1, N = 100000 

    IF (FLAG_IS_SET) THEN
       <Set variable>
       <UNSET_THE_FLAG>
    END IF

    <CODE>

END DO
!$END OMP DO
JKRT
  • 1,179
  • 12
  • 25
  • Why cannot you set the variable right before you enter the loop? – Dima Chubarov May 02 '17 at 15:06
  • I do not know how many threads I have, and my constant depends on the i value generated by the !$OMP DO directive. Thus I cannot know what value to assign before the directive is executed. – JKRT May 02 '17 at 15:07
  • suggest you edit the question title to indicate this is an openmp question – agentp May 02 '17 at 15:53
  • 3
    Firstly apologies, I don't know much about openmp so could be talking rubbish. You don't have `PARALLEL` in your openmp statement so have you already created the `!$OMP PARALLEL` region first and if so shouldn't you actually know how many threads you have before you enter the loop (allowing you to set the variable before the loop)? Or is it that the variable depends both on the number of threads and how the loop is "chunked"? If so are you using the default (static?) schedule? – d_1999 May 02 '17 at 16:21
  • Does the firstprivate clause help? http://stackoverflow.com/questions/15304760/how-are-firstprivate-and-lastprivate-different-than-private-clauses-in-openmp – Ian Bush May 02 '17 at 18:10
  • The variable I set is the index of the loop - 1. For each thread that is generated. So what I would need to do to move it outside my loop is to get the index of the specific start of the range. However from my understanding The OMP DO directive generates these values. It might be very well be so that there is exist no Fortran construct for what I am aiming to do. – JKRT May 02 '17 at 19:02
  • 2
    So it's essentially the number of the first iteration assigned to each thread by the OMP run time? If so it's as you have above, have a private flag and use the value of that to detect the first iteration assigned to the thread. – Ian Bush May 02 '17 at 19:51
  • Yes. My solution works, if it is like you say I will keep my flag construct. – JKRT May 02 '17 at 20:08
  • Maybe you can post your solution. – Holmz May 03 '17 at 00:37
  • If you have a C++ code that does what you want then please show it because I don§t understand what you want to do. – Vladimir F Героям слава May 03 '17 at 09:10

2 Answers2

2

A simple solution is manually work-sharing the iterations across threads. Assuming that 100000 is multiple of n_threads:

!$OMP PARALLEL PRIVATE(variable)
i_thread = omp_get_thread_num()
n_threads = omp_get_num_threads()
chunk_size = 100000 / n_threads
i_start = i_thread * chunk_size + 1
<Set variable>
DO i = i_start, i_start + chunk_size - 1
    <CODE>
END DO
!$OMP END PARALLEL

It avoids the conditional branching in the innermost loop and it is probably close to what the compilers do with the static scheduling.

Franz
  • 534
  • 3
  • 8
  • 1
    If you want to go this way an easier and more OMP-like in style method would be to use static scheduling for the loop. Then you know a priori exactly which iterations are mapped to which thread. – Ian Bush May 03 '17 at 06:53
  • 1
    To be guaranteed about the _thread_ vs _iterations_ mapping, static schedule requires chunk_size to be specified. Otherwise, according to the OpenMP specs, _the iteration space is divided into chunks that are approximately equal in size_. – Franz May 03 '17 at 07:38
1

It is unclear to me what you are trying to do. If you want to do what you say you do ("assign a variable once and only once at the start of a loop iteration") that falls out completely naturally as

!$OMP DO PRIVATE(variable)
DO i = 0, N = 100000
variable = f(i)        ! Assign value to the local variable at the start of each iteration
<CODE>
END DO
!$END OMP DO

Since variable is thread private, there is a copy in each thread and you assign each instance of the variable once.

But this seems so easy that maybe I don't understand what you're really trying to do!

Jim Cownie
  • 2,409
  • 1
  • 11
  • 20
  • 2
    They're trying to set `variable` **only** on the first iteration (for each thread), rather than at the start of each iteration. – d_1999 May 03 '17 at 10:10
  • 1
    That's not what he said :-) (" once at the start of a loop iteration"). – Jim Cownie May 04 '17 at 08:42
  • Fair enough, but the pseudocode demonstrates their intent! – d_1999 May 04 '17 at 08:55
  • The problem I have is that the other request seems perverse without some other justification for it (which has not been given), so this all feels like someone deciding that they this is the solution to a higher level problem which they haven't explained, and it may be that there's a better solution to that higher level problem. (For instance, this could be someone implementing their own reduction and wanting to initialize a per-thread value, but OpenMP already has reductions!) – Jim Cownie May 04 '17 at 16:32