Пример #1
0
        /// <summary>Creates a new instance.</summary>
        /// <param name="processCount">The number of process threads to create to execute the MPI program.</param>
        private MiniMPIProgram(int processCount)
        {
            _id             = GetNextMpiRuntimeID();
            _owningThreadID = Thread.CurrentThread.ManagedThreadId;

            _startProcessesTogether = new ManualResetEvent(false);

            // Create all the processes
            ProcessCount = processCount;

            _firstErroredProcessRank = -1;
            _state = MiniMPIProgramState.Initialized;
        }
Пример #2
0
        /// <summary>
        /// Every time the runtime state changes, this method determines the
        /// change and performs the processing of runtime rules.
        /// </summary>
        /// <remarks>
        ///	This method runs a continuous loop.  Inside of the continuous loop,
        /// it waits for the runtime state to change.  If all of the processes
        /// have finished, then it will set the state to finished and
        /// subsequently will wait until all of the processes join.
        ///	A subclass of MiniMPIRuntime may define the function OnProcessRuntimeRules to describe
        ///	what this method should do as well each time the runtime state changes.
        /// </remarks>
        private void ExecuteRuntimeLoop()
        {
            do
            {
                // TODO: Use different handles for instructions versus _stateID changes.
                //WaitHandle.WaitAny

                // Wait for the state to change before trying to do anything
                Runtime.BlockTillStateChanged();

                // Determine the current state
                MiniMPIProgramState state = _state;
                if (state != MiniMPIProgramState.Finished)
                {
                    // The only way we can detect when to finish is whether all processes have
                    // finished.
                    if (Thread.VolatileRead(ref _processesFinishedCount) == ProcessCount)
                    {
                        // The most common way the state will get set to Finished is when
                        // all the process threads have finished.
                        _state = state = MiniMPIProgramState.Finished;
                    }
                }

                // Give highest priority to terminating this thread
                if (state == MiniMPIProgramState.Finished)
                {
                    return;
                }

                // First, move any new pending instructions to the ready state
                // Do this just once per iteration
                Runtime.AddInstructionsFromPendingQueue();

                // Only process rules if we are executing
                if (state == MiniMPIProgramState.Executing)
                {
                    // The ProcessRules method should handle performing the collective abort
                    Runtime.ProcessRules();
                }
            } while (true);
        }
Пример #3
0
        /// <summary>
        /// Starts the runtime thread and all process threads and waits for the
        /// runtime to finish.
        /// </summary>
        /// <exception cref="MiniMPIExecutionException">At least one spawned process thread threw an exception.</exception>
        private void Execute <TIMpiApi>(Action <TIMpiApi> processWork)
            where TIMpiApi : IMiniMPICoreAPI
        {
            // ** Make sure we've only been called once **
            if (_hasExecuteBeenCalled)
            {
                throw new InvalidOperationException("Execute has already been called for this runtime instance.");
            }
            _hasExecuteBeenCalled = true;

            // Spawn and start the processes, but they'll wait until the next line to be
            // allowed to start all at the same time.
            SpawnWorkerProcesses(processWork);
            Runtime.InitializeProgram(this.Processes);

            _state = MiniMPIProgramState.Executing;

            // Signal to the processes that they may start now at the same time.
            //   Note: The reason this is done is so that all processes start at
            // same time.  This will allow for no favoritism to the lower-ranked
            // processes which are started first.
            _startProcessesTogether.Set();

            // Execute the runtime loop
            ExecuteRuntimeLoop();

            // Make sure that the state of the MiniMPIRuntime is set to Finished,
            // otherwise something went wrong.
            Debug.Assert(_state == MiniMPIProgramState.Finished);

            // Make sure each process's thread has fully completed too
            // TODO: Think about making the Process threads background threads. Then they'll always get aborted once the program exits.
            foreach (var p in Processes)
            {
                p.Thread.Join();
            }

            // Make sure that the number of processes that finished is equal to
            // the number of processes created.
            Debug.Assert(Thread.VolatileRead(ref _processesFinishedCount) == ProcessCount);

            // Detect any errors
            // JAM: Do I need these to be a Thread.VolatileRead (p.Error, _firstErroredProcessRank)?
            //      Or is the Interlocked.ExchangeCompare in the process threads enough?
            int firstErroredProcess = _firstErroredProcessRank;

            if (firstErroredProcess != -1)
            {
                var processErrors = Processes
                                    .Select(p => {
                    var ex = p.Error;
                    return(ex == null ? null : new MiniMPIProcessException(p.Rank, ex));
                })
                                    .Where(pex => pex != null)
                                    .ToArray();
                throw new MiniMPIExecutionException(
                          processErrors.Single(pex => pex.Rank == firstErroredProcess)
                          , processErrors
                          );
            }
        }