示例#1
0
        /// <summary>
        ///   Initializes a new instance.
        /// </summary>
        /// <param name="createModel">Creates the model that should be checked.</param>
        /// <param name="output">The callback that should be used to output messages.</param>
        /// <param name="configuration">The analysis configuration that should be used.</param>
        internal ModelTraverser(AnalysisModelCreator createModel, AnalysisConfiguration configuration, int transitionSize, bool createStutteringState)
        {
            Requires.NotNull(createModel, nameof(createModel));
            var stopwatch = new Stopwatch();

            stopwatch.Start();

            TransitionCollection.ValidateTransitionSizes();

            var tasks  = new Task[configuration.CpuCount];
            var stacks = new StateStack[configuration.CpuCount];

            _loadBalancer = new LoadBalancer(stacks);
            Context       = new TraversalContext(_loadBalancer, configuration);
            _workers      = new Worker[configuration.CpuCount];

            for (var i = 0; i < configuration.CpuCount; ++i)
            {
                var index = i;
                tasks[i] = Task.Factory.StartNew(() =>
                {
                    stacks[index]   = new StateStack(configuration.StackCapacity);
                    _workers[index] = new Worker(index, Context, stacks[index], createModel.Create());
                });
            }

            Task.WaitAll(tasks);

            var firstModel = _workers[0].Model;

            if (transitionSize == DeriveTransitionSizeFromModel)
            {
                transitionSize = firstModel.TransitionSize;
            }

            if (configuration.WriteStateVectorLayout)
            {
                firstModel.WriteStateVectorLayout(configuration.DefaultTraceOutput);
            }

            var modelCapacity = configuration.ModelCapacity.DeriveModelByteSize(firstModel.ModelStateVectorSize, transitionSize);

            Context.ModelCapacity = modelCapacity;
            if (configuration.UseCompactStateStorage)
            {
                _states = new CompactStateStorage(modelCapacity.SizeOfState, modelCapacity.NumberOfStates);
            }
            else
            {
                _states = new SparseStateStorage(modelCapacity.SizeOfState, modelCapacity.NumberOfStates);
            }
            Context.States = _states;
            if (createStutteringState)
            {
                Context.StutteringStateIndex = _states.ReserveStateIndex();
            }
            _initializationTime = stopwatch.Elapsed;
            stopwatch.Stop();
        }
示例#2
0
        /// <summary>
        ///   Splits the work between this instance and the <paramref name="other" /> instance. Returns <c>true</c> to indicate that
        ///   work has been split; <c>false</c>, otherwise.
        /// </summary>
        /// <param name="other">The other instance the work should be split with.</param>
        public bool SplitWork(StateStack other)
        {
            Assert.That(CanSplit, "Cannot split the state stack.");
            Assert.That(other.FrameCount == 0, "Expected an empty state stack.");

            // We go through each frame and split the first frame with more than two states in half
            for (var i = 0; i < FrameCount; ++i)
            {
                other.PushFrame();

                switch (_frames[i].Count)
                {
                // The stack is in an invalid state; clear the other worker's stack and let this worker
                // continue; it will clean up its stack and try to split work later
                case 0:
                    other.Clear();
                    return(false);

                // We can't split work here, so just push the state to the other worker's stack
                case 1:
                    other.PushState(_states[_frames[i].Offset]);
                    break;

                // We've encountered a frame where we can actually split work; we always split work as early as possible,
                // that is, as low on the stack as possible, to hopefully maximize the amount of work passed to the other worker
                default:
                    // Split the states of the frame
                    var otherCount = _frames[i].Count / 2;
                    var thisCount  = _frames[i].Count - otherCount;

                    // Add the first otherCount states to the other stack
                    for (var j = 0; j < otherCount; ++j)
                    {
                        other.PushState(_states[_frames[i].Offset + j]);
                    }

                    // Adjust the count and offset of the frame
                    _frames[i].Offset += otherCount;
                    _frames[i].Count   = thisCount;

                    // Find the next splittable frame if this one no longer is
                    if (thisCount == 1)
                    {
                        UpdateLowestSplittableFrame();
                    }

                    return(true);
                }
            }

            // This stack could not be split, so we clear the other's stack and let some other worker try again
            other.Clear();
            return(false);
        }
示例#3
0
        /// <summary>
        ///   Initializes a new instance.
        /// </summary>
        /// <param name="index">The zero-based index of the worker.</param>
        /// <param name="context">The context the model is traversed in.</param>
        /// <param name="stateStack">The state stack that should be used by the worker.</param>
        /// <param name="model">The model that the worker should analyze.</param>
        public Worker(int index, TraversalContext <TExecutableModel> context, StateStack stateStack, AnalysisModel <TExecutableModel> model)
        {
            Requires.NotNull(context, nameof(context));
            Requires.NotNull(stateStack, nameof(stateStack));
            Requires.NotNull(model, nameof(model));

            _index      = index;
            _context    = context;
            _stateStack = stateStack;

            Model = model;
        }
示例#4
0
        /// <summary>
        ///   Initializes a new instance.
        /// </summary>
        /// <param name="createModel">Creates the model that should be checked.</param>
        /// <param name="output">The callback that should be used to output messages.</param>
        /// <param name="configuration">The analysis configuration that should be used.</param>
        internal ModelTraverser(AnalysisModelCreator <TExecutableModel> createModel, Action <string> output, AnalysisConfiguration configuration, int transitionSize)
        {
            Requires.NotNull(createModel, nameof(createModel));
            Requires.NotNull(output, nameof(output));
            var stopwatch = new Stopwatch();

            stopwatch.Start();

            TransitionCollection.ValidateTransitionSizes();

            var tasks  = new Task[configuration.CpuCount];
            var stacks = new StateStack[configuration.CpuCount];

            _loadBalancer = new LoadBalancer(stacks);
            Context       = new TraversalContext <TExecutableModel>(_loadBalancer, configuration, output);
            _workers      = new Worker <TExecutableModel> [configuration.CpuCount];

            for (var i = 0; i < configuration.CpuCount; ++i)
            {
                var index = i;
                tasks[i] = Task.Factory.StartNew(() =>
                {
                    stacks[index]   = new StateStack(configuration.StackCapacity);
                    _workers[index] = new Worker <TExecutableModel>(index, Context, stacks[index], createModel.Create());
                });
            }

            Task.WaitAll(tasks);

            var firstModel = _workers[0].Model;

            if (transitionSize == DeriveTransitionSizeFromModel)
            {
                transitionSize = firstModel.TransitionSize;
            }

            var modelCapacity = configuration.ModelCapacity.DeriveModelByteSize(firstModel.StateVectorSize, transitionSize);

            Context.ModelCapacity = modelCapacity;
            _states        = new StateStorage(modelCapacity.SizeOfState, modelCapacity.NumberOfStates);
            Context.States = _states;
            Context.StutteringStateIndex = _states.ReserveStateIndex();
            _initializationTime          = stopwatch.Elapsed;
            stopwatch.Stop();
        }