1

I am trying to execute 16 tasks assigned one by one to each element of an array called tasks_ready_master. I want to avoid using OMP Tasking. I thought about using the fork/wait method.

!$OMP SINGLE 
       n=16
       do ff =1,n
          pid=c_fork()
          if (pid < 0) then
             call perror('fork()' // c_null_char)
          else if  (pid == 0) then
             call tasks_ready_master(ff+4)%f_ptr(self,var)
             call exit(STATUS)
          else
             pid=c_wait(STATUS)
             call sleep(50)
          end if
       end do
!$OMP END SINGLE

I referred to the C code I found on Multiple child process. For the unix module, I followed the steps on https://cyber.dabamos.de/programming/modernfortran/fork.html.

The idea is to create 16 child processes and each process will execute a task. From what I understood, the code under else if (pid == 0) then is executed by a child process.

I don't understand the c_wait function and is it necessary to use the sleep function here ?

For me the part under else (parent process) is useless. Is it important ? Without it, It shows me:

fork(): Resource temporarily unavailable

Sorry but there isn't no enough documentation on fork/wait in Fortran.

(I will tag C since one of the links I posted (in my question) contains a C code and the functions used are from C.)

Thanks to the comments, I have:

       n=3
       do ff =1,n
          pid(ff)=c_fork()
          if (pid(ff) < 0) then
             call perror('fork()' // c_null_char)
          else if  (pid(ff) == 0) then
             call tasks_ready_master(ff+4)%f_ptr(self,var)
             call exit(STATUS)
          end if
       end do

       do ff=1,n
          pid(ff)=c_wait(STATUS)
       end do

I consider pid as an array of 16 integer elements.

hakim
  • 139
  • 15
  • 1
    `Resource temporarily unavailable` could mean that you've tried to spawn more processes than you are allowed to spawn. Yes, the code in the `if (pid == 0) then` block is where the child processes will run. Your code does however seem to only spawn 1 child at a time and wait for it to finish which makes the execution of the 16 processes done in a serial fashion - with a `sleep(50)` after each. – Ted Lyngmo Jul 06 '21 at 09:40
  • 1
    Do you want to run all child processes concurrently or one after the other? The `wait_c` in the loop would wait for the end of the process (more precisely for a status change) in the parent process before starting the next child. To run the children concurrently you would have to call `wait_c` (or an alternative function) at the end of the parent process or when you want to react on a child's status change. Normally, the `sleep` should not be necessary. WIth 16 child processes I would not expect `fork` to fail with `Resource temporarily unavailable`. Probably you have more child processes. – Bodo Jul 06 '21 at 09:47
  • @Bodo Can you check my question please (I edited it) and tell me if I really understood what you said in your comment ? I get the `Resource temporarily unavailable` only when I retire the `c_wait` call. I want to run all child processes concurrently. Is the right place where to call `c_wait` ? Thanks for your help ! I also changed pid from an integer to an array of integers. – hakim Jul 06 '21 at 10:45
  • @hakim Please [edit] your question and add all requested information or clarification there. The 2nd variant looks more reasonable. Your 1st loop will continue if one `c_fork` reports an error and store the resulting value `-1` in the `pid` array. I don't know if this is what you need/want. In the 2nd loop it doesn't make sense to overwrite the `pid` array with the return value of `c_wait`. You have to call wait once for every child you started. `wait` will return -1 and set `errno` to `ECHILD` if there is no (more) child process to wait for. Do you still get errors with the new program? – Bodo Jul 06 '21 at 12:18
  • @Bodo my problem with `wait` in Fortran is that it's a function not like in C where it is a subroutine. And I'm not sure if the equivalent of `wait` is `c_wait` in Fortran. There is not enough documentation on this topic. I wrote `pid(ff)=c_wait(STATUS)` because I didn't know how to use `c_wait` here as a function.. Okay I'll edit my question in order to provide more details. – hakim Jul 06 '21 at 12:29
  • 1
    You can assign the return value of `c_wait` to a simple variable and use the value to check for an error report (value < 0). No need to assign it to the array. You could check if a positive return value of `c_wait` matches any of the PIDs stored in the array to find out whoch child exited, but I don't think this is necessary in your case. I guess it is not even necessary to keep an array of all PIDs returned by `c_fork`. (It was about 35 years ago when I last used Fortran on a computer that filled half a room, built of discrete components instead of integrated circuits.) – Bodo Jul 06 '21 at 12:44

0 Answers0