0

着眼于代码的并行部分,下面给出的哪个选项是首选?有更好的解决方案吗?我正在尝试对独立实现进行平均do_something

选项 1:使用 CRITICAL

  resultado%uno = 0.d0
  !$OMP PARALLEL DO shared(large) private(i_omp) schedule(static,1)
  do i_omp=1, nthreads
     call do_something(large, resultadoOmp(i_omp))
     !$OMP CRITICAL (forceloop)
     resultado%uno = resultado%uno + resultadoOmp(i_omp)%uno
     !$OMP END CRITICAL (forceloop)
  enddo
  !$OMP END PARALLEL DO
  resultado%uno  = resultado%uno/nthreads

选项 2:避免CRITICAL(和ATOMIC

  !$OMP PARALLEL DO shared(large) private(i_omp) schedule(static,1)
  do i_omp=1, nthreads
     call do_something(large, resultadoOmp(i_omp))
  enddo
  !$OMP END PARALLEL DO

  uno = 0.d0
  !$OMP PARALLEL DO shared(resultado) private(i_omp) schedule(static,1) &
  !$OMP & REDUCTION(+:uno)
  do i_omp=1, nthreads
     uno = uno + resultadoOmp(i_omp)%uno
  end do
  !$OMP END PARALLEL DO
  resultado%uno  = uno/nthreads

在这方面我不能使用,REDUCTION(+:resultado%uno)也不能使用REDUCTION(+:resultado),只允许使用数字类型。

这种方法的缺点,IMO,是必须resultadoOmp用线程数来确定派生的尖端。好处是避免了CRITICAL可能影响性能的子句,对吗?

4

1 回答 1

0

IMO 这种方法的缺点是必须使用线程数来确定派生的tipe resultadoOmp 的尺寸。优点是避免了可能影响性能的 CRITICAL 子句,我是对的吗?

是的你是对的。看起来您无论如何都在用线程数来确定 resultadoOmp 的尺寸,所以这不是一个缺点吗?第二部分的性能确实应该更好,尽管两个并行区域可能会再次吃掉这个优势。因此,您应该只对两个部分使用一个并行区域。根据 do_something 的运行时间,我什至可能完全忽略归约操作的并行性,并在并行计算所有 uno 条目后在单个线程上进行求和:

!$OMP PARALLEL DO shared(large) private(i_omp) schedule(static,1)
do i_omp=1, nthreads
   call do_something(large, resultadoOmp(i_omp))
end do
!$OMP END PARALLEL DO

resultado%uno = sum(resultadoOmp(:)%uno)/nthreads

您将需要使用实际设置来衡量各种实现以得出结论。

于 2013-02-03T19:50:24.920 回答