InitializeCriticalSectionAndSpinCount最佳SpinCount(用户模式)

时间:2014-08-10 19:21:57

标签: c windows synchronization critical-section

我不太了解InitializeCriticalSectionAndSpinCount的文档: http://msdn.microsoft.com/en-us/library/windows/desktop/ms683476(v=vs.85).aspx

它说"你可以通过选择一个小的旋转计数来显着提高性能......"

但是,由于等待微调器比等待对象更快,因此让SpinCount尽可能高是否有意义?我错过了什么?感谢。

(我在多线程应用程序使用的C DLL中使用它)

这是关键部分的代码,由大量线程不断调用:

int g_slots[256] = {0};
...
slot = 256;
EnterCriticalSection(&g_LockHandle);
while (slot-- > 0)
{
    if (g_slots[slot] == 0)
    {
        g_slots[slot] = spid;
        break;
    }
}
LeaveCriticalSection(&g_LockHandle);

后续评论:

对于任何感兴趣的人,这是我在运行Windows 2008 R2的4核服务器上进行测试时的非正式结果:如果进行超快速操作(如测试和增加单个变量),Interlocked将获胜。遥远的第二个是具有低旋转计数(例如,16)的CriticalSection + SpinCount,然后是普通的CriticalSection。但是,如果扫描一个数组(例如整数),Interlocked在CriticalSection(带或不带SpinCount)之后排在第三位。 CriticalSection +高SpinCount在所有情况下都是最慢的。

Neil Weicher www.netlib.com

2 个答案:

答案 0 :(得分:2)

文档实际上说的是,我强调您删除的文本是:

  

您可以通过为短期的关键部分选择小的旋转计数来显着提高性能。

因此,旋转计数的选择非常关键地取决于临界区的持续时间。

你问:

  

但是,因为等待微调器比等待对象更快,所以让SpinCount尽可能高是否有意义?

旋转比阻塞更快是不正确的。对于长时间的关键部分,最好完全避免旋转。如果锁定很可能不会在很长一段时间内释放,那么最好的策略是立即阻止并等到你可以获得锁定。即使是持续时间较短的部分,也可能没有安排持有锁的线程运行,在这种情况下,旋转显然会浪费CPU资源。

旋转只有在旋转时可以获得锁定的可能性很大时才有用。即便如此,只有花费的时间少于产生的时间,上下文切换成本。

答案 1 :(得分:1)

我同意声明"您可以通过选择小的旋转计数来显着提高性能"本身。

当我测试在8核PC上使用InitializeCriticalSectionAndSpinCount的对象池类时,最佳值小于20.旋转计数越大,它的工作速度越慢。

这些是我对此测试结果的推论:

  • 较小的旋转计数,消耗较少的无意义处理。
  • 非常小的旋转计数适用于保证O(1)的例程(例如,无循环)

我不认为旋转计数应该大于数千。旋转计数是一个繁忙的等待。它不仅消耗CPU功率,而且在CPU和RAM之间消耗大量带宽,因此可能导致其他CPU和RAM之间的流量不足。