기계 학습 알고리즘을 적응 적으로 조정하기 위해 내 프로그램의 특정 부분에서 스택 높이를 안정적으로 추적하려고합니다.스택 높이/재귀 깊이를 안정적으로 추적 할 수 있습니까?
는 지금, 내 코드는 다음과 같습니다 : 나는 ThreadStatic
필드 Interlocked
를 사용하는 것은 필요하지 않다고 알고 있어요, 내가 Constrained Execution Regions 알고 있어요
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);
}
. 그러나이 문제는 Monitor.Enter
/Monitor.Exit
문제와 매우 유사하므로 CER을 사용하여 해결할 수 있다고 확신하지 못합니다. 예를 들어, Monitor
의 솔루션은 .NET에서 추가 된 Monitor.TryEnter
오버로드 중 하나에서 사용할 수있는 out lockTaken
매개 변수를 사용하고 있습니다. Interlocked.Increment
과 비슷한 전략이 있습니까? 모니터 (.NET 4+)에 대한
예 솔루션 : finally 블록은 제한된 실행 영역이기 때문에, 및 .NET 프레임 워크는 out lockTaken
매개 변수가 정확하게 설정되도록 보장하기 때문에
var lockTaken = false;
try
{
Monitor.TryEnter(handle, ref lockTaken);
}
finally
{
if (lockTaken)
{
Monitor.Exit(handle);
}
}
이 작동합니다.
가능하지 않은 경우 두 가지 대안 중 하나를 선택할 수 있습니다.
- 스택의 스택 높이를 전달합니다 (예 : 메소드 매개 변수로 전달). 이것은 코드베이스의 많은 메소드의 복잡성을 상당히 증가시킵니다.
- 루트 호출 사이트에서 재귀 부분을 호출하기 전후에
stackHeight
을0
으로 설정합니다 (예외가 발생한 경우에도 마찬가지 임). 이 느낌은 ... 나쁘다.
그래서, 내 사용 사례에 대해 가능한 유사한 무엇인가, 또는 나는 다른 방법에 의지해야합니까?
편집 :
추측 : 내가 필요로 할 때 내가 증가 재귀 호출하기 전에 값을 유지하고 복원 할
var incremented = false;
try
{
RuntimeHelpers.PrepareConstrainedRegions();
try
{
}
finally
{
stackHeight++;
incremented = true;
}
// Use `stackHeight`
}
finally
{
if (incremented)
{
stackHeight--;
}
}
그래, 그건 아주 간단합니다. 내가 왜 그렇게 생각하지 않았어? 클래식 overthinking ... –