# Parallel sum function

**URL:** <https://fortran-lang.discourse.group/t/parallel-sum-function/2074>\
**Category:** Help\
**Created:** [October 14, 2021, 9:23pm UTC](https://fortran-lang.discourse.group/t/parallel-sum-function/2074 "2021-10-14T21:23:45Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![fortran4r](https://avatars.discourse-cdn.com/v4/letter/f/9de0a6/32.png) [@fortran4r](https://fortran-lang.discourse.group/u/fortran4r)\
**Post date:** [October 14, 2021, 9:23pm UTC](https://fortran-lang.discourse.group/t/parallel-sum-function/2074/1 "2021-10-14T21:23:45Z")

</div>

I have a subroutine as below:

```auto
subroutine lm(n, x, y, res) 
  integer(8) :: n
  real(8) :: x(n), y(n), res  
  real(8) :: sum_x, sum_y, sum_xx, sum_xy
  integer(8) :: i
  
  sum_x = 0d0
  sum_y = 0d0
  sum_xx = 0d0
  sum_xy = 0d0

  !$omp parallel do reduction(+:sum_x)
  do i = 1, n
    sum_x = sum_x + x(i) 
  end do
  !$omp end parallel do
  
  !$omp parallel do reduction(+:sum_y)
  do i = 1, n
    sum_y = sum_y + y(i) 
  end do
  !$omp end parallel do

  !$omp parallel do reduction(+:sum_xx)
  do i = 1, n
    sum_xx = sum_xx + x(i)*x(i) 
  end do
  !$omp end parallel do
  
  !$omp parallel do reduction(+:sum_xy)
  do i = 1, n
    sum_xy = sum_xy + x(i)*y(i) 
  end do
  !$omp end parallel do

  res = (n*sum_xy - sum_x*sum_y)/(n*sum_xx - sum_x*sum_x)
end subroutine

```

If a parallel sum function can be used, the subroutine will be much less verbose. Is there a plan of adding a parallel sum function to the language or std? C++ is already doing this, see:  
[https://en.cppreference.com/w/cpp/experimental/reduce](https://en.cppreference.com/w/cpp/experimental/reduce)

---

<div class="post-metadata">

**Author:** ![vmagnin](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/vmagnin/32/28_2.png) [@vmagnin](https://fortran-lang.discourse.group/u/vmagnin)\
**Post date:** [October 15, 2021, 6:27am UTC](https://fortran-lang.discourse.group/t/parallel-sum-function/2074/2 "2021-10-15T06:27:56Z")

</div>

There is already such a function in the standard:  
[https://gcc.gnu.org/onlinedocs/gfortran/CO\_005fSUM.html](https://gcc.gnu.org/onlinedocs/gfortran/CO_005fSUM.html)

Using images and `co_sum()` you can do the same thing than with OpenMP. I have starded playing with that:  
[https://github.com/vmagnin/exploring\_coarrays/blob/main/pi\_monte\_carlo\_co\_sum.f90](https://github.com/vmagnin/exploring_coarrays/blob/main/pi_monte_carlo_co_sum.f90)

See Milan’s book for more information.

---

<div class="post-metadata">

**Author:** ![ivanpribec](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/ivanpribec/32/3290_2.png) [@ivanpribec](https://fortran-lang.discourse.group/u/ivanpribec)\
**Post date:** [October 15, 2021, 8:29am UTC](https://fortran-lang.discourse.group/t/parallel-sum-function/2074/3 "2021-10-15T08:29:18Z")

</div>

> [@fortran4r](#):
>
> … the subroutine will be much less verbose.

```fortran
res = (n*sum(x*y) - sum(x)*sum(y))/(n*sum(x**2) - sum(x)**2)

```

**Edit:** If you still want to do it the verbose way, you might consider merging the loops.

```fortran
  !$omp parallel do reduction(+:sum_x,sum_y,sum_xx,sum_xy)
  do i = 1, n
    sum_x = sum_x + x(i)
    sum_y = sum_y + y(i)
    sum_xx = sum_xx + x(i)**2
    sum_xy = sum_xy + x(i)*y(i) 
  end do
  !$omp end parallel do

```

I expect this would also reduce the overhead of launching the thread group. Before adding parallel instructions, it’s a good idea to focus on single-core performance. Then you have a better picture if you’re actually profiting from the OMP pragmas or just wasting additional CPU cycles.

**Edit 2:** a MWE can be found in the folded region.

> **Click to open**
>
> ```fortran
> module lm_mod
>   
> ! These are the types used in the dotCall64 R package
> use, intrinsic :: iso_c_binding, only: &
> dp => c_double, &
> int64 => c_int64_t
> 
> implicit none
> 
> contains
> 
> subroutine lm(n, x, y, res) 
> integer(int64), intent(in) :: n
> real(dp), intent(in) :: x(n), y(n)
> real(dp), intent(out) :: res  
> real(dp) :: sum_x, sum_y, sum_xx, sum_xy
> integer(int64) :: i
> 
> #if PARALLEL
> sum_x = 0
> sum_y = 0
> sum_xx = 0
> sum_xy = 0
> !$omp parallel do reduction(+:sum_x,sum_y,sum_xx,sum_xy) shared(x,y)
> do i = 1, n
> sum_x = sum_x + x(i)
> sum_y = sum_y + y(i)
> sum_xx = sum_xx + x(i)**2
> sum_xy = sum_xy + x(i)*y(i)
> end do
> !$omp end parallel do
> #else
> sum_x = sum(x)
> sum_y = sum(y)
> sum_xx = sum(x**2)
> sum_xy = sum(x*y)
> #endif
> res = (n*sum_xy - sum_x*sum_y)/(n*sum_xx - sum_x*sum_x)
> 
> end subroutine
> 
> end module
> 
> program test_lm
> 
> use lm_mod
> implicit none
> 
> real(dp), allocatable :: x(:), y(:)
> real(dp) :: dx, res
> 
> character(len=8) :: argv
> integer(int64) :: n, i
> integer(int64) :: rate, t1, t2
> 
> call system_clock(count_rate=rate)
> 
> call get_command_argument(1,argv)
> read(argv,*) n
> 
> allocate(x(n),y(n))
> 
> dx = 1.0_dp/real(n-1,dp)
> x = [((i-1)*dx,i=1,n)]
> 
> call random_number(y)
> 
> y = 0.5_dp*x + 0.05_dp*y
> 
> call system_clock(t1)
> call lm(n,x,y,res)
> write(*,*) "res = ", res
> call system_clock(t2)
> 
> write(*,*) "Time(s) = ", real(t2-t1,dp)/real(rate,dp)
> 
> end program
> 
> ```

---

<div class="post-metadata">

**Author:** ![fortran4r](https://avatars.discourse-cdn.com/v4/letter/f/9de0a6/32.png) [@fortran4r](https://fortran-lang.discourse.group/u/fortran4r)\
**Post date:** [October 15, 2021, 1:42pm UTC](https://fortran-lang.discourse.group/t/parallel-sum-function/2074/4 "2021-10-15T13:42:50Z")

</div>

Can co\_sum be used in shared libs?

---

<div class="post-metadata">

**Author:** ![vmagnin](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/vmagnin/32/28_2.png) [@vmagnin](https://fortran-lang.discourse.group/u/vmagnin)\
**Post date:** [October 15, 2021, 1:51pm UTC](https://fortran-lang.discourse.group/t/parallel-sum-function/2074/5 "2021-10-15T13:51:35Z")

</div>

See that very recent post:

> [@Using coarrays in a shared library (OpenCoarrays)](https://fortran-lang.discourse.group/t/using-coarrays-in-a-shared-library-opencoarrays/1089):
>
> Suppose I wanted to make a shared library exposing a C interface via bind(C), and use that library from a language other than Fortran, but use OpenCoarrays within the library. Does anybody know how I could accomplish this? I gather that I have to call \_gfortran\_caf\_init() and the associated finalization routine, but would I have to execute the program that uses that library by using cafrun / mpiexec? I’d love to hear from anyone who has experience with or knowledge about this. Thanks.

Note that the term _Coarrays_ can be used to talk about coarrays themselves, but is also often used as a more generic term to talk about all the parallel features introduced by Fortran 2008/2018, like the collective subroutines.
