protected override void OnUpdate() { int2 gridSize = new int2(WorldManager.MapWorld.regionSize, WorldManager.MapWorld.regionSize); NativeList <JobHandle> jobHandles = new NativeList <JobHandle>(Allocator.Temp); Entities.ForEach((Entity entity, DynamicBuffer <PathfindingRoute> pathRoute, ref PathfindingParams pathfindingParams) => { List <MapGrowth> mapGrowths = WorldManager.MapWorld.GetMapGrowths(pathfindingParams.growthCode); NativeArray <int2> targetLocations = new NativeArray <int2>(GetAllTargetsFromGrowth(mapGrowths), Allocator.TempJob); PathFinderJob pathfinderJob = new PathFinderJob { pathfindingType = pathfindingParams.pathfindingType, positionStart = pathfindingParams.startPosition, positionEnd = pathfindingParams.endPosition, gridSize = gridSize, entity = entity, routeFollow = GetComponentDataFromEntity <PathfindingRouteFollow>(), pathRoute = pathRoute, pathNodes = WorldManager.PathNodesNA, targets = targetLocations }; jobHandles.Add(pathfinderJob.Schedule()); PostUpdateCommands.RemoveComponent <PathfindingParams>(entity); }); JobHandle.CompleteAll(jobHandles); }
private async Task <IEnumerable <byte[]> > GetUniqueNodeCountsAsync(Shape shape) { const int ThreadCount = 1; var tableau = shape.CreateTableau(); var terminalNodePairs = tableau.TerminalNodeUniqueCombinations() .GroupBy(nodePair => (TerminalNode)nodePair.Node1) .Select(grp => ( startNode: grp.Key, endNodes: grp.Select(node => (TerminalNode)node.Node2).ToList())) .ToList(); var jobSpecs = terminalNodePairs.Select(nodePair => new PathFinderJobSpec { Tableau = tableau, Name = nodePair.startNode.Index.ToString(), StartPoint = nodePair.startNode, EndPoints = nodePair.endNodes.ToList(), ThreadCount = ThreadCount }).ToList(); var combinedNodeCounts = new Dictionary <byte[], int>(new ByteSequenceEqualEqualityComparer()); var tokenSource = new CancellationTokenSource(); var tasks = new List <Task <(IDictionary <byte[], int>, PathFinderState)> >(); foreach (var jobSpec in jobSpecs) { var pathFinderJob = new PathFinderJob(jobSpec); var pathFinderState = new PathFinderState { Name = jobSpec.Name, Steps = jobSpec.StartPoint.Links.Select(link => new Step(link.Value, link.Key)).ToList(), Progress = new Progress() }; tasks.Add(pathFinderJob.ExploreAsync(pathFinderState, tokenSource.Token)); } await Task.WhenAll(tasks); foreach (var task in tasks) { var(nodeCounts, pathFinderState) = task.Result; foreach (var nodeCount in nodeCounts) { if (!combinedNodeCounts.TryAdd(nodeCount.Key, nodeCount.Value)) { combinedNodeCounts[nodeCount.Key] += nodeCount.Value; } } } return(combinedNodeCounts .Where(kv => kv.Value == 1) .Select(kv => kv.Key)); }
void Start() { float startTime = Time.realtimeSinceStartup; int findPathJobCount = 5; NativeArray <JobHandle> jobHandleArray = new NativeArray <JobHandle>(findPathJobCount, Allocator.TempJob); for (int i = 0; i < findPathJobCount; i++) { PathFinderJob pathJob = new PathFinderJob { positionStart = new int2(0, 0), positionEnd = new int2(1023, 1023), gridSize = new int2(1024, 1024) }; jobHandleArray[i] = pathJob.Schedule(); Debug.Log("Creating Job Time: " + ((Time.realtimeSinceStartup - startTime) * 1000f)); } JobHandle.CompleteAll(jobHandleArray); Debug.Log("Total Time: " + ((Time.realtimeSinceStartup - startTime) * 1000f)); jobHandleArray.Dispose(); }
public static async Task Main(string[] args) { Trace.Listeners.Add(new TextWriterTraceListener(Console.Out)); if (!Directory.Exists(Configuration.FolderName)) { Directory.CreateDirectory(Configuration.FolderName); } var shape = GetShape(args); var tableau = shape.CreateTableau(); var concurrency = GetConcurrency(args); var persistInterval = GetPersistInterval(args); var terminalNodePairs = tableau.TerminalNodeUniqueCombinations() .GroupBy(nodePair => (TerminalNode)nodePair.Node1) .Select(grp => ( startNode: grp.Key, endNodes: grp.Select(node => (TerminalNode)node.Node2).ToList())) .ToList(); foreach (var(startNode, endNodes) in terminalNodePairs) { Trace.WriteLine($"{startNode.Index}: {string.Join(", ", endNodes.Select(node => node.Index))}"); } var jobs = new List <(PathFinderJob, PathFinderState)>(); foreach (var(startNode, endNodes) in terminalNodePairs) { var jobAdded = false; var jobSpec = new PathFinderJobSpec { Name = startNode.Index.ToString(), Tableau = tableau, StartPoint = startNode, EndPoints = endNodes, ThreadCount = concurrency, MonitorInterval = persistInterval }; if (persistInterval > TimeSpan.Zero) { var saveFilePath = Configuration.Filename(shape, jobSpec.Name); Trace.WriteLine($"Save file path: {saveFilePath}"); if (File.Exists(saveFilePath)) { var savedState = RouteStateReaderWriter.ReadFromFile(saveFilePath); if (savedState.Shape != shape.Name) { throw new Exception($"The shape {savedState.Shape} specfied in file '{saveFilePath}' does not match the expected value {shape.Name}."); } if (savedState.Size != shape.Size) { throw new Exception($"The size {savedState.Size} specfied in file '{saveFilePath}' does not match the expected value {shape.Size}."); } var endPoints = savedState.TerminalNodes .Select(index => tableau.TerminalNodes[index]) .ToList(); var steps = new List <Step>(); var queue = new Queue <(Step step, int id)>(); var items = savedState.Steps.Where(x => x.PreviousId == 0).ToList(); foreach (var item in items) { var step = new Step( node: tableau.Nodes[item.Position], direction: new Direction(item.Direction)); queue.Enqueue((step, item.Id)); } while (queue.Any()) { var(previousStep, id) = queue.Dequeue(); items = savedState.Steps.Where(x => x.PreviousId == id).ToList(); if (items.Count == 0) { steps.Add(previousStep); continue; } foreach (var item in items) { var direction = new Direction(item.Direction); var twist = direction - previousStep.Direction; var step = new Step( node: tableau.Nodes[item.Position], direction: direction, twist: twist, previous: previousStep); queue.Enqueue((step, item.Id)); } } var pathFinderJob = new PathFinderJob(jobSpec); //TODO: paths var pathFinderState = new PathFinderState { Name = jobSpec.Name, Steps = steps, Progress = savedState.Progress }; jobs.Add((pathFinderJob, pathFinderState)); jobAdded = true; } } if (!jobAdded) { var pathFinderJob = new PathFinderJob(jobSpec); var pathFinderState = new PathFinderState { Name = jobSpec.Name, Steps = startNode.Links.Select(link => new Step(link.Value, link.Key)).ToList(), Progress = new Progress() }; jobs.Add((pathFinderJob, pathFinderState)); } } var tokenSource = new CancellationTokenSource(); var tasks = new List <Task <(IDictionary <byte[], int>, PathFinderState)> >(); foreach (var(pathFinderJob, pathFinderState) in jobs) { tasks.Add(pathFinderJob.ExploreAsync(pathFinderState, tokenSource.Token)); } await Task.WhenAll(tasks); var combinedElapsedTime = TimeSpan.Zero; var combinedRouteCount = 0L; var combinedNodeCounts = new Dictionary <byte[], int>(new ByteSequenceEqualEqualityComparer()); foreach (var task in tasks) { var(nodeCounts, pathFinderState) = task.Result; foreach (var nodeCount in nodeCounts) { if (!combinedNodeCounts.ContainsKey(nodeCount.Key)) { combinedNodeCounts.Add(nodeCount.Key, 0); } combinedNodeCounts[nodeCount.Key] += nodeCount.Value; } var uniqueSolutionCount = nodeCounts.Count(item => item.Value == 1); combinedRouteCount += pathFinderState.Progress.RouteCount; if (pathFinderState.Progress.ElapsedTime > combinedElapsedTime) { combinedElapsedTime = pathFinderState.Progress.ElapsedTime; } Trace.WriteLine($"Result for job {pathFinderState.Name}: routes = {pathFinderState.Progress.RouteCount}, distinct solutions = {nodeCounts.Count}, unique solutions = {uniqueSolutionCount}, elapsed time = {pathFinderState.Progress.ElapsedTime}"); } var combinedUniqueSolutionCount = combinedNodeCounts.Count(item => item.Value == 1); Trace.WriteLine($"Overall result: routes = {combinedRouteCount}, distinct solutions = {combinedNodeCounts.Count}, unique solutions = {combinedUniqueSolutionCount}, elapsed time = {combinedElapsedTime}"); }