【问题标题】:How long is a single spin in ManualResetEventSlimManualResetEventSlim 中的单次旋转需要多长时间
【发布时间】:2012-04-24 19:39:10
【问题描述】:

c# 中的单次旋转需要多长时间?我想知道的是有一个 ManualResetEventSlim 有一个 spinCount 参数,我想知道每次旋转的时间以毫秒为单位或它是如何工作的?我知道旋转对于短等待比内核等待更有效。所以我只是想看看我应该为一般需要 2-10 秒的工作设置这个值。

【问题讨论】:

  • 2-10 .. 什么?你是说微秒吗?
  • 纺纱是以纳秒为单位的,你根本不会在 2-10 秒内完成它......甚至不会在 2-10 毫秒内完成。

标签: c# multithreading c#-4.0


【解决方案1】:

构造函数中的spinCount参数与执行旋转等待所花费的毫秒数之间没有相关性。

这是它的工作原理。 MRES 使用这个spinCount 参数来完成自己的等待程序,独立于Thread.SpinWait

  • 前 10 次迭代在调用 Thread.YieldThread.SpinWait 之间交替。对Thread.SpinWait 的调用以Environment.ProcessorCount * 4 的旋转开始,然后在每次连续调用时大约翻倍。
  • 此后每次迭代都可以被 20 次调用 Thread.Sleep(1) 整除。
  • 否则可被 5 整除的呼叫 Thread.Sleep(0)
  • 否则会调用Thread.Yield
  • CancellationToken 在 100 次后每 10 次迭代检查一次。

如您所见,在 MRES 的自定义旋转程序中进行了相当复杂的歌舞。并且算法可能会因版本而异。真的无法预测每次旋转会持续多长时间。

如果您的典型等待时间为 2-10 秒,那么您的代码几乎肯定会通过 Monitor.WaitMonitor.Pulse 协调进行内核级等待,因为无论如何spinCount 参数都限制为 2047。

另外,2-10 秒是很长的时间。你真的要转那么久吗?

【讨论】:

  • +1 了解有趣的细节。它真的很努力让其他线程释放锁!
  • 发走吧,只要你不希望我回答它我也想知道。在我使用 sleep(0)/sleep(1) 的奇怪情况下(仅用于调试),我发现性能没有差异。
  • @Gabe - 它在迭代 1、2、3、4、7、8、9 时翻倍。它在迭代 5 上执行 Yield 而不是 SpinWait。在迭代 6 上它增加 *4。
  • 我有点明白了,但不是完全明白,但无论如何我会旋转 10 个周期,让它做内核互斥锁。
  • @Gabe:是的,斧头是对的。我说“大约”是因为公式是ProcessorCount * (4 << iteration),但迭代不一定是连续的。顺便说一句,那里有一些相当厚的代码。我想知道微软是怎么想出来的。
【解决方案2】:

旋转计数应该很小。默认值为 10(如果在单处理器上运行,则为 1)。如果您使用允许您指定旋转计数的构造函数,则允许的最大值为 2047。如果事件没有很快发出信号,则 ManualResetEventSlim 使用常规事件句柄等待。正如@HenkHolterman 所提到的,所涉及的时间远比几秒钟小得多。我们说的是周期,而不是秒甚至毫秒。

http://msdn.microsoft.com/en-us/library/5hbefs30.aspx

在 .NET Framework 版本 4 中,您可以使用 System.Threading.ManualResetEventSlim 类以获得更好的性能 当等待时间预计很短,并且当事件发生时 不跨越进程边界。 ManualResetEventSlim 使用忙旋转 等待事件发出信号的一小段时间。什么时候 等待时间很短,旋转可能比等待便宜得多 通过使用等待句柄。但是,如果事件没有发出信号 在一定时间内,ManualResetEventSlim 会使用 常规事件句柄等待。

http://msdn.microsoft.com/en-us/library/ee722114.aspx

在多核计算机上,当资源不应该被占用时 在很长一段时间内,等待的效率会更高 线程在用户模式下旋转几十或几百个周期, 然后重试获取资源。如果资源可用 旋转后,您节省了数千个周期。如果 资源仍然不可用,那么你只用了几个周期 并且仍然可以进入基于内核的等待。

编辑:但要直接回答您的问题,单次旋转的时间长度无法明确回答,因为它取决于运行它的硬件。 http://msdn.microsoft.com/en-us/library/system.threading.thread.spinwait(v=vs.95).aspx

SpinWait 实质上将处理器置于一个非常紧凑的循环中,其中 由迭代参数指定的循环计数。持续时间 因此,等待时间取决于处理器的速度。

【讨论】:

    猜你喜欢
    • 2017-03-06
    • 2011-05-02
    • 2016-09-17
    • 2012-06-30
    • 1970-01-01
    • 2015-01-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多