【问题标题】:Double check locking in fortran with openmp使用 openmp 仔细检查 fortran 中的锁定
【发布时间】:2019-03-18 17:19:27
【问题描述】:

所以我有一些带有双重检查锁定解决方案的代码,用于在多线程(使用 openmp)应用程序中读取数据文件,看起来像:

logical, dimension(10,10) :: is_data_loaded
is_data_loaded=.false.

! Other code

subroutine load(i,j)
    integer,intent(in) :: i,j ! Indexes into array is_data_loaded
    if(is_data_loaded(i,j)) return
    !$OMP CRITICAL(load data)
        if(.not.is_data_loaded(i,j)) then
            call load_single_file(i,j)
            is_data_loaded(i,j) = .true.
        endif
    !$OMP END CRITICAL(load_data)
end subroutine 

我担心如果两个线程同时到达关键区域(具有相同的 i,j 索引),第二个线程会被第一个进入该区域的线程阻塞,但是一旦第一个线程完成,第二个线程可能在看到更新的 is_data_loaded 标志之前开始执行关键块,因此我们遇到了两个线程更新相同数据的问题。

首先,这是 opemp 关键块的问题吗?我不确定语义以及标准是否说“在下一个线程在关键块中运行之前,线程之间的所有内容都必须保持一致”之类的内容。如果这是一个问题,仅仅将读/写内容包装到一个 omp atomic 语句中就足够了吗?

【问题讨论】:

  • 谢谢,现在很好,但我不会在一个线程完成和下一个开始之间仍然存在潜在的竞争条件(第二个可能没有同步 is_data_loaded 中的更改)?
  • 好吧,你没有告诉我们应该有什么样的竞争条件。即使没有任何critical,您的代码中也不存在竞争条件,前提是您始终为不同的索引调用load。你真的应该准备一个minimal reproducible example 并展示你想要避免的竞争条件。代码应包括对load() 的调用以及load_single_file 内部发生的情况。

标签: multithreading fortran openmp


【解决方案1】:

我认为代码是错误的,因为在另一个线程从critical 区域设置它之后,线程可能确实看不到is_data_loaded 的更新。虽然critical 区域将确保发生相应的内存刷新,但执行if(is_data_loaded(i,j)) return 的线程可能看不到更新,因为该语句可能仍会看到过期数据。

我认为需要在if(is_data_loaded(i,j)) return 之前添加!$omp flush 以确保所有数据都已刷新并且is_data_loaded(i,j) 加载了最新数据。

【讨论】:

  • 我可以理解,在一个循环中,一个值可能会卡在一个寄存器中或一些奇怪的非缓存一致的 NUMA 中,但这里子程序中没有循环。跨度>
  • 对不起,你是对的,没有循环。但仍然是第一个if 不一定会看到另一个线程对数组的最新更新。 OpenMP 在它的内存模型中没有做出这样的保证。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-18
相关资源
最近更新 更多