multithreading - 当另一个线程同时修改队列时,线程应该如何验证队列是否已满?
问题描述
我昨天在网站上问了一个问题,并收到了关于我的错误来源的答案,但我仍然对如何解决问题感到困惑。所以我试图用排名不是 1 的线程调用的函数替换同步屏障。线程号 1 负责填充队列。
我的想法是线程(等级不等于 1)应该检查队列是否已满。如果不是,他们调用已经预定义的睡眠函数。如果它已满,我们可以确定我们可以通过而不必担心比赛条件。
if (num_thread==1) then
do i_task=first_task,last_task
tasklist_GRAD(i_task)%state=STATE_READY
call queue_enqueue_data(master_queue,tasklist_GRAD(i_task)) !< add the list elements to the queue (full queue)
end do
end if
if (num_thread .ne. 1) then
call wait_thread(master_queue)
end if
!!$ !$OMP BARRIER !!!!!!! retired OMP BARR
call master_worker_execution(self,var,master_queue,worker_queue,first_task,last_task,nthreads,num_thread,lck)
这是等待函数的定义:
subroutine wait_thread(master_queue)
type(QUEUE_STRUCT),pointer,asynchronous::master_queue !< the master queue of tasks
do while (.not. queue_full(master_queue))
call system_sleep(1)
end do
end subroutine wait_thread
问题是 1 号线程显然会修改名为master_queue
so write 的队列,同时其他线程将检查队列是否已满,因此也对其进行修改。这可能导致竞争条件。
下面是queue_full
函数的定义:
recursive logical function queue_full( queue )
type(QUEUE_STRUCT),asynchronous, intent(in) :: queue
!$OMP CRITICAL
queue_full = (queue%size == queue%capacity)
!$OMP END CRITICAL
end function queue_full
运行时,我没有收到分段错误,但我也没有得到代码的结果OMP_BARRIER
。
通常我会显示值,但现在我得到一个闪烁的光标。
我的问题是:有没有办法解决这个问题?是不是不能换了OMP_BARRIER
?
我试图添加属性asynchronous
,master_queue
所以声明变成了这样: type(QUEUE_STRUCT),pointer,asynchronous::master_queue !< the master queue of tasks
。定义中的critical
指令queue_full
是我也添加的,但徒劳无功。
请问有什么帮助吗?
编辑:
我刚刚尝试过这种方法,但我不知道它是否真的取代了 OMP_BARRIER。这是新模块time
(没什么复杂的,system_sleep
功能wait
):
module time
use QUEUE
contains
recursive subroutine system_sleep(wait)
use,intrinsic :: iso_c_binding, only: c_int
integer,intent(in) :: wait
integer(kind=c_int):: waited
interface
function c_usleep(msecs) bind (C,name="usleep")
import
integer(c_int) :: c_usleep
integer(c_int),intent(in),VALUE :: msecs
end function c_usleep
end interface
if(wait.gt.0)then
waited=c_usleep(int(wait,kind=c_int))
endif
end subroutine system_sleep
recursive subroutine wait(full)
logical,intent(in)::full
do
call system_sleep(1000)
if (full .eqv. .true.) EXIT
end do
end subroutine wait
end module time
这就是我更换的方式OMP_BARRIER
:
full = .false.
first_task=5
last_task=6
if (num_thread==1) then
do i_task=first_task,last_task
tasklist_GRAD(i_task)%state=STATE_READY
call queue_enqueue_data(master_queue,tasklist_GRAD(i_task)) !< add the list elements to the queue (full queue)
end do
full=.true.
end if
if (num_thread .ne. 1) then !!!!!!!!!! how to replace OMP_BARRIER
call wait(full) !!! wait until full equal to true
end if
call master_worker_execution(self,var,master_queue,worker_queue,first_task,last_task,nthreads,num_thread,lck)
我还想补充一点,shared
变量full
的类型是logical
.
这是摆脱显式障碍的有效方法吗?
解决方案
推荐阅读
- spring-boot - 带有 Spring Boot 的 Informix
- python - 无法在列表理解之外检索 itertools 迭代器
- reactjs - 在 React 16 和 Bootstrap 4 中,如何将引导选项卡组件中的每个选项卡映射到 URL?
- python - 在 websocket 的输出中向数据框添加新行
- node.js - 为什么 http.get 在 NodeJS 中需要这么长时间?
- reactjs - 如何在 React 中提取状态的值
- spring - 我想分配对象字段,例如。使用thymeleaf spring boot的greeting.method(可以是post或get)到Form Method属性
- android - 从 viewPager 的多个页面访问单个媒体播放器实例
- forms - 在嵌套属性表单上设计 strong_params
- java - 如何在枚举器数据字段上获取用户输入?