public void ThrowOnDuplicateId() { var job = new ParallelJob(new ConsoleLogProvider()) .AddTask("a", () => { }); TestUtility.ShouldFail <InvalidOperationException>(() => job.AddTask("a", () => { }), "has already been added"); }
public void UnresolvableDependencies() { var result = new ConcurrentQueue <string>(); var job = new ParallelJob(new ConsoleLogProvider()) .AddTask("a", () => result.Enqueue("a"), new[] { "c", "d", "e" }) .AddTask("b", () => result.Enqueue("b"), new[] { "c", "d", "e" }) .AddTask("c", () => result.Enqueue("c"), new[] { "d", "e" }) .AddTask("d", () => result.Enqueue("d"), new[] { "a" }) .AddTask("e", () => result.Enqueue("e")); TestUtility.ShouldFail <InvalidOperationException>(() => job.RunAllTasks(), "Unable to resolve required task dependencies"); Assert.AreEqual("e", string.Concat(result)); }
// Start is called before the first frame update void Start() { SimpleJob simpleJob = new SimpleJob { number = myNumber, data = myData, }; ParallelJob parallelJob = new ParallelJob { number = myNumber, data = myData, }; TransformJob transformJob = new TransformJob { number = myNumber, data = myData, deltaTime = Time.deltaTime, }; simpleJobHandle = simpleJob.Schedule(); parallelJobHandle = parallelJob.Schedule(myData.Length, 32, simpleJobHandle); transformJobHandle = transformJob.Schedule(transformAccessArray, parallelJobHandle); // dependency like a->b->c... JobHandle.ScheduleBatchedJobs(); simpleJobHandle.Complete(); parallelJobHandle.Complete(); transformJobHandle.Complete(); if (simpleJobHandle.IsCompleted) { Debug.Log("simple job result " + simpleJob.data[0]); } if (parallelJobHandle.IsCompleted) { for (int i = 0; i < myData.Length; ++i) { Debug.Log("parallel job result " + parallelJob.data[i]); } } myData.Dispose(); transformAccessArray.Dispose(); }
public void SimpleDependency() { var result = new ConcurrentQueue <string>(); var job = new ParallelJob(new ConsoleLogProvider()) .AddTask("a", () => { Task.Delay(50).Wait(); result.Enqueue("a"); }) .AddTask("b", () => result.Enqueue("b"), new [] { "a" }) .AddTask("c", () => result.Enqueue("c")); job.RunAllTasks(); Assert.AreEqual("cab", string.Concat(result)); }
public void ComplexDependencies() { var result = new ConcurrentQueue <string>(); var job = new ParallelJob(new ConsoleLogProvider()) .AddTask("a", () => result.Enqueue("a"), new[] { "c", "d", "e" }) .AddTask("b", () => result.Enqueue("b"), new[] { "c", "d", "e" }) .AddTask("c", () => result.Enqueue("c"), new[] { "d", "e" }) .AddTask("d", () => result.Enqueue("d"), new[] { "e" }) .AddTask("e", () => result.Enqueue("e")); job.RunAllTasks(); var sequence = string.Concat(result); Assert.IsTrue(sequence == "edcab" || sequence == "edcba"); }
public void FindPrimesInAGeneratedSample() { results.text = ("\n Starting..."); //start a stopper to benchmark System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); sw.Start(); NativeArray <int> input = new NativeArray <int>(inputSize, Allocator.TempJob); //store data how many prime numbers we found -> make an array element for each thread to avoid racing (multiple threads trying to write the same element can cause trouble) NativeArray <int> numberOfFoundPrimes = new NativeArray <int>(numberOfThreads, Allocator.TempJob); //initialize the sample for (int i = 0; i < inputSize; i++) { input[i] = UnityEngine.Random.Range(0, 10); } jobData = new ParallelJob(); jobData.input = input; jobData.nthreads = numberOfThreads; jobData.inputSize = inputSize; jobData.foundPrimes = numberOfFoundPrimes; //pass to scheduler - divide the input interval with the threads so we get (thread number) of chunks and we can calculate thread id's in the Execute method //(roughly the same as static scheduling) handle = jobData.Schedule(inputSize, inputSize / numberOfThreads); //waiting for all threads to finish handle.Complete(); //summarize the total prime numbers we found on each thread int totalFoundPrimes = 0; for (int i = 0; i < numberOfThreads; i++) { totalFoundPrimes += jobData.foundPrimes[i]; } //stop our stopper sw.Stop(); results.text += ("\n Done! Elapsed time: " + sw.ElapsedMilliseconds / 1000f + "\n Found: " + totalFoundPrimes); // disposal of nativearrays input.Dispose(); numberOfFoundPrimes.Dispose(); }
private void RunDemo() { ParallelJob parallelJob = new ParallelJob { Number = m_MyNumber, Data = m_MyData }; m_ParallelJobHandle = parallelJob.Schedule(m_MyData.Length, 32); JobHandle.ScheduleBatchedJobs(); m_ParallelJobHandle.Complete(); if (m_ParallelJobHandle.IsCompleted) { for (int i = 0; i < m_MyData.Length; i++) { Debug.Log(parallelJob.Data[i]); } FreeMemoryData(); } }
static void TestJob() { var j1 = new Job((job) => { Debug.Log("j1"); job.Success(); }); var j2 = new Job((job) => { Debug.Log("j2"); job.Success(); }); var j3 = new Job((job) => { Debug.Log("j3"); job.Fail(); }); var j4 = new Job((job) => { Debug.Log("j4"); job.Success(); }); var parallel = new ParallelJob(); parallel.AddChild(j1); parallel.AddChild(j2); parallel.AddChild(j3); parallel.AddChild(j4); parallel.Run((job) => { Debug.Log("parallel success"); }, (Job) => { var children = (Job as ParallelJob)?.m_ErrorChildren; Debug.Log("parallel error"); }, (job) => { Debug.Log("parallel progress:" + job.Progress); }); }
public void StopOnException() { var result = new ConcurrentQueue <string>(); var job = new ParallelJob(new ConsoleLogProvider()) .AddTask("a", () => { Task.Delay(50).Wait(); result.Enqueue("a"); }) .AddTask("b", () => { result.Enqueue("b"); throw new InvalidOperationException("Test exception"); }) .AddTask("c", () => result.Enqueue("c"), new[] { "a" }); var e = TestUtility.ShouldFail <InvalidOperationException>(() => job.RunAllTasks(), "Test exception"); Assert.AreEqual("ab", string.Concat(result.OrderBy(a => a))); }
public void CorrectlyCancels() { var lockAStart = new SemaphoreSlim(0, 1); var lockAFinished = new SemaphoreSlim(0, 1); var lockBFinished = new SemaphoreSlim(0, 1); var result = new ConcurrentQueue <string>(); var job = new ParallelJob(new ConsoleLogProvider()) .AddTask("a", () => { lockAStart.Wait(); result.Enqueue("a"); lockAFinished.Release(); }) .AddTask("b", () => { result.Enqueue("b"); lockBFinished.Release(); }) .AddTask("c", () => result.Enqueue("c"), new[] { "a" }); var cancellationTokenSource = new CancellationTokenSource(); var task = Task.Run(() => job.RunAllTasks(0, cancellationTokenSource.Token)); lockBFinished.Wait(); // Wait for "b" to finish. cancellationTokenSource.Cancel(); var e = TestUtility.ShouldFail <AggregateException>(() => task.Wait()); Assert.IsTrue(e.InnerException is OperationCanceledException); // Only "b" should be completed. "a" is waiting for lock, "c" i waiting for "a". Assert.AreEqual("b", TestUtility.Dump(result)); lockAStart.Release(); // Allow "a" to run now. // "a" is expected to complete also, since it has been started prior to cancellation. lockAFinished.Wait(); // Wait for "a" to finish. Thread.Sleep(50); // Wait a little longer, but "c" should still not start, because it had not started prior to cancellation. Assert.AreEqual("b, a", TestUtility.Dump(result)); }
public void CorrectlyCancels() { var lockAStart = new SemaphoreSlim(0, 1); var lockAFinished = new SemaphoreSlim(0, 1); var lockBFinished = new SemaphoreSlim(0, 1); var result = new ConcurrentQueue <string>(); var job = new ParallelJob(new ConsoleLogProvider()) .AddTask("a", () => { result.Enqueue("a1"); lockAStart.Wait(); result.Enqueue("a2"); lockAFinished.Release(); }) .AddTask("b", () => { result.Enqueue("b"); lockBFinished.Release(); }) .AddTask("c", () => result.Enqueue("c"), new[] { "a" }); var cancellationTokenSource = new CancellationTokenSource(); var task = Task.Run(() => job.RunAllTasks(0, cancellationTokenSource.Token)); lockBFinished.Wait(); // Wait for "b" to finish. cancellationTokenSource.Cancel(); var e = TestUtility.ShouldFail <AggregateException>(() => task.Wait()); Assert.IsTrue(e.InnerException is OperationCanceledException); // only b completes immediately after cancellation Assert.AreEqual("a1b", string.Concat(result)); lockAStart.Release(); // Allow "a" to run now. // a should complete also, since it has been started prior to cancellation lockAFinished.Wait(); // Wait for "a" to finish. Assert.AreEqual("a1ba2", string.Concat(result)); }
private ParallelJob PrepareGeneratorsJob(IList <IGenerator> generators) { var allDependencies = ResolveDependencies(generators); var validDependencies = FilterInvalidDependencies(generators, allDependencies); var job = new ParallelJob(_logProvider); foreach (var generator in generators) { var generatorName = GetGeneratorName(generator); validDependencies.TryGetValue(generatorName, out var generatorDependencies); job.AddTask(generatorName, () => { _logger.Info(() => $"Starting {generatorName}."); var sw = Stopwatch.StartNew(); generator.Generate(); _performanceLogger.Write(sw, () => $"{generatorName} completed."); }, generatorDependencies ?? new List <string>()); } return(job); }
private void runDemo() { ParallelJob parallelJob = new ParallelJob { number = myNumber, data = myData }; myParallelJobHandle = parallelJob.Schedule(myData.Length, 32); JobHandle.ScheduleBatchedJobs(); myParallelJobHandle.Complete(); if (myParallelJobHandle.IsCompleted) { for (int i = 0; i < myData.Length; i++) { Debug.Log(parallelJob.data[i]); } freeMemoryData(); } }
// Update is called once per frame void Update() { if (useThread) { ParallelJob tempParallelJob = new ParallelJob() { deltaTime = Time.deltaTime }; NativeArray <float3> eulerAngles = new NativeArray <float3>(goList.Count, Allocator.TempJob); for (int i = 0; i < goList.Count; ++i) { eulerAngles[i] = goList[i].transform.eulerAngles; } tempParallelJob.eulerAngles = eulerAngles; JobHandle jobHandle = tempParallelJob.Schedule(goList.Count, 10); jobHandle.Complete(); for (int i = 0; i < goList.Count; ++i) { goList[i].transform.eulerAngles = eulerAngles[i]; } eulerAngles.Dispose(); } else { foreach (var item in goList) { item.transform.eulerAngles += new Vector3(0, 30 * Time.deltaTime, 0); for (int i = 0; i < 1000; ++i) { float result = math.exp10(math.sqrt(5 * 6)); } } } }
// Start is called before the first frame update void Start() { ParallelJob parallelJob = new ParallelJob { number = myNumber, data = myData, }; parallelJobHandle = parallelJob.Schedule(myData.Length, 32); JobHandle.ScheduleBatchedJobs(); parallelJobHandle.Complete(); if (parallelJobHandle.IsCompleted) { for (int i = 0; i < myData.Length; ++i) { Debug.Log(parallelJob.data[i]); } } myData.Dispose(); }