Пример #1
0
        void PrepareParallelTasks()
        {
            //create a collection of task that will run in parallel on several threads.
            //the number of threads and tasks to perform are not dependent.
            _multiParallelTasks = new MultiThreadedParallelTaskCollection(NUM_OF_SVELTO_THREADS, true);
            //in this case though we just want to perform a task for each thread
            //ParticlesCPUKernel is a task (IEnumerator) that executes the
            //algebra operation on the particles. Each task perform the operation
            //on particlesPerThread particles
#if BENCHMARK
            pc = new ParticleCounter(particlesPerThread - 16);
#else
            _pc = new ParticleCounter(0);
#endif
#if OLD_STYLE
            //calculate the number of particles per thread
            uint particlesPerThread = _particleCount / NUM_OF_SVELTO_THREADS;
            for (int i = 0; i < NUM_OF_SVELTO_THREADS; i++)
            {
                _multiParallelTasks.Add(new ParticlesCPUKernel((int)(particlesPerThread * i), (int)particlesPerThread, this, _pc));
            }
#else
            var particlesCpuKernel = new ParticlesCPUKernel(this);
            _multiParallelTasks.Add(ref particlesCpuKernel, (int)_particleCount);
#endif
        }
Пример #2
0
    public IEnumerator TestMultiThreadParallelTaskReset()
    {
        var test = new MultiThreadedParallelTaskCollection("test", 4, false);

        Token token = new Token();

        int done = 0;

        test.onComplete += () => done++;
        test.Add(new WaitEnumerator(token));
        test.Add(new WaitEnumerator(token));
        test.Add(new WaitEnumerator(token));
        test.Add(new WaitEnumerator(token));

        test.Run();

        yield return(new WaitForSeconds(0.5f));

        token.count = 3;

        test.Stop();

        test.Complete();
        test.Dispose();

        Assert.That(done == 1);
        Assert.AreEqual(4, token.count);
    }
Пример #3
0
        IEnumerator WaitForEntityViewsAdded()
        {
//Engines are usually designed to be able to cope with dynamic adding and removing of entities,
//but in this case I needed to know when the entities are ready to be processed. This wouldn't be
//strictly necessary if I coded the engine in a different way, but I decided to keep it simpler and more readable.
//That's why the engine starts immediately a task that waits for the EntityViews to be added(it assumes that all the
//entities are created on the same frame).This demo aims to be allocation free during the main execution, that's
//why all the tasks are prepared before hand. In this step, we prepare just one task that runs the main operations
//that must be executed on the entities.
            int count = 0;

#if FIRST_TIER_EXAMPLE || SECOND_TIER_EXAMPLE
            ReadOnlyCollectionStruct <BoidEntityView> _entityViews;
#endif
#if FOURTH_TIER_EXAMPLE || THIRD_TIER_EXAMPLE
            BoidEntityView[] _entityViews;
#endif
            do
            {
#if FIRST_TIER_EXAMPLE || SECOND_TIER_EXAMPLE
                _entityViews = entitiesDB.QueryEntityViews <BoidEntityView>();
                count        = _entityViews.Count;
#endif
#if FOURTH_TIER_EXAMPLE || THIRD_TIER_EXAMPLE
                _entityViews = entitiesDB.QueryEntities <BoidEntityView>(ExclusiveGroups.BoidGroup, out count);
#endif
                yield return(null);
            } while (count == 0);

#if TURBO_EXAMPLE
            int numberOfThreads = (int)Mathf.Min(NUM_OF_THREADS, count);

            var countn = count / numberOfThreads;

            _multiParallelTask = new MultiThreadedParallelTaskCollection((uint)numberOfThreads);

            for (int i = 0; i < numberOfThreads; i++)
            {
                _multiParallelTask.Add(new BoidEnumerator(_entityViews, countn * i, countn));
            }
#elif FIRST_TIER_EXAMPLE || SECOND_TIER_EXAMPLE || THIRD_TIER_EXAMPLE || FOURTH_TIER_EXAMPLE
            _boidEnumerator = new BoidEnumerator(_entityViews, 0, count);
#endif
            _testEnumerator = new TestEnumerator(_printEntityView);

            Update().RunOnScheduler(StandardSchedulers.updateScheduler);
        }
        public IEnumerator ParallelMultiThread()
        {
            yield return(null);

            var parallelMultiThread = new MultiThreadedParallelTaskCollection("test", 2, true);

            parallelMultiThread.Add(new SlowTask());
            parallelMultiThread.Add(new SlowTask());

            var sw = System.Diagnostics.Stopwatch.StartNew();

            parallelMultiThread.Complete();
            parallelMultiThread.Dispose();

            sw.Stop();

            Assert.That(sw.ElapsedMilliseconds, Is.AtLeast(900));
            Assert.That(sw.ElapsedMilliseconds, Is.AtMost(1100));
        }
        public IEnumerator TestMultiThreadParallelTaskCompletes()
        {
            yield return(null);

            var test = new MultiThreadedParallelTaskCollection("test", 4, false);

            bool done = false;

            test.onComplete += () => done = true;
            Token token = new Token();

            test.Add(new WaitEnumerator(token));
            test.Add(new WaitEnumerator(token));
            test.Add(new WaitEnumerator(token));
            test.Add(new WaitEnumerator(token));

            var multiThreadRunner = new MultiThreadRunner("test", true);

            test.RunOnScheduler(multiThreadRunner);
            DateTime now = DateTime.Now;

            yield return(null);

            while (test.isRunning)
            {
                yield return(null);
            }

            var totalSeconds = (DateTime.Now - now).TotalSeconds;

            Assert.Greater(totalSeconds, 1.9);
            Assert.Less(totalSeconds, 2.1);
            Assert.That(done, Is.True);
            Assert.AreEqual(4, token.count);

            test.Dispose();
            multiThreadRunner.Dispose();
        }
