public void ParallelSchedulerEmptySequenceTest()
        {
            ParallelScheduler ps    = new ParallelScheduler();
            var variablesUsedByNode = new[] { new int[] { } };

            ps.CreateGraph(variablesUsedByNode);
        }
        public void ParallelSchedulerTest2()
        {
            ParallelScheduler ps = new ParallelScheduler();

            ps.FillIdleSlots = true;
            int depth = 10;

            int[][] variablesUsedByNode = Util.ArrayInit(2 * depth + 1, i =>
            {
                if (i < depth)
                {
                    return(new int[] { 0 });
                }
                else if (i < 2 * depth)
                {
                    return(new int[] { i - depth });
                }
                else
                {
                    return(Util.ArrayInit(depth, j => j));
                }
            });
            ps.CreateGraph(variablesUsedByNode);
            var schedule = ps.GetScheduleWithBarriers(2);

            ParallelScheduler.WriteSchedule(schedule);
            var perThread = ps.ConvertToSchedulePerThread(schedule, 2);

            Assert.True(perThread[1][0].Length == 0);
            Assert.True(perThread[0][2].Length == 0);
        }
        private void DistributedSchedule(int processCount, int threadCount)
        {
            int nodeCount = 100;
            IReadOnlyList <Gaussian> xExpected;
            Gaussian shiftExpected;
            IReadOnlyList <int[]> variablesUsedByNode;
            var schedulePerThread = parallelScheduleTest(processCount, nodeCount, out xExpected, out shiftExpected, out variablesUsedByNode);

            int[][][] schedulePerProcess = ParallelScheduler.ConvertToSchedulePerProcess(schedulePerThread);
            Dictionary <int, int>[] processLocalIndexOfArrayIndexPerProcess;
            IReadOnlyList <Compiler.Graphs.DistributedCommunicationInfo> distributedCommunicationInfos = ParallelScheduler.GetDistributedCommunicationInfos(schedulePerThread, variablesUsedByNode, out processLocalIndexOfArrayIndexPerProcess);

            Console.WriteLine("communication cost = {0}", TotalCommunicationCost(distributedCommunicationInfos));
            int[][][][][] schedulePerThreadPerProcess;
            if (threadCount > 1)
            {
                schedulePerThreadPerProcess = Util.ArrayInit(processCount, process =>
                                                             ParallelScheduler.GetSchedulePerThreadInProcess(schedulePerProcess[process], distributedCommunicationInfos[process].indices, threadCount)
                                                             );
            }
            else
            {
                schedulePerThreadPerProcess = Util.ArrayInit(processCount, process => default(int[][][][]));
            }

            IList <Gaussian>[] xResultPerProcess     = new IList <Gaussian> [processCount];
            Gaussian[]         shiftResultPerProcess = new Gaussian[processCount];
            bool debug = false;

            if (debug)
            {
                Assert.Equal(1, processCount);
                SequentialCommunicator comm = new SequentialCommunicator();
                DistributedScheduleTestProcess(comm, xResultPerProcess, shiftResultPerProcess, distributedCommunicationInfos[comm.Rank], schedulePerProcess[comm.Rank], schedulePerThreadPerProcess[comm.Rank]);
            }
            else
            {
                ThreadCommunicator.Run(processCount, comm =>
                                       DistributedScheduleTestProcess(comm, xResultPerProcess, shiftResultPerProcess, distributedCommunicationInfos[comm.Rank], schedulePerProcess[comm.Rank], schedulePerThreadPerProcess[comm.Rank])
                                       );
            }
            Gaussian[] arrayMarginal = new Gaussian[nodeCount];
            for (int process = 0; process < processCount; process++)
            {
                ////Console.WriteLine($"shift {shiftExpected} {shiftResultPerProcess[process]}");
                Assert.Equal(shiftExpected, shiftResultPerProcess[process]);
                foreach (var entry in processLocalIndexOfArrayIndexPerProcess[process])
                {
                    int arrayIndex = entry.Key;
                    int localIndex = entry.Value;
                    arrayMarginal[arrayIndex] = xResultPerProcess[process][localIndex];
                }
            }
            var arrayActual = new DistributionStructArray <Gaussian, double>(arrayMarginal);
            ////Console.WriteLine(arrayActual);
            double error = arrayActual.MaxDiff(xExpected);

            Assert.True(error < 1e-10);
        }
        public void ParallelSchedulerTest3()
        {
            var schedule = ParallelSchedulerTest(20000, 2);

            ParallelScheduler.WriteSchedule(schedule, true);
            Assert.True(schedule.Count == 10);
            Assert.True(schedule[3].Count == 2);
            //Assert.True(schedule[3][0].Count == 21);
            Assert.True(schedule[9].Count == 2);
            //Assert.True(schedule[9][0].Count == 3758);
        }
        internal void ParallelSchedulerTest()
        {
            ParallelScheduler ps = new ParallelScheduler();

            int[] nodes = Util.ArrayInit(5, i => ps.NewNode());
            ps.AddEdge(nodes[0], nodes[2]);
            ps.AddEdge(nodes[1], nodes[2]);
            ps.AddEdge(nodes[2], nodes[4]);
            ps.AddEdge(nodes[3], nodes[4]);
            var schedule = ps.GetScheduleWithBarriers(2);

            ParallelScheduler.WriteSchedule(schedule);
            // TODO: add assertion
        }
        public static List <List <List <int> > > ParallelSchedulerTest(int nodeCount, int parentCount)
        {
            Rand.Restart(0);
            ParallelScheduler ps = new ParallelScheduler();

            int[] nodes = Util.ArrayInit(nodeCount, i => ps.NewNode());
            for (int i = 0; i < nodeCount; i++)
            {
                if (i > parentCount)
                {
                    for (int j = 0; j < parentCount; j++)
                    {
                        int parent = Rand.Int(i);
                        if (!ps.ContainsEdge(nodes[parent], nodes[i]))
                        {
                            ps.AddEdge(nodes[parent], nodes[i]);
                        }
                    }
                }
            }
            var schedule = ps.GetScheduleWithBarriers(2);

            return(schedule);
        }
        private int[][][] parallelScheduleTest(int numThreads, int nodeCount, out IReadOnlyList <Gaussian> xMarginal, out Gaussian shiftMarginal, out IReadOnlyList <int[]> variablesUsedByNode)
        {
            int maxParentCount = 1;

            variablesUsedByNode = GenerateVariablesUsedByNode(nodeCount, maxParentCount);
            ParallelScheduler ps = new ParallelScheduler();

            ps.CreateGraph(variablesUsedByNode);
            var schedule = ps.GetScheduleWithBarriers(numThreads);

            ParallelScheduler.WriteSchedule(schedule, true);
            var schedulePerThread = ps.ConvertToSchedulePerThread(schedule, numThreads);

            var   nodeCountVar = Variable.Observed(nodeCount).Named("nodeCount");
            Range node         = new Range(nodeCountVar).Named("node");

            node.AddAttribute(new Sequential()
            {
                BackwardPass = true
            });
            var x = Variable.Array <double>(node).Named("x");

            x[node] = Variable.GaussianFromMeanAndPrecision(0, 1).ForEach(node);
            var   parentCount = Variable.Observed(variablesUsedByNode.Select(a => a.Length).ToArray(), node).Named("parentCount");
            Range parent      = new Range(parentCount[node]).Named("parent");
            var   indices     = Variable.Observed(variablesUsedByNode.ToArray(), node, parent).Named("indices");
            var   shift       = Variable.GaussianFromMeanAndPrecision(0, 1).Named("shift");

            shift.AddAttribute(new PointEstimate());
            using (Variable.ForEach(node))
            {
                var subArray = Variable.Subarray(x, indices[node]).Named("subArray");
                using (Variable.If(parentCount[node] == 1))
                {
                    Variable.ConstrainEqualRandom(subArray[0], Gaussian.FromMeanAndVariance(0, 1));
                }
                using (Variable.If(parentCount[node] == 2))
                {
                    Variable.ConstrainEqual(subArray[0], subArray[1] + 1);
                }
                Variable.ConstrainEqualRandom(shift, new Gaussian(1, 2));
            }

            InferenceEngine engine = new InferenceEngine();

            engine.NumberOfIterations   = 2;
            engine.OptimiseForVariables = new IVariable[] { x, shift };
            var xExpected = engine.Infer(x);
            //Console.WriteLine(xExpected);
            var shiftExpected = engine.Infer(shift);

            var   threadCount      = Variable.Observed(0).Named("threadCount");
            Range thread           = new Range(threadCount).Named("thread");
            var   blockCount       = Variable.Observed(0).Named("blockCount");
            Range gameBlock        = new Range(blockCount).Named("block");
            var   gameCountInBlock = Variable.Observed(default(int[][]), thread, gameBlock).Named("GameCountInBlock");
            Range gameInBlock      = new Range(gameCountInBlock[thread][gameBlock]).Named("gameInBlock");
            var   gamesInBlock     = Variable.Observed(default(int[][][]), thread, gameBlock, gameInBlock).Named("GamesInBlock");

            node.AddAttribute(new ParallelSchedule(gamesInBlock));

            threadCount.ObservedValue      = schedulePerThread.Length;
            blockCount.ObservedValue       = (schedulePerThread.Length == 0) ? 0 : schedulePerThread[0].Length;
            gameCountInBlock.ObservedValue = Util.ArrayInit(schedulePerThread.Length, t =>
                                                            Util.ArrayInit(schedulePerThread[t].Length, b => schedulePerThread[t][b].Length));
            gamesInBlock.ObservedValue = schedulePerThread;

            var xActual = engine.Infer <IReadOnlyList <Gaussian> >(x);

            //Debug.WriteLine(xActual);
            Assert.True(xExpected.Equals(xActual));
            var shiftActual = engine.Infer <Gaussian>(shift);

            Assert.True(shiftExpected.Equals(shiftActual));

            xMarginal     = xActual;
            shiftMarginal = shiftActual;
            return(schedulePerThread);
        }