0

I'm trying to implement a code where we spawn a child process who should add one to the variable sum at each iteration. We have at all 3 iteartions. The result of sum is : 0+1+1+1 = 3. But when I want to spawn 3 threads in the child process part (so each thread will have an iteration), I get a sum equal to 9.
(I'm new to POSIX Threads and to all the functions that I will use later so don't get surprised if the error is obvious, please)
Here is my code:

 program main
 use, intrinsic :: iso_c_binding
      use :: unix
      implicit none
      integer :: i, rc,pid, STATUS,any_child
      integer, parameter :: NTHREADS = 3
      type(c_pthread_t)  :: threads(NTHREADS)
      integer, target    :: routines(NTHREADS) = [ (i, i = 1, NTHREADS) ]
      integer :: sum=0,product=5
      pid = c_fork()
    
      if (pid < 0) then
         ! Fork failed.
         call perror('fork()' // c_null_char)
      else if (pid == 0) then
         print '(a)', '>>> child process running ...'
         do i = 1, NTHREADS
            ! Create new thread.
            rc = c_pthread_create(threads(i), c_null_ptr, c_funloc(compute), c_loc(routines(i)))
         end do
         
         do i = 1, NTHREADS
            ! Join thread.
             rc= c_pthread_join(threads(i), c_loc(routines(i)))
         end do
         print '(a)', '>>> child process done.'
         
         call exit(STATUS)
      else
         ! Parent process.
         print*,'habibi'
         any_child=c_wait(STATUS)
         print*,'ya nour 3in'
         open(2,file='variables.dat')
         read(2,*) sum,product
         close(2)
         print*,'The sum is equal to : ',sum
         print*,'The product is equal to : ',product
      end if
    
    contains
      recursive subroutine compute(arg) bind(c)
        !! Runs inside a thread and prints out current thread id and loop
        !! iteration.
        type(c_ptr), intent(in), value :: arg
        integer, pointer               :: n
        integer                        :: i, rc
        integer :: sum=0,product=5
    
    
        if (.not. c_associated(arg)) return ! Check whether argument has been passed.
        call c_f_pointer(arg, n)            ! Convert C pointer to Fortran pointer.
    
        do i = 1, 3
           sum=sum+1
           product=product*2
           open(1, file = 'variables.dat')
           write(1,*) sum,product
           close(1)
           print '("--- Thread #", i0, " - Loop iteration ", i0)', n, i
           rc = c_usleep(10**6)            ! Sleep 1 sec.
        end do
      end subroutine compute
    
    end program main

Here is the output:

 habibi
>>> child process running ...
--- Thread #1 - Loop iteration 1
--- Thread #3 - Loop iteration 1
--- Thread #2 - Loop iteration 1
--- Thread #1 - Loop iteration 2
--- Thread #3 - Loop iteration 2
--- Thread #2 - Loop iteration 2
--- Thread #1 - Loop iteration 3
--- Thread #3 - Loop iteration 3
--- Thread #2 - Loop iteration 3
>>> child process done.
 ya nour 3in
 The sum is equal to :            9
 The product is equal to :         2560

and here is how I compiled: gfortran -o fork fork.f90 libfortran-unix.a -lpthread

Can anyone explain why I got a sum equal to 9 and what should I do to fix it ? I want the sum to be equal to 3 so that each thread add 1 to the first value (which is 0).

hakim
  • 139
  • 15
  • Do you know that `sum` in `compute` has the SAVE attribute? – francescalus Jul 08 '21 at 12:39
  • @francescalus can you explain more please ? how can I get rid of the SAVE attribute ? – hakim Jul 08 '21 at 12:44
  • You can see [this question](https://stackoverflow.com/q/3352741/3157076) and related ones. – francescalus Jul 08 '21 at 12:50
  • @francescalus If I understood well, I should assign the value to the variable after the type declaration. Thanks a lot ! – hakim Jul 08 '21 at 12:55
  • @francescalus last question if you have time : what happens if I retire the `do` loop in compute ? In the case where we have the `do` loop going from 1 to 3, does it mean that each thread will have 1 iteration ? I doubt that each thread will have 3 iterations .. – hakim Jul 08 '21 at 13:01
  • Each thread will run the subroutine fully. If the loop inside is run three times, each thread will run it three times: there's no automatic work sharing with threads (the way this is written). pthreads are very different from OpenMP threads. – francescalus Jul 08 '21 at 13:41

0 Answers0