【问题标题】:Is it possible to track the stack height / recursion depth reliably?是否可以可靠地跟踪堆栈高度/递归深度?
【发布时间】:2018-04-17 09:05:47
【问题描述】:

我试图在程序的某个部分可靠地跟踪我的堆栈高度,以便自适应地调整机器学习算法。

现在,我的代码如下所示:

private const int MaxStackHeight = 20;

[ThreadStatic]
private static int stackHeight;

...

try
{
    var currentHeight = Interlocked.Increment(ref stackHeight);
    var depthFactor = currentHeight / (double)MaxStackHeight;
    // Use `depthFactor` to limit the amount of branching & recursion at this depth by choosing simpler candidates.
}
finally
{
    Interlocked.Decrement(ref stackHeight);
}

我知道将InterlockedThreadStatic 字段一起使用不是必需的,并且我知道Constrained Execution Regions。但是,这个问题与Monitor.Enter/Monitor.Exit 问题非常相似,所以我不相信这可以通过使用 CER 来解决。例如,Monitor 的解决方案是使用在 .NET 4 中添加的Monitor.TryEnter 重载之一上可用的out lockTaken 参数。Interlocked.Increment 是否有类似的策略?

Monitor (.NET 4+) 的示例解决方案:

var lockTaken = false;
try
{
    Monitor.TryEnter(handle, ref lockTaken);
}
finally
{
    if (lockTaken)
    {
        Monitor.Exit(handle);
    }
}

之所以可行,是因为 finally 块是一个受约束的执行区域,并且因为 .NET Framework 保证将准确设置 out lockTaken 参数。

如果不可能,我可以采用两种选择之一。

  • 在堆栈上传递堆栈的高度(例如,将其作为方法参数传递)。这显着增加了我的代码库中许多方法的复杂性。
  • 在根调用站点,在调用递归部分之前和之后将stackHeight 设置为0(即使在出现异常的情况下)。这感觉……很糟糕。

那么, 对我的用例来说可能有类似的可能性,还是我需要求助于其他方法?

编辑:

最佳猜测:

        var incremented = false;
        try
        {
            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
            }
            finally
            {
                stackHeight++;
                incremented = true;
            }

            // Use `stackHeight`
        }
        finally
        {
            if (incremented)
            {
                stackHeight--;
            }
        }

【问题讨论】:

    标签: c# .net multithreading recursion stack-overflow


    【解决方案1】:

    我会在递增和递归调用之前保留该值,并在需要时恢复它,例如:

    var currentStackHeight = stackHeight;
    try {
      for(var i = 0; i < 10; i++) {
        stackHeight = currentStackHeight + 1;
        recurseDeeper();
      }
    }
    finally {
      stackHeight = currentStackHeight;
    }
    

    【讨论】:

      猜你喜欢
      • 2010-10-25
      • 1970-01-01
      • 1970-01-01
      • 2020-03-28
      • 2011-03-16
      • 1970-01-01
      • 2014-01-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多