MST

星途 面试题库

面试题:Fortran OpenMP并行编程之共享与私有变量处理

在一个Fortran程序中,利用OpenMP并行化一段计算密集型代码。代码中有一个全局变量`sum`用于累加计算结果,还有一个局部数组`local_array`在每个线程内独立使用。请描述如何正确设置变量的属性(共享或私有)以保证程序的正确性,并给出完整的并行化代码示例。同时说明在这种场景下可能会出现的竞争条件及如何避免。
33.3万 热度难度
编程语言Fortran

知识考点

AI 面试

面试题答案

一键面试

变量属性设置

  1. sum变量:由于sum是全局变量且用于累加计算结果,它需要在线程间共享。所有线程都要对其进行读写操作,以实现最终的累加。
  2. local_array数组local_array是局部数组,在每个线程内独立使用,所以应该设置为私有。每个线程有自己独立的副本,互不干扰。

并行化代码示例

program parallel_example
    use omp_lib
    implicit none
    integer :: i, n
    real :: sum
    real, dimension(100) :: local_array
    n = 10000
    sum = 0.0

!$omp parallel private(i, local_array) shared(sum, n)
    local_array = 0.0
!$omp do
    do i = 1, n
        local_array(mod(i, 100) + 1) = local_array(mod(i, 100) + 1) + real(i)
    end do
!$omp critical
    sum = sum + sum(local_array)
!$omp end critical
!$omp end parallel

    write(*,*) 'Final sum:', sum
end program parallel_example

竞争条件及避免方法

  1. 竞争条件:在对sum进行累加操作时,如果多个线程同时读写sum,就会出现竞争条件。例如,线程A读取sum的值,还未完成更新操作时,线程B也读取了相同的sum值,这样就会导致更新丢失,最终结果错误。
  2. 避免方法:使用critical指令。在上述代码中,critical块保证了在任何时刻只有一个线程能够进入该块,对sum进行更新操作。这样就避免了竞争条件,确保sum的累加操作正确进行。另外,也可以使用reduction子句来简化代码并自动处理这种累加的竞争问题,例如:
!$omp parallel private(i, local_array) shared(n) reduction(+:sum)
    local_array = 0.0
!$omp do
    do i = 1, n
        local_array(mod(i, 100) + 1) = local_array(mod(i, 100) + 1) + real(i)
    end do
    sum = sum + sum(local_array)
!$omp end parallel

reduction(+:sum)子句自动为每个线程创建sum的私有副本,在线程结束时将这些私有副本的值累加到全局sum中,同样避免了竞争条件。