提高在不同物理处理器上等待互斥锁的性能

时间:2012-12-24 08:25:04

标签: multithreading winapi synchronization

当我尝试使用不同的互斥体变体时,最后我找到了2个最快的基元。

一个是基于InterlockedExchange(众所周知的方法)

Access:
  while InterlockedExchange(AccessFlag, 1) <> 0 do
Release:
  InterlockedExchange(AccessFlag, 0)

另一个是基于事件的。

Init:
  Event = CreateEvent(Null, false, true, Null);
Access:
  WaitForSingleObject(Event, INFINITE)
Release:
  SetEvent(Event)

InterlockedExchanged-based总是最快,但是在失败的情况下它没有睡觉。另一方面,它在单个物理处理器(核心)或多个核心上都有很大的作用。虽然单核测试的好处是,如果我在循环内添加Sleep(0),则没有失败。

基于事件在等待睡眠时非常棒,但是当我测量性能时,我注意到如果它们驻留在单个物理处理器上(使用相同值调用的SetThreadAffinityMask或测试时,使用这种类型的互斥锁的几个线程执行速度更快)单核计算机)而不是不同的处理器。根据处理器的类型,这从x4(iCore 5)到x8(Xeon)不等。

Xeon的一些统计数据

3个线程,每个增加一个变量10(10,000,000步),每次增加时使用互斥锁访问它。

  • 多处理器,基于InterlockedExcchange的

    344毫秒/每位女士:87,209 / while循环失败:2,487,376(占3的总步数的8%) 线程,Sleep(0)存在,但可能对多处理器线程无用)

  • 多处理器,基于事件

    6187毫秒/每位女士:4,848

  • 单处理器,基于InterlockedExcchange的

    281毫秒/每位女士: 106,761 / while循环失败:0(循环内的Sleep(0));

  • 单处理器,基于事件

    765毫秒/每位女士:39,215

我认为真正的核心间同步会有一些损失。但是我想结婚&#34; InterlockedExchange方法的完美表现与基于事件的方法的正确性(&#34;睡眠,如果你不工作&#34;)。这可能吗?

1 个答案:

答案 0 :(得分:1)

我认为这样做的一种常见方法是仅在有限次数的尝试中使用CAS步骤。如果您的情况没有及时成为现实,那么您将经历“更昂贵”的基于事件的解决方案的开销。