提问人:Simon Gauvin 提问时间:6/28/2022 最后编辑:Jarod42Simon Gauvin 更新时间:6/28/2022 访问量:1179
为什么 std::barrier 会分配?
Why does std::barrier allocate?
问:
为什么 std::barrier 在堆上分配内存,而 std
::latch
不?
它们之间的主要区别在于可以重用而不能重用,但我找不到解释为什么这会使前者分配内存。std::barrier
std::latch
答:
20赞
nanofarad
6/28/2022
#1
虽然朴素屏障确实可以使用恒定量的存储作为对象的一部分来实现,但实际的屏障实现使用具有> O(1) 存储但更好的并发属性的结构。幼稚的恒定存储屏障可能会受到同一计数器上大量线程争用的影响。这种争用可能导致 O(N) 运行时从屏障中释放线程。std::barrier
作为“更好”实现的一个例子,gcc libstdc++ 实现使用树屏障。这避免了在所有线程之间共享的单个计数器/互斥锁上的争用,并且树屏障可以在对数时间内传播“屏障完成,释放时间”信号,但代价是需要线性空间来表示线程树。
不难想象增强的树型屏障实现,这些实现可以识别缓存/套接字/内存总线层次结构,并根据线程的物理位置对树中的线程进行分组,以最大程度地减少跨内核、跨芯片和跨套接字轮询所需的最低限度。
另一方面,闩锁是一种更轻量级的同步工具。但是,我不太确定为什么禁止分配闩锁 - cppreference 状态,
闩锁类是向下的计数器类型
std::ptrdiff_t
这将指示它不应该分配(即它只是一个计数器,没有空间来保存指向已分配对象的指针)。另一方面,标准中的 [thread.latch] 只说“闩锁维护一个内部计数器,该计数器在创建闩锁时初始化”,而不禁止它分配。
评论