///<summary> /// Constructs the position updater. ///</summary> ///<param name="timeStepSettings">Time step settings to use.</param> /// <param name="parallelLooper">Parallel loop provider to use.</param> public ContinuousPositionUpdater(TimeStepSettings timeStepSettings, IParallelLooper parallelLooper) : base(timeStepSettings, parallelLooper) { preUpdate = PreUpdate; updateTimeOfImpact = UpdateTimeOfImpact; updateContinuous = UpdateContinuousItem; }
///<summary> /// Constructs the bounding box updater. ///</summary> ///<param name="timeStepSettings">Time step setttings to be used by the updater.</param> /// <param name="parallelLooper">Parallel loop provider to be used by the updater.</param> public BoundingBoxUpdater(TimeStepSettings timeStepSettings, IParallelLooper parallelLooper) : this(timeStepSettings) { ParallelLooper = parallelLooper; AllowMultithreading = true; }
public override void Update(float dt, IParallelLooper looper) { var wholeStartTime = Stopwatch.GetTimestamp(); this.dt = dt; inverseDt = 1 / dt; ApplyGravity(dt, looper); var solverStartTime = Stopwatch.GetTimestamp(); looper.ForLoop(0, constraints.Count, Preupdate); looper.ForLoop(0, dynamics.Count, ApplyAccumulatedImpulses); for (int i = 0; i < IterationCount; ++i) { looper.ForLoop(0, constraints.Count, SolveIteration); looper.ForLoop(0, dynamics.Count, ApplyImpulse); } var solverEndTime = Stopwatch.GetTimestamp(); looper.ForLoop(0, dynamics.Count, UpdatePosition); var wholeEndTime = Stopwatch.GetTimestamp(); SolveTime = (solverEndTime - solverStartTime) / (double)Stopwatch.Frequency; TotalTime = (wholeEndTime - wholeStartTime) / (double)Stopwatch.Frequency; }
/// <summary> /// Constructs a grid-based sort and sweep broad phase. /// </summary> /// <param name="parallelLooper">Parallel loop provider to use for the broad phase.</param> public Grid2DSortAndSweep(IParallelLooper parallelLooper) : base(parallelLooper) { updateEntry = UpdateEntry; updateCell = UpdateCell; QueryAccelerator = new Grid2DSortAndSweepQueryAccelerator(this); }
///<summary> /// Constructs a new space for things to live in. ///</summary> ///<param name="parallelLooper">Used by the space to perform multithreaded updates. Pass null if multithreading is not required.</param> public Space(IParallelLooper parallelLooper) { timeStepSettings = new TimeStepSettings(); this.parallelLooper = parallelLooper; SpaceObjectBuffer = new SpaceObjectBuffer(this); EntityStateWriteBuffer = new EntityStateWriteBuffer(); DeactivationManager = new DeactivationManager(TimeStepSettings, ParallelLooper); ForceUpdater = new ForceUpdater(TimeStepSettings, ParallelLooper); BoundingBoxUpdater = new BoundingBoxUpdater(TimeStepSettings, ParallelLooper); BroadPhase = new DynamicHierarchy(ParallelLooper); NarrowPhase = new NarrowPhase(TimeStepSettings, BroadPhase.Overlaps, ParallelLooper); Solver = new Solver(TimeStepSettings, DeactivationManager, ParallelLooper); NarrowPhase.Solver = Solver; PositionUpdater = new ContinuousPositionUpdater(TimeStepSettings, ParallelLooper); BufferedStates = new BufferedStatesManager(ParallelLooper); DeferredEventDispatcher = new DeferredEventDispatcher(); DuringForcesUpdateables = new DuringForcesUpdateableManager(timeStepSettings, ParallelLooper); BeforeNarrowPhaseUpdateables = new BeforeNarrowPhaseUpdateableManager(timeStepSettings, ParallelLooper); BeforeSolverUpdateables = new BeforeSolverUpdateableManager(timeStepSettings, ParallelLooper); BeforePositionUpdateUpdateables = new BeforePositionUpdateUpdateableManager(timeStepSettings, ParallelLooper); EndOfTimeStepUpdateables = new EndOfTimeStepUpdateableManager(timeStepSettings, ParallelLooper); EndOfFrameUpdateables = new EndOfFrameUpdateableManager(timeStepSettings, ParallelLooper); }
/// <summary> /// Constructs a new dynamic hierarchy broad phase. /// </summary> /// <param name="parallelLooper">Parallel loop provider to use in the broad phase.</param> public DynamicHierarchy(IParallelLooper parallelLooper) : base(parallelLooper) { multithreadedRefit = MultithreadedRefit; multithreadedOverlap = MultithreadedOverlap; QueryAccelerator = new DynamicHierarchyQueryAccelerator(this); }
///<summary> /// Constructs a read buffer manager. ///</summary> ///<param name="manager">Owning buffered states manager.</param> ///<param name="parallelLooper">Parallel loop provider to use.</param> public StateReadBuffers(BufferedStatesManager manager, IParallelLooper parallelLooper) { this.manager = manager; multithreadedStateUpdateDelegate = MultithreadedStateUpdate; FlipLocker = new object(); ParallelLooper = parallelLooper; AllowMultithreading = true; }
///<summary> /// Constructs a new interpolated states manager. ///</summary> ///<param name="manager">Owning buffered states manager.</param> /// <param name="parallelLooper">Parallel loop provider to use.</param> public InterpolatedStatesManager(BufferedStatesManager manager, IParallelLooper parallelLooper) { this.manager = manager; multithreadedWithReadBuffersDelegate = UpdateIndex; FlipLocker = new object(); ParallelLooper = parallelLooper; AllowMultithreading = true; }
protected BroadPhase(IParallelLooper parallelLooper) : this() { ParallelLooper = parallelLooper; AllowMultithreading = true; }
///<summary> /// Constructs a new manager. ///</summary> ///<param name="parallelLooper">Parallel loop provider to be used by the manager.</param> public BufferedStatesManager(IParallelLooper parallelLooper) { InterpolatedStates = new InterpolatedStatesManager(this, parallelLooper); ReadBuffers = new StateReadBuffers(this, parallelLooper); }
protected UpdateableManager(TimeStepSettings timeStepSettings, IParallelLooper parallelLooper) : this(timeStepSettings) { ParallelLooper = parallelLooper; AllowMultithreading = true; }
///<summary> /// Constructs a manager. ///</summary> ///<param name="timeStepSettings">Time step settings to use.</param> /// <param name="parallelLooper">Parallel loop provider to use.</param> public EndOfFrameUpdateableManager(TimeStepSettings timeStepSettings, IParallelLooper parallelLooper) : base(timeStepSettings, parallelLooper) { }
///<summary> /// Constructs a manager. ///</summary> ///<param name="timeStepSettings">Time step settings to use.</param> /// <param name="parallelLooper">Parallel loop provider to use.</param> public BeforePositionUpdateUpdateableManager(TimeStepSettings timeStepSettings, IParallelLooper parallelLooper) : base(timeStepSettings, parallelLooper) { }
double RunTest(IParallelLooper threadManager, Func<Space, int> simulationBuilder) { Space space = new Space(threadManager); var timeStepCount = simulationBuilder(space); //Perform one starter frame to warm things up. space.Update(); var startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; for (int i = 0; i < timeStepCount; i++) { space.Update(); } var endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; return endTime - startTime; }
double RunTest(int splitOffset, IParallelLooper parallelLooper) { Entity toAdd; //BoundingBox box = new BoundingBox(new Vector3(-5, 1, 1), new Vector3(5, 7, 7)); BoundingBox box = new BoundingBox(new Vector3(-500, -500, -500), new Vector3(500, 500, 500)); int splitDepth = splitOffset + (int)Math.Ceiling(Math.Log(parallelLooper.ThreadCount, 2)); DynamicHierarchy dh = new DynamicHierarchy(parallelLooper); Random rand = new Random(0); RawList<Entity> entities = new RawList<Entity>(); for (int k = 0; k < 10000; k++) { Vector3 position = new Vector3((float)(rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X), (float)(rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y), (float)(rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z)); toAdd = new Box(position, 1, 1, 1, 1); toAdd.CollisionInformation.CollisionRules.Personal = CollisionRule.NoNarrowPhasePair; toAdd.CollisionInformation.UpdateBoundingBox(0); dh.Add(toAdd.CollisionInformation); entities.Add(toAdd); } Space.ForceUpdater.Gravity = new Vector3(); int numRuns = 3000; //Prime the system. dh.Update(); var testType = Test.Update; BroadPhaseOverlap[] overlapBasis = new BroadPhaseOverlap[dh.Overlaps.Count]; dh.Overlaps.CopyTo(overlapBasis, 0); double time = 0; double startTime, endTime; switch (testType) { #region Update Timing case Test.Update: for (int i = 0; i < numRuns; i++) { //DH4 startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; //dh.Update(); //lock (dh.Locker) //{ // dh.Overlaps.Clear(); // if (dh.ROOTEXISTS) // { // dh.MultithreadedRefitPhase(splitDepth); // dh.MultithreadedOverlapPhase(splitDepth); // } //} //dh.Update(); //lock (dh.Locker) //{ // dh.Overlaps.Clear(); // if (dh.ROOTEXISTS) // { // dh.SingleThreadedRefitPhase(); // dh.SingleThreadedOverlapPhase(); // } //} endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; time += endTime - startTime; //if (dh.Overlaps.Count != overlapBasis.Length) // Debug.WriteLine("Failed Update."); //for (int j = 0; j < overlapBasis.Length; j++) //{ // if (!dh.Overlaps.Contains(overlapBasis[j])) // Debug.WriteLine("Failed Update."); //} //MoveEntities(entities); } break; #endregion #region Refit Timing case Test.Refit: for (int i = 0; i < numRuns; i++) { dh.Overlaps.Clear(); //DH4 startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; //dh.MultithreadedRefitPhase(splitDepth); //dh.SingleThreadedRefitPhase(); endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; time += endTime - startTime; //dh.SingleThreadedOverlapPhase(); //if (dh.Overlaps.Count != overlapBasis.Length) // Debug.WriteLine("Failed Refit."); //for (int j = 0; j < overlapBasis.Length; j++) //{ // if (!dh.Overlaps.Contains(overlapBasis[j])) // Debug.WriteLine("Failed Refit."); //} //MoveEntities(entities); } break; #endregion #region Overlap Timing case Test.Overlap: for (int i = 0; i < numRuns; i++) { dh.Overlaps.Clear(); //dh.MultithreadedRefitPhase(splitDepth); //DH4 startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; //dh.MultithreadedOverlapPhase(splitDepth); //dh.SingleThreadedOverlapPhase(); endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; time += endTime - startTime; //if (dh.Overlaps.Count != overlapBasis.Length) // Debug.WriteLine("Failed Overlap."); //for (int j = 0; j < overlapBasis.Length; j++) //{ // if (!dh.Overlaps.Contains(overlapBasis[j])) // Debug.WriteLine("Failed Overlap."); //} //MoveEntities(entities); } break; #endregion #region Ray cast timing case Test.RayCast: float rayLength = 100; RawList<Ray> rays = new RawList<Ray>(); for (int i = 0; i < numRuns; i++) { rays.Add(new Ray() { Position = new Vector3((float)(rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X), (float)(rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y), (float)(rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z)), Direction = Vector3.Normalize(new Vector3((float)(rand.NextDouble() - .5), (float)(rand.NextDouble() - .5), (float)(rand.NextDouble() - .5))) }); } RawList<BroadPhaseEntry> outputIntersections = new RawList<BroadPhaseEntry>(); //DH4 startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; for (int i = 0; i < numRuns; i++) { dh.QueryAccelerator.RayCast(rays.Elements[i], rayLength, outputIntersections); outputIntersections.Clear(); } endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; time = endTime - startTime; break; #endregion #region Bounding box query timing case Test.BoundingBoxQuery: float boundingBoxSize = 10; var boundingBoxes = new RawList<BoundingBox>(); Vector3 offset = new Vector3(boundingBoxSize / 2, boundingBoxSize / 2, boundingBoxSize / 2); for (int i = 0; i < numRuns; i++) { Vector3 center = new Vector3((float)(rand.NextDouble() * (box.Max.X - box.Min.X) + box.Min.X), (float)(rand.NextDouble() * (box.Max.Y - box.Min.Y) + box.Min.Y), (float)(rand.NextDouble() * (box.Max.Z - box.Min.Z) + box.Min.Z)); boundingBoxes.Add(new BoundingBox() { Min = center - offset, Max = center + offset }); } outputIntersections = new RawList<BroadPhaseEntry>(); //DH4 startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; for (int i = 0; i < numRuns; i++) { dh.QueryAccelerator.GetEntries(boundingBoxes.Elements[i], outputIntersections); outputIntersections.Clear(); } endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; time = endTime - startTime; break; #endregion } return time / numRuns; }
protected PositionUpdater(TimeStepSettings timeStepSettings, IParallelLooper parallelLooper) : this(timeStepSettings) { ParallelLooper = parallelLooper; AllowMultithreading = true; }
public static TestResults TestDH(TestCollidableBEPU[] leaves, BEPUutilities.BoundingBox[] queries, ref BoundingBox positionBounds, int queryCount, int selfTestCount, int refitCount, int frameCount, float dt, IParallelLooper looper) { GC.Collect(); { DynamicHierarchy tree = new DynamicHierarchy(looper); for (int i = 0; i < leaves.Length; ++i) { tree.Add(leaves[i]); } if (looper.ThreadCount > 1) tree.MultithreadedRefitPhase(tree.GetSplitDepth()); else tree.SingleThreadedRefitPhase(); tree.Overlaps.Count = 0; if (looper.ThreadCount > 1) tree.MultithreadedOverlapPhase(tree.GetSplitDepth()); else tree.SingleThreadedOverlapPhase(); for (int i = 0; i < leaves.Length; ++i) { tree.Remove(leaves[i]); } } GC.Collect(); { var startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; DynamicHierarchy tree = new DynamicHierarchy(looper); for (int i = 0; i < leaves.Length; ++i) { tree.Add(leaves[i]); } var endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; Console.WriteLine($"DH Build Time: {endTime - startTime}"); Console.WriteLine($"Cost metric: {tree.MeasureCostMetric()}"); //tree.SingleThreadedRefitPhase(); //startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; //for (int i = 0; i < refitCount; ++i) //{ // tree.SingleThreadedRefitPhase(); // //Console.WriteLine($"Cost metric: {tree.MeasureCostMetric()}"); //} //endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; //Console.WriteLine($"DH Refit Time: {endTime - startTime}"); //Console.WriteLine($"Cost metric: {tree.MeasureCostMetric()}"); //tree.SingleThreadedOverlapPhase(); //startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; //for (int i = 0; i < selfTestCount; ++i) //{ // tree.Overlaps.Clear(); // tree.SingleThreadedOverlapPhase(); //} //endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; //Console.WriteLine($"DH selftest Time: {endTime - startTime}, overlaps: {tree.Overlaps.Count}"); //**************** Dynamic Testing Random random = new Random(5); TestResults results = new TestResults("Old", frameCount); startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; for (int t = 0; t < frameCount; ++t) { //Update the positions of objects. for (int i = 0; i < leaves.Length; ++i) { var leaf = leaves[i]; //Bounce off the walls. if (leaf.Position.X < positionBounds.Min.X && leaf.Velocity.X < 0) leaf.Velocity.X = -leaf.Velocity.X; if (leaf.Position.Y < positionBounds.Min.Y && leaf.Velocity.Y < 0) leaf.Velocity.Y = -leaf.Velocity.Y; if (leaf.Position.Z < positionBounds.Min.Z && leaf.Velocity.Z < 0) leaf.Velocity.Z = -leaf.Velocity.Z; if (leaf.Position.X > positionBounds.Max.X && leaf.Velocity.X > 0) leaf.Velocity.X = -leaf.Velocity.X; if (leaf.Position.Y > positionBounds.Max.Y && leaf.Velocity.Y > 0) leaf.Velocity.Y = -leaf.Velocity.Y; if (leaf.Position.Z > positionBounds.Max.Z && leaf.Velocity.Z > 0) leaf.Velocity.Z = -leaf.Velocity.Z; leaf.Position += leaf.Velocity * dt; leaf.UpdateBoundingBox(); } var refineStartTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; if (looper.ThreadCount > 1) tree.MultithreadedRefitPhase(tree.GetSplitDepth()); else tree.SingleThreadedRefitPhase(); //tree.Refit(); //for (int i = 0; i < 1; ++i) //{ // subtreeReferences.Count = 0; // treeletInternalNodes.Count = 0; // tree.BinnedRefine(0, ref subtreeReferences, maximumSubtrees, ref treeletInternalNodes, ref spareNodes, ref resources, out nodesInvalidated); //} //tree.RemoveUnusedInternalNodes(ref spareNodes); var refineEndTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; tree.Overlaps.Count = 0; if (looper.ThreadCount > 1) tree.MultithreadedOverlapPhase(tree.GetSplitDepth()); else tree.SingleThreadedOverlapPhase(); var testEndTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; results.Refine[t] = 1000 * (refineEndTime - refineStartTime); results.SelfTest[t] = 1000 * (testEndTime - refineEndTime); results.Total[t] = 1000 * (testEndTime - refineStartTime); results.OverlapCounts[t] = tree.Overlaps.Count; results.TreeCosts[t] = tree.MeasureCostMetric(); if (t % 16 == 0) { Console.WriteLine($"_________________{t}_________________"); Console.WriteLine($"Refine time: {results.Refine[t]}"); Console.WriteLine($"Test time: {results.SelfTest[t]}"); Console.WriteLine($"TIME: {results.Total[t]}"); Console.WriteLine($"Cost metric: {results.TreeCosts[t]}"); Console.WriteLine($"Overlaps: {results.OverlapCounts[t]}"); GC.Collect(); } } endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; Console.WriteLine($"Cost metric: {tree.MeasureCostMetric()}"); tree.Overlaps.Clear(); tree.SingleThreadedOverlapPhase(); startTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; for (int i = 0; i < selfTestCount; ++i) { tree.Overlaps.Clear(); tree.SingleThreadedOverlapPhase(); } endTime = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; Console.WriteLine($"DH selftest Time2: {endTime - startTime}, overlaps: {tree.Overlaps.Count}"); return results; } }
/// <summary> /// Constructs a new sort and sweep broad phase. /// </summary> /// <param name="parallelLooper">Parallel loop provider to use in the broad phase.</param> public SortAndSweep1D(IParallelLooper parallelLooper) : base(parallelLooper) { sweepSegment = Sweep; backbuffer = new RawList<BroadPhaseEntry>(); }
public abstract void Update(float dt, IParallelLooper looper);
protected void ApplyGravity(float dt, IParallelLooper looper) { Vector3.Multiply(ref Gravity, dt, out gravityVelocityChange); looper.ForLoop(0, dynamics.Count, ApplyGravity); }
public unsafe int RefitAndRefine(int frameIndex, IParallelLooper looper, RefitAndRefineMultithreadedContext context, float refineAggressivenessScale = 1, float cacheOptimizeAggressivenessScale = 1) { //Don't proceed if the tree is empty. if (leafCount == 0) return 0; var pool = BufferPools<int>.Locking; int estimatedRefinementTargetCount; GetRefitAndMarkTuning(out context.MaximumSubtrees, out estimatedRefinementTargetCount, out context.LeafCountThreshold); context.Initialize(looper.ThreadCount, estimatedRefinementTargetCount, pool); //Collect the refinement candidates. if (LeafCount <= 2) { RefitAndMark(context.LeafCountThreshold, ref context.RefinementCandidates.Elements[0]); } else { CollectNodesForMultithreadedRefit(looper.ThreadCount, ref context.RefitNodes, context.LeafCountThreshold, ref context.RefinementCandidates.Elements[0]); //Console.WriteLine($"Refit subtree count: {context.RefitNodes.Count}"); looper.ForLoop(0, looper.ThreadCount, context.RefitAndMarkAction); } var refinementCandidatesCount = 0; for (int i = 0; i < looper.ThreadCount; ++i) { refinementCandidatesCount += context.RefinementCandidates.Elements[i].Count; } int targetRefinementCount, period, offset; GetRefineTuning(frameIndex, refinementCandidatesCount, refineAggressivenessScale, context.RefitCostChange, looper.ThreadCount, out targetRefinementCount, out period, out offset); //Condense the set of candidates into a set of targets. context.RefinementTargets = new QuickList<int>(pool, BufferPool<int>.GetPoolIndex(targetRefinementCount)); int actualRefinementTargetsCount = 0; var currentCandidatesIndex = 0; int index = offset; for (int i = 0; i < targetRefinementCount - 1; ++i) { index += period; //Wrap around if the index doesn't fit. while (index >= context.RefinementCandidates.Elements[currentCandidatesIndex].Count) { index -= context.RefinementCandidates.Elements[currentCandidatesIndex].Count; ++currentCandidatesIndex; if (currentCandidatesIndex >= context.RefinementCandidates.Count) currentCandidatesIndex -= context.RefinementCandidates.Count; } Debug.Assert(index < context.RefinementCandidates.Elements[currentCandidatesIndex].Count && index >= 0); var nodeIndex = context.RefinementCandidates.Elements[currentCandidatesIndex].Elements[index]; context.RefinementTargets.Elements[actualRefinementTargetsCount++] = nodeIndex; nodes[nodeIndex].RefineFlag = 1; } context.RefinementTargets.Count = actualRefinementTargetsCount; if (nodes->RefineFlag != 1) { context.RefinementTargets.Add(0); ++actualRefinementTargetsCount; nodes->RefineFlag = 1; } //Refine all marked targets. looper.ForLoop(0, Math.Min(looper.ThreadCount, context.RefinementTargets.Count), context.RefineAction); //To multithread this, give each worker a contiguous chunk of nodes. You want to do the biggest chunks possible to chain decent cache behavior as far as possible. //Note that more cache optimization is required with more threads, since spreading it out more slightly lessens its effectiveness. var cacheOptimizeCount = GetCacheOptimizeTuning(context.MaximumSubtrees, context.RefitCostChange, (Math.Max(1, looper.ThreadCount * 0.25f)) * cacheOptimizeAggressivenessScale); var cacheOptimizationTasks = looper.ThreadCount * 2; context.PerWorkerCacheOptimizeCount = cacheOptimizeCount / cacheOptimizationTasks; var startIndex = (int)(((long)frameIndex * context.PerWorkerCacheOptimizeCount) % nodeCount); context.CacheOptimizeStarts.Add(startIndex); var optimizationSpacing = nodeCount / looper.ThreadCount; var optimizationSpacingWithExtra = optimizationSpacing + 1; var optimizationRemainder = nodeCount - optimizationSpacing * looper.ThreadCount; for (int i = 1; i < cacheOptimizationTasks; ++i) { if (optimizationRemainder > 0) { startIndex += optimizationSpacingWithExtra; --optimizationRemainder; } else { startIndex += optimizationSpacing; } if (startIndex >= nodeCount) startIndex -= nodeCount; Debug.Assert(startIndex >= 0 && startIndex < nodeCount); context.CacheOptimizeStarts.Add(startIndex); } //for (int i = 0; i < looper.ThreadCount; ++i) //{ // var start = context.CacheOptimizeStarts[i]; // var end = Math.Min(start + context.PerWorkerCacheOptimizeCount, NodeCount); // for (int j = start; j < end; ++j) // { // //ValidateRefineFlags(0); // IncrementalCacheOptimizeThreadSafe(j); // //ValidateRefineFlags(0); // } //} //var start = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; //Validate(); //ValidateRefineFlags(0); looper.ForLoop(0, cacheOptimizationTasks, context.CacheOptimizeAction); //ValidateRefineFlags(0); //var end = Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency; //Validate(); //Console.WriteLine($"Cache optimize time: {end - start}"); context.CleanUp(); return actualRefinementTargetsCount; }
///<summary> /// Constructs a deactivation manager. ///</summary> ///<param name="timeStepSettings">The time step settings used by the manager.</param> /// <param name="parallelLooper">Parallel loop provider used by the manager.</param> public DeactivationManager(TimeStepSettings timeStepSettings, IParallelLooper parallelLooper) : this(timeStepSettings) { ParallelLooper = parallelLooper; AllowMultithreading = true; }
///<summary> /// Constructs a manager. ///</summary> ///<param name="timeStepSettings">Time step settings to use.</param> /// <param name="parallelLooper">Parallel loop provider to use.</param> public BeforeSolverUpdateableManager(TimeStepSettings timeStepSettings, IParallelLooper parallelLooper) : base(timeStepSettings, parallelLooper) { }