Пример #6
0
    public IEnumerator TestStopMultiThreadParallelTask()
    {
        var test = new MultiThreadedParallelTaskCollection("test", 4, false);

        Token token = new Token();
        bool  done  = false;

        test.onComplete += () => done = true;
        test.Add(new WaitEnumerator(token));
        test.Add(new WaitEnumerator(token));
        test.Add(new WaitEnumerator(token));
        test.Add(new WaitEnumerator(token));

        test.Run();

        yield return(new WaitForSeconds(0.5f));

        test.Stop();
        test.Dispose();

        Assert.That(done, Is.False);
        Assert.AreEqual(token.count, 0);
    }
Пример #7
0
        public BoidsSimulationEngine(ThreadSynchronizationSignal synchronizationSignal, Param param, int boidCount)
        {
            this.param = param;

            //Svelto.Tasks is based on the concept of tasks and runners to run them. Runners can be many. I may even
            //write a Unity Jobs runner one day. The MultiThreadRunner is the Svelto.Tasks runner to run tasks
            //on other threads. For more information please check my Svelto.Tasks articles.
            //this runner will run the main loop
            _runner = new MultiThreadRunner("BoidSimulationSystem", 1);
            //MultiThreadedParallelTaskCollection enables massive parallelism on the CPU. I will create a Svelto.Tasks
            //job for each boid. These jobs will be then spread on 16 threads on an I7.
            _parallelJobs = new MultiThreadedParallelTaskCollection("BoidsSimulationJobs", (uint)(System.Environment.ProcessorCount * 2), true);
            //Svelto Tasks Jobs must be struct, as they must be instantiated multiple times, the first one
            //will be used as blueprint fro the other ones
            var jobInstance = new BoidSimulationJob(this, boidCount);

            //Create boidCount jobs and add them
            _parallelJobs.Add(ref jobInstance, boidCount);

            //the Synchronization signal is used to send signals between threads and allow synchronizations
            _synchronizationSignal = synchronizationSignal;
            _boidCount             = boidCount;
        }