///<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;

        }
예제 #3
0
        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;
        }
예제 #4
0
 /// <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);
 }
예제 #5
0
파일: Space.cs 프로젝트: Telanor/bepu-fork
        ///<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);
        }
예제 #6
0
 /// <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);
 }
예제 #7
0
 ///<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;
 }
예제 #9
0
 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;
 }
예제 #12
0
 ///<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)
 {
 }
예제 #13
0
 ///<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;
 }
예제 #17
0
        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>();
 }
예제 #19
0
 public abstract void Update(float dt, IParallelLooper looper);
예제 #20
0
 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;
        }
예제 #22
0
 ///<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;
 }
예제 #23
0
 ///<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)
 {
 }