Esiste una formula per calcolare il tempo di esecuzione totale dei processi sequenziali asincroni?

4

Ho una serie di passaggi che devono essere eseguiti in sequenza su un elenco di dati. Tuttavia, ogni passaggio funziona solo su un singolo pezzo di dati alla volta. Per questo motivo, posso eseguire i passaggi in modo asincrono.

Ad esempio, ho due pezzi di dati e due passaggi. Quando il primo passo ha finito di elaborare il primo pezzo di dati, lo passa al secondo passaggio. Ora il primo passaggio elabora il secondo pezzo di dati mentre il secondo passaggio elabora il primo pezzo di dati. Così via e così via fino a quando tutti i dati sono stati elaborati da ogni passaggio.

Al contrario, scorrere l'elenco degli elementi ed eseguirli sequenzialmente in ordine si trasforma nell'equazione:

total_time = (step1 + step2 + ... + stepN) * number_of_items

Dato che conosco il tempo di esecuzione di ogni passaggio per un singolo pezzo di dati, e conosco il numero di elementi da elaborare, c'è una formula che mi dirà il tempo totale di esecuzione per l'elaborazione di tutti dati in modo asincrono?

Ho scritto un programma (vedi sotto) che simula questo processo. Non sono completamente sicuro che lo stia calcolando correttamente, ma credo che sia vicino. Questo è stato il mio tentativo di capire come risolvere il problema. Lo sto includendo qui per mostrare la mia comprensione del problema, che potrebbe essere sbagliato.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace ConsoleApplication1 {
    class Step : Queue<object> {
        public Step(int totalExecutionTime)
        {
            _totalExecutionTime = totalExecutionTime;
            CurrentExecutionTime = _totalExecutionTime;
        }
        readonly int _totalExecutionTime;
        public Queue<object> NextStep { private get; set; }
        public int CurrentExecutionTime { get; private set; }
        public void RunTick()
        {
            if (Count == 0)
                return;
            if (CurrentExecutionTime == 0)
                CurrentExecutionTime = _totalExecutionTime;
            CurrentExecutionTime--;
            if (CurrentExecutionTime == 0 && NextStep != null)
                NextStep.Enqueue(Dequeue());
        }
    }
    class Program {
        static void Main(string[] args)
        {
            int totalItems = 10;
            int[] stepLengths = new int[] { 1,2,5,2,2 };
            if (File.Exists("output.txt"))
                File.Delete("output.txt");
            WriteLine("ASYNC: {0}", TotalTime(totalItems, stepLengths));
            WriteLine("SEQUENTIAL: {0}", stepLengths.Sum() * totalItems);
            Console.WriteLine("DONE");
            Console.ReadLine();
        }

        static int TotalTime2(int totalItems, int[] stepLengths)
        {
            throw new NotImplementedException();
        }

        private static int TotalTime(int totalItems, int[] stepLengths)
        {
            var steps = new List<Step>();
            Step prevStep = null;
            foreach(var stepLength in stepLengths) {
                var step = new Step(stepLength);
                steps.Add(step);
                if (prevStep != null)
                    prevStep.NextStep = step;
                prevStep = step;
            }
            var first = steps.First();
            for(int i = 0; i < totalItems; i++) {
                first.Enqueue(new object());
            }
            var last = steps.Last();
            var revSteps = steps.Reverse<Step>().ToList();
            var totalTime = 0;
            do
            {
                Display(steps, totalTime);
                revSteps.ForEach(s => s.RunTick());
                totalTime++;
            } while (last.Count < totalItems);
            if (last.CurrentExecutionTime > 0)
            {
                do
                {
                    Display(steps, totalTime);
                    revSteps.ForEach(s => s.RunTick());
                    totalTime++;
                } while (last.CurrentExecutionTime > 0);
            }
            Display(steps, totalTime);
            return totalTime;
        }

        static void Display(List<Step> steps, int totalTime)
        {
            Write("[");
            steps.ForEach(s => Write("{0},", s.CurrentExecutionTime.ToString().PadLeft(2)));
            WriteLine("]");
            Write("[");
            steps.ForEach(s => Write("{0},", s.Count.ToString().PadLeft(2)));
            WriteLine("] {0}", totalTime.ToString().PadLeft(5));
            WriteLine();
        }
        static void Write(string fmt, params object[] args)
        {
            Console.Write(fmt, args);
            using (var w = new StreamWriter("output.txt", true))
            {
                w.Write(fmt, args);
            }
        }

        static void WriteLine(string fmt, params object[] args)
        {
            Console.WriteLine(fmt, args);
            using (var w = new StreamWriter("output.txt", true))
            {
                w.WriteLine(fmt, args);
            }
        }

        static void WriteLine()
        {
            Console.WriteLine();
            using (var w = new StreamWriter("output.txt", true))
            {
                w.WriteLine();
            }
        }
    }
}
    
posta Charles Lambert 01.12.2011 - 23:05
fonte

1 risposta

2

Supponendo che i processi siano completamente indipendenti (nessuna contesa di risorse) e che ogni processo abbia una coda di input infinita, l'elaborazione di tutti gli elementi richiederà circa il tempo necessario per gestire tutti i dati, più il tempo per il primo elemento per raggiungere il processo più lento, più il tempo per completare l'ultimo elemento dopo che ha lasciato il processo più lento.

    
risposta data 01.12.2011 - 23:22
fonte