Worker Pools in Co-array Fortran

module worker_module
  use iso_fortran_env, only: int32, real32
  implicit none

  type :: job_type
    integer(int32) :: id
    real(real32) :: result
  end type job_type

contains

  subroutine worker(id, jobs, results)
    integer(int32), intent(in) :: id
    type(job_type), intent(inout) :: jobs[*]
    type(job_type), intent(inout) :: results[*]
    integer(int32) :: j
    
    do
      sync all
      if (this_image() == 1) then
        j = jobs[1]%id
        if (j == 0) exit
        jobs[1]%id = 0
      end if
      sync all
      
      if (j /= 0) then
        print *, "worker", id, "started  job", j
        call sleep(1)
        print *, "worker", id, "finished job", j
        
        sync all
        if (this_image() == 1) then
          results[1]%id = j
          results[1]%result = real(j * 2)
        end if
      end if
    end do
  end subroutine worker

end module worker_module

program worker_pools
  use worker_module
  use iso_fortran_env, only: int32
  implicit none

  integer(int32), parameter :: num_jobs = 5
  type(job_type) :: jobs[*], results[*]
  integer(int32) :: i

  if (num_images() < 4) error stop "This program requires at least 4 images"

  ! Initialize jobs
  if (this_image() == 1) then
    do i = 1, num_jobs
      jobs[1]%id = i
    end do
  end if

  ! Start workers
  if (this_image() > 1 .and. this_image() <= 4) then
    call worker(this_image() - 1, jobs, results)
  end if

  ! Collect results
  if (this_image() == 1) then
    do i = 1, num_jobs
      sync all
      print *, "Job", results[1]%id, "result:", results[1]%result
    end do
    
    ! Signal workers to finish
    jobs[1]%id = 0
    sync all
  end if

end program worker_pools

In this example, we implement a worker pool using Co-array Fortran’s parallel execution model. Here’s how it works:

  1. We define a job_type to represent jobs and results.

  2. The worker subroutine simulates processing jobs. It uses synchronization (sync all) to coordinate access to shared data.

  3. In the main program, we use image 1 as the coordinator and images 2-4 as workers.

  4. Jobs are initialized on image 1 and workers (images 2-4) process these jobs concurrently.

  5. Results are collected on image 1 and printed.

  6. After all jobs are processed, we signal the workers to finish by setting jobs[1]%id to 0.

To run this program, you would compile it with a Co-array Fortran compiler and execute it with multiple images. For example:

$ caf worker_pools.f90 -o worker_pools
$ cafrun -np 4 ./worker_pools

This program demonstrates parallel execution in Co-array Fortran, simulating a worker pool where multiple workers process jobs concurrently. The exact output may vary due to the parallel nature of the execution, but it will show jobs being processed by different workers concurrently.

Note that Co-array Fortran uses a different concurrency model compared to other languages. Instead of explicit threads or goroutines, it uses the concept of images that run in parallel, with each image capable of accessing data on other images through co-arrays.