【问题标题】:Strange results using atomic in OMP (gfortran)在 OMP (gfortran) 中使用原子的奇怪结果
【发布时间】:2021-03-04 18:21:02
【问题描述】:

测试一个原子示例代码我得到了一个奇怪的结果。

program atomic

    use omp_lib
    implicit none

    integer, parameter :: num_threads = 4, m = 1000000
    integer :: thread_num
    integer :: i, j, sum1 = 0, sum2 = 0, tic,toc, rate 
    real:: time
    integer, external :: increment

    thread_num = 0
    !$ call omp_set_num_threads(num_threads)

!////////// ATOMIC ////////////////////////////////////////////////////////////


  CALL system_clock(count_rate=rate)
  call system_clock(tic)
    !$omp parallel do private(thread_num, j) &
    !$omp shared(sum1, sum2)
        do i = 0 , m-1
            !$ thread_num = omp_get_thread_num()
            
            !$omp atomic
                sum1 = sum1 + i
                sum2 = sum2 + increment(thread_num, i)    
        end do
    !$omp end paralleldo

    print*, "sum 1 = ", sum1
    print*, "sum 2 = ", sum2
  call system_clock(toc)
    time = real(toc-tic)/real(rate)
    print*, "Time atomic: ", time, 's'

!////////// CRITICAL ////////////////////////////////////////////////////////////
sum1=0; sum2=0
  CALL system_clock(count_rate=rate)
  call system_clock(tic)
    !$omp parallel do private(thread_num, j) &
    !$omp shared(sum1, sum2)
        do i = 0 , m-1
            !$ thread_num = omp_get_thread_num()
            
            !$omp critical
                sum1 = sum1 + i
                sum2 = sum2 + increment(thread_num, i)    
            !$omp end critical
        end do
    !$omp end paralleldo

    print*, "sum 1 = ", sum1
    print*, "sum 2 = ", sum2
  call system_clock(toc)
    time = real(toc-tic)/real(rate)
    print*, "Time critical: ", time, 's'


end program atomic

integer function increment (thread_num, j)
    implicit none
    integer, intent(in) :: thread_num, j

!    print*, "Function increment run by thread number: ", thread_num
    increment = j

end function increment


  1. 使用 'm = 10000000'(7 个零)我得到:

总和 1 = -2014260032

总和 2 = -1146784608

时间原子:1.13900006 s

总和 1 = -2014260032

总和 2 = -2014260032

时间紧迫:4.09000015 秒


  1. 使用 'm=1000000'(6 个零)我得到:

总和 1 = 1783293664

总和 2 = 1576859165

时间原子:0.123999998 s

总和 1 = 1783293664

总和 2 = 1783293664

时间紧迫:0.133000001 s


我有两个问题:

为什么我在第一种情况下得到负输出?

为什么在原子输出中 sum1 不等于 sum2?


编译使用:

gfortran -Wall -Wextra -fopenmp -O2 -Wall -o prog.exe prueba.f90

./prog.exe

【问题讨论】:

    标签: multithreading parallel-processing openmp atomic gfortran


    【解决方案1】:

    为什么我在第一种情况下得到负输出?

    因为求和运算溢出。从这个source 可以读到:

    在计算机编程中,当算术运算时会发生整数溢出 操作尝试创建一个超出 可以用给定位数表示的范围 - 要么 高于最大或低于最小可表示值

    对于m = 10000000,结果为49999995000000,该值大于 Fortran 中整数(32 位整数)可表示的最大值。

    第二个问题

    为什么在原子输出中 sum1 不等于 sum2?

    因为 atomic 子句只应用于操作:

    sum1 = sum1 + i
    

    您可以通过使用可以表示更广泛数字的数据类型来解决的第一个问题。第二个问题可以解决如下:

            !$omp atomic
                sum1 = sum1 + i
            !$omp atomic
                sum2 = sum2 + increment(thread_num, i)   
    

    【讨论】:

      猜你喜欢
      • 2017-02-26
      • 2020-12-27
      • 2010-09-14
      • 2011-12-19
      • 1970-01-01
      • 1970-01-01
      • 2014-07-25
      • 1970-01-01
      • 2019-06-10
      相关资源
      最近更新 更多