Skip to content

Commit

Permalink
Add fork method to ISearchControl
Browse files Browse the repository at this point in the history
 - Moving the lookahead control creation to the search control allows
   better customization, e.g., when users implement their own
   SearchControl.
 - Simplifies the implementation of concurrent algorithms
  • Loading branch information
abeham committed Apr 9, 2023
1 parent 40eecf2 commit decb296
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 119 deletions.
70 changes: 17 additions & 53 deletions src/TreesearchLib/ConcurrentAlgorithms.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@ public static void ParallelDepthSearch<T, Q>(ISearchControl<T, Q> control, T sta

var (d, states) = Algorithms.BreadthSearch(control, state, depth: depth, filterWidth, depthLimit, maxDegreeOfParallelism < 0 ? Environment.ProcessorCount : maxDegreeOfParallelism);
depth = d;
var remainingNodes = control.NodeLimit - control.VisitedNodes;
if (depth >= depthLimit || states.Nodes == 0 || remainingNodes <= 0)
if (control.ShouldStop() || depth >= depthLimit || states.Nodes == 0 || control.NodeLimit <= control.VisitedNodes)
{
return;
}
Expand All @@ -57,31 +56,21 @@ public static void ParallelDepthSearch<T, Q>(ISearchControl<T, Q> control, T sta
var searchState = new LIFOCollection<(int, T)>((localDepth, s));
while (true)
{
var localControl = SearchControl<T, Q>.Start(s)
.WithRuntimeLimit(TimeSpan.FromSeconds(1))
.WithCancellationToken(control.Cancellation);
ISearchControl<T, Q> localControl;
lock (locker)
{
if (control.ShouldStop() || backtracks >= backtrackLimit)
localControl = control.Fork(s, withBestQuality: true, maxTimeLimit: TimeSpan.FromSeconds(1));
if (localControl.ShouldStop() || backtracks >= backtrackLimit)
{
localControl.Finish();
break;
}
backtracksMem = backtracks;

localControl = localControl.WithNodeLimit(remainingNodes);
if (control.BestQuality.HasValue)
{
localControl = localControl.WithUpperBound<T, Q>(control.BestQuality.Value);
}
}
var localbacktracks = Algorithms.DepthSearch<T, Q>(localControl, searchState, backtracksMem, filterWidth, depthLimit, backtracksPerThread);
localControl.Finish();


lock (locker)
{
control.Merge(localControl);
remainingNodes = control.NodeLimit - control.VisitedNodes;
backtracks += localbacktracks - backtracksMem;
}
if (searchState.Nodes == 0)
Expand Down Expand Up @@ -124,8 +113,7 @@ public static void ParallelDepthSearch<T, C, Q>(ISearchControl<T, Q> control, T

var (d, states) = Algorithms.BreadthSearch<T, C, Q>(control, (T)state.Clone(), depth, filterWidth, depthLimit, maxDegreeOfParallelism < 0 ? Environment.ProcessorCount : maxDegreeOfParallelism);
depth = d;
var remainingnodes = control.NodeLimit - control.VisitedNodes;
if (depth >= depthLimit || states.Nodes == 0 || remainingnodes <= 0)
if (control.ShouldStop() || depth >= depthLimit || states.Nodes == 0 || control.NodeLimit <= control.VisitedNodes)
{
return;
}
Expand All @@ -151,33 +139,23 @@ public static void ParallelDepthSearch<T, C, Q>(ISearchControl<T, Q> control, T

while (true)
{
var localControl = SearchControl<T, C, Q>.Start(s)
.WithRuntimeLimit(TimeSpan.FromSeconds(1))
.WithCancellationToken(control.Cancellation);
ISearchControl<T, Q> localControl;
lock (locker)
{
if (control.ShouldStop() || backtracks >= backtrackLimit)
localControl = control.Fork(s, withBestQuality: true, maxTimeLimit: TimeSpan.FromSeconds(1));
if (localControl.ShouldStop() || backtracks >= backtrackLimit)
{
localControl.Finish();
break;
}
backtracksMem = backtracks;

localControl = localControl.WithNodeLimit(remainingnodes);
if (control.BestQuality.HasValue)
{
localControl = localControl.WithUpperBound<T, C, Q>(control.BestQuality.Value);
}
}

var (dd, localbacktracks) = Algorithms.DepthSearch<T, C, Q>(localControl, s, searchState, localDepth, backtracksMem, filterWidth, depthLimit, backtracksPerThread);
localDepth = dd;
localControl.Finish();

lock (locker)
{
control.Merge(localControl);
remainingnodes = control.NodeLimit - control.VisitedNodes;
backtracks += localbacktracks - backtracksMem;
}
if (searchState.Nodes == 0)
Expand Down Expand Up @@ -214,8 +192,7 @@ public static IStateCollection<T> ParallelBreadthSearch<T, Q>(ISearchControl<T,

var (d, states) = Algorithms.BreadthSearch(control, state, depth, filterWidth, depthLimit, maxDegreeOfParallelism < 0 ? Environment.ProcessorCount : maxDegreeOfParallelism);
depth = d;
var remainingnodes = control.NodeLimit - control.VisitedNodes;
if (depth >= depthLimit || states.Nodes == 0 || remainingnodes <= 0)
if (control.ShouldStop() || depth >= depthLimit || states.Nodes == 0 || control.NodeLimit <= control.VisitedNodes)
{
return states;
}
Expand All @@ -230,25 +207,21 @@ public static IStateCollection<T> ParallelBreadthSearch<T, Q>(ISearchControl<T,
var searchState = new BiLevelFIFOCollection<T>(s);
while (!control.ShouldStop())
{
var localControl = SearchControl<T, Q>.Start(s)
.WithRuntimeLimit(TimeSpan.FromSeconds(1))
.WithCancellationToken(control.Cancellation);
ISearchControl<T, Q> localControl;
lock (locker)
{
localControl = localControl.WithNodeLimit(remainingnodes);
if (control.BestQuality.HasValue)
localControl = control.Fork(s, withBestQuality: true, maxTimeLimit: TimeSpan.FromSeconds(1));
if (localControl.ShouldStop())
{
localControl = localControl.WithUpperBound<T, Q>(control.BestQuality.Value);
break;
}
}

localDepth = Algorithms.BreadthSearch<T, Q>(localControl, searchState, localDepth, filterWidth, depthLimit, int.MaxValue);
localControl.Finish();

lock (locker)
{
control.Merge(localControl);
remainingnodes = control.NodeLimit - control.VisitedNodes;
}

if (searchState.GetQueueNodes + searchState.PutQueueNodes == 0
Expand Down Expand Up @@ -287,8 +260,7 @@ public static IStateCollection<T> ParallelBreadthSearch<T, C, Q>(ISearchControl<

var (d, states) = Algorithms.BreadthSearch<T, C, Q>(control, (T)state.Clone(), depth, filterWidth, depthLimit, maxDegreeOfParallelism < 0 ? Environment.ProcessorCount : maxDegreeOfParallelism);
depth = d;
var remainingnodes = control.NodeLimit - control.VisitedNodes;
if (depth >= depthLimit || states.Nodes == 0 || remainingnodes <= 0)
if (control.ShouldStop() || depth >= depthLimit || states.Nodes == 0 || control.NodeLimit <= control.VisitedNodes)
{
return states;
}
Expand All @@ -302,25 +274,17 @@ public static IStateCollection<T> ParallelBreadthSearch<T, C, Q>(ISearchControl<
var searchState = new BiLevelFIFOCollection<T>(s);
while (!control.ShouldStop())
{
var localControl = SearchControl<T, C, Q>.Start(s)
.WithRuntimeLimit<T, C, Q>(TimeSpan.FromSeconds(1))
.WithCancellationToken(control.Cancellation);
ISearchControl<T, Q> localControl;
lock (locker)
{
localControl = localControl.WithNodeLimit(remainingnodes);
if (control.BestQuality.HasValue)
{
localControl = localControl.WithUpperBound<T, C, Q>(control.BestQuality.Value);
}
localControl = control.Fork(s, withBestQuality: true, maxTimeLimit: TimeSpan.FromSeconds(1));
}

localDepth = Algorithms.BreadthSearch<T, C, Q>(localControl, searchState, localDepth, filterWidth, depthLimit, int.MaxValue);
localControl.Finish();

lock (locker)
{
control.Merge(localControl);
remainingnodes = control.NodeLimit - control.VisitedNodes;
}

if (searchState.GetQueueNodes + searchState.PutQueueNodes == 0
Expand Down
72 changes: 20 additions & 52 deletions src/TreesearchLib/ConcurrentHeuristics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,13 @@ public static void ParallelBeamSearch<T, Q>(ISearchControl<T, Q> control, T stat
(currentState) =>
{
var localNextLayer = new Queue<(float rank, T state)>();
var localControl = SearchControl<T, Q>.Start(currentState)
.WithCancellationToken(control.Cancellation)
.WithRuntimeLimit(reaminingTime);
ISearchControl<T, Q> localControl;
lock (locker)
{
localControl = localControl.WithNodeLimit(remainingNodes);
if (control.BestQuality.HasValue)
localControl = control.Fork(currentState, withBestQuality: true);
if (localControl.ShouldStop())
{
// to discard certain nodes
localControl = localControl.WithUpperBound<T, Q>(control.BestQuality.Value);
return;
}
}
foreach (var next in currentState.GetBranches().Take(filterWidth))
Expand All @@ -76,7 +73,6 @@ public static void ParallelBeamSearch<T, Q>(ISearchControl<T, Q> control, T stat

localNextLayer.Enqueue((rank(next), next));
}
localControl.Finish();
lock (locker)
{
control.Merge(localControl);
Expand Down Expand Up @@ -131,15 +127,13 @@ public static void ParallelBeamSearch<T, C, Q>(ISearchControl<T, Q> control, T s
(currentState) =>
{
var localNextLayer = new Queue<(float rank, T state)>();
var localControl = SearchControl<T, C, Q>.Start(currentState)
.WithCancellationToken(control.Cancellation)
.WithRuntimeLimit(remainingRuntime);
ISearchControl<T, Q> localControl;
lock (locker)
{
localControl = localControl.WithNodeLimit(remainingNodes);
if (control.BestQuality.HasValue)
localControl = control.Fork(currentState, withBestQuality: true);
if (localControl.ShouldStop())
{
localControl = localControl.WithUpperBound<T, C, Q>(control.BestQuality.Value);
return;
}
}
foreach (var choice in currentState.GetChoices().Take(filterWidth))
Expand All @@ -154,7 +148,6 @@ public static void ParallelBeamSearch<T, C, Q>(ISearchControl<T, Q> control, T s

localNextLayer.Enqueue((rank(next), next));
}
localControl.Finish();
lock (locker)
{
control.Merge(localControl);
Expand Down Expand Up @@ -216,23 +209,17 @@ public static SearchControl<T, Q> ParallelRakeSearch<T, Q>(
quality = next.Quality;
} else
{
SearchControl<T, Q> localControl = null;
ISearchControl<T, Q> localControl;
lock (locker)
{
var remainingTime = control.Runtime - control.Elapsed;
var remainingNodes = control.NodeLimit - control.VisitedNodes;
if (remainingTime <= TimeSpan.Zero || remainingNodes <= 0)
localControl = control.Fork(next, withBestQuality: false);
if (localControl.ShouldStop())
{
i++;
return;
}
localControl = SearchControl<T, Q>.Start(next)
.WithCancellationToken(control.Cancellation)
.WithRuntimeLimit(remainingTime)
.WithNodeLimit(remainingNodes);
}
lookahead(localControl, next);
localControl.Finish();
lock (locker)
{
control.Merge(localControl);
Expand Down Expand Up @@ -316,23 +303,17 @@ public static SearchControl<T, C, Q> ParallelRakeSearch<T, C, Q>(
quality = next.Quality;
} else
{
SearchControl<T, C, Q> localControl = null;
ISearchControl<T, Q> localControl;
lock (locker)
{
var remainingTime = control.Runtime - control.Elapsed;
var remainingNodes = control.NodeLimit - control.VisitedNodes;
if (remainingTime <= TimeSpan.Zero || remainingNodes <= 0)
localControl = control.Fork(next, withBestQuality: false);
if (localControl.ShouldStop())
{
i++;
return;
}
localControl = SearchControl<T, C, Q>.Start(next)
.WithCancellationToken(control.Cancellation)
.WithRuntimeLimit(remainingTime)
.WithNodeLimit(remainingNodes);
}
lookahead(localControl, next);
localControl.Finish();
lock (locker)
{
control.Merge(localControl);
Expand Down Expand Up @@ -418,22 +399,16 @@ public static void ParallelPilotMethod<T, Q>(ISearchControl<T, Q> control,
quality = next.Quality;
} else
{
SearchControl<T, Q> localControl = null;
ISearchControl<T, Q> localControl;
lock (locker)
{
var remainingTime = control.Runtime - control.Elapsed;
var remainingNodes = control.NodeLimit - control.VisitedNodes;
if (remainingTime <= TimeSpan.Zero || remainingNodes <= 0)
localControl = control.Fork(next, withBestQuality: false);
if (localControl.ShouldStop())
{
return;
}
localControl = SearchControl<T, Q>.Start(next)
.WithCancellationToken(control.Cancellation)
.WithRuntimeLimit(remainingTime)
.WithNodeLimit(remainingNodes);
}
lookahead(localControl, next);
localControl.Finish();
if (localControl.BestQuality.HasValue) quality = localControl.BestQuality;
lock (locker)
{
Expand Down Expand Up @@ -507,23 +482,16 @@ public static void ParallelPilotMethod<T, C, Q>(ISearchControl<T, Q> control,
quality = next.Quality;
} else
{
SearchControl<T, C, Q> localControl = null;
ISearchControl<T, Q> localControl;
lock (locker)
{

var remainingTime = control.Runtime - control.Elapsed;
var remainingNodes = control.NodeLimit - control.VisitedNodes;
if (remainingTime <= TimeSpan.Zero || remainingNodes <= 0)
localControl = control.Fork(next, withBestQuality: false);
if (localControl.ShouldStop())
{
return;
}
localControl = SearchControl<T, C, Q>.Start(next)
.WithCancellationToken(control.Cancellation)
.WithRuntimeLimit(remainingTime)
.WithNodeLimit(remainingNodes);
}
lookahead(localControl, next);
localControl.Finish();
if (localControl.BestQuality.HasValue) quality = localControl.BestQuality;
lock (locker)
{
Expand Down
Loading

0 comments on commit decb296

Please sign in to comment.