/// <summary>
        /// Consumer-producer based multithreading work distribution
        /// Each thread waits for a new Assignment to be added to availableAssignments queue
        /// Most of the time is number of items in availableAssignments expected to be several times larger than number of threads
        /// </summary>
        protected void Consume()
        {
            MT.InitThreadData();

            while (!availableAssignments.IsEmpty || finishedAssignments < totalNumberOfAssignments - threads || NetworkWorker.assignmentsAtClients > 0)
            {
                availableAssignments.TryDequeue(out Assignment newAssignment);

                if (!progressData.Continue) // test whether rendering should end (Stop button pressed)
                {
                    return;
                }

                if (newAssignment == null) // TryDequeue was not successful
                {
                    continue;
                }

                float[] colorArray = newAssignment.Render(false, renderer, progressData);
                BitmapMerger(colorArray, newAssignment.x1, newAssignment.y1, newAssignment.x2 + 1, newAssignment.y2 + 1);

                if (newAssignment.stride == 1)
                {
                    finishedAssignments++;
                    assignmentRoundsFinished++;
                }
                else
                {
                    newAssignment.stride = newAssignment.stride >> 1; // stride values: 8 > 4 > 2 > 1
                    assignmentRoundsFinished++;
                    availableAssignments.Enqueue(newAssignment);
                }
            }
        }
示例#2
0
 /// <summary>
 /// Routine of one worker-thread.
 /// Result image and rendering progress are the only two shared objects.
 /// </summary>
 /// <param name="spec">Thread-specific data (worker-thread-selector).</param>
 private void RenderWorker(object spec)
 {
     if (spec is WorkerThreadInit init)
     {
         MT.InitThreadData();
         init.rend.RenderRectangle(init.image, 0, 0, init.width, init.height, init.sel);
     }
 }
示例#3
0
        /// <summary>
        /// Consumer-producer based multithreading work distribution
        /// Each thread waits for a new Assignment to be added to availableAssignments queue
        /// Most of the time is number of items in availableAssignments expected to be several times larger than number of threads
        /// </summary>
        protected void Consume()
        {
            // Set TLS.
            MT.InitThreadData();
            MT.SetRendering(scene, imageFunction, renderer);

            // Animation time (fore debugging animated scenes).
            if (scene is ITimeDependent sc)
            {
                sc.Time = 0.0;
            }

            while (!availableAssignments.IsEmpty ||
                   finishedAssignments < totalNumberOfAssignments - threads ||
                   NetworkWorker.assignmentsAtClients > 0)
            {
                availableAssignments.TryDequeue(out Assignment newAssignment);

                if (!progressData.Continue) // test whether rendering should end (Stop button pressed)
                {
                    return;
                }

                if (newAssignment == null) // TryDequeue was not successful
                {
                    continue;
                }

                float[] colorArray = newAssignment.Render(false, renderer, progressData);
                BitmapMerger(colorArray, newAssignment.x1, newAssignment.y1, newAssignment.x2 + 1, newAssignment.y2 + 1);

                if (newAssignment.stride == 1)
                {
                    finishedAssignments++;
                    assignmentRoundsFinished++;
                }
                else
                {
                    newAssignment.stride >>= 1; // stride values: 8 > 4 > 2 > 1
                    assignmentRoundsFinished++;
                    availableAssignments.Enqueue(newAssignment);
                }
            }
        }
示例#4
0
        /// <summary>
        /// [Re]-renders the whole image (in separate thread). OLD VERSION!!!
        /// </summary>
        private void RenderImage_OLD()
        {
            Cursor.Current = Cursors.WaitCursor;

            // determine output image size:
            int width = ImageWidth;

            if (width <= 0)
            {
                width = panel1.Width;
            }

            int height = ImageHeight;

            if (height <= 0)
            {
                height = panel1.Height;
            }

            Bitmap newImage = new Bitmap(width, height, PixelFormat.Format24bppRgb);

            int threads = CheckMultithreading.Checked ? Environment.ProcessorCount : 1;
            int t; // thread ordinal number

            WorkerThreadInit[] wti = new WorkerThreadInit[threads];

            // separate renderer, image function and the scene for each thread (safety precaution)
            for (t = 0; t < threads; t++)
            {
                IRayScene      sc  = FormSupport.getScene();
                IImageFunction imf = getImageFunction(sc, width, height);
                IRenderer      r   = getRenderer(imf, width, height);
                wti[t] = new WorkerThreadInit(r, sc as ITimeDependent, imf as ITimeDependent, newImage, width, height, t, threads);
            }

            progress.SyncInterval = ((width * (long)height) > (2L << 20)) ? 3000L : 1000L;
            progress.Reset();
            CSGInnerNode.ResetStatistics();

            lock (sw)
                sw.Restart();

            if (threads > 1)
            {
                Thread[] pool = new Thread[threads];
                for (t = 0; t < threads; t++)
                {
                    pool[t] = new Thread(new ParameterizedThreadStart(RenderWorker));
                }
                for (t = threads; --t >= 0;)
                {
                    pool[t].Start(wti[t]);
                }

                for (t = 0; t < threads; t++)
                {
                    pool[t].Join();
                    pool[t] = null;
                }
            }
            else
            {
                MT.InitThreadData();
                wti[0].rend.RenderRectangle(newImage, 0, 0, width, height);
            }

            long elapsed;

            lock (sw)
            {
                sw.Stop();
                elapsed = sw.ElapsedMilliseconds;
            }

            string msg = string.Format(CultureInfo.InvariantCulture,
                                       "{0:f1}s  [ {1}x{2}, mt{3}, r{4:#,#}k, i{5:#,#}k, bb{6:#,#}k, t{7:#,#}k ]",
                                       1.0e-3 * elapsed, width, height, threads,
                                       (Intersection.countRays + 500L) / 1000L,
                                       (Intersection.countIntersections + 500L) / 1000L,
                                       (CSGInnerNode.countBoundingBoxes + 500L) / 1000L,
                                       (CSGInnerNode.countTriangles + 500L) / 1000L);

            SetText(msg);
            Console.WriteLine(@"Rendering finished: " + msg);
            SetImage(newImage);

            Cursor.Current = Cursors.Default;

            StopRendering();
        }
示例#5
0
        /// <summary>
        /// Creates threadpool and starts all threads on Consume method
        /// Thread which calls this method will take care of preparing assignments and receiving rendered images from RenderClients meanwhile
        /// </summary>
        public void RunThreads()
        {
            pool = new Thread[MT.threads];

            AssignNetworkWorkerToStream();

            WaitHandle[] waitHandles = new WaitHandle[MT.threads];

            // Multiply animated instances.
            int i;

            // Scene definitions.
            if (scenes[0] is ITimeDependent scenea)
            {
                scenea.Time = time;
                scenes      = new IRayScene[MT.threads];
                for (i = 0; i < MT.threads; i++)
                {
                    scenes[i] = i == 0 ? (IRayScene)scenea : (IRayScene)scenea.Clone();
                }
            }

            // Image functions.
            if (imageFunctions[0] is ITimeDependent imfa)
            {
                imfa.Time      = time;
                imageFunctions = new IImageFunction[MT.threads];
                for (i = 0; i < MT.threads; i++)
                {
                    imageFunctions[i] = i == 0 ? (IImageFunction)imfa : (IImageFunction)imfa.Clone();
                }
            }

            // Renderers.
            if (renderers[0] is ITimeDependent renda)
            {
                renda.Time = time;
                renderers  = new IRenderer[MT.threads];
                for (i = 0; i < MT.threads; i++)
                {
                    renderers[i] = i == 0 ? (IRenderer)renda : (IRenderer)renda.Clone();
                }
            }

            for (i = 0; i < MT.threads; i++)
            {
                EventWaitHandle handle = new EventWaitHandle(false, EventResetMode.ManualReset);

                // Thread-specific instances: thread's id.
                int tid = i;

                Thread newThread = new Thread(() =>
                {
                    // Set TLS.
                    MT.threadID = tid;
                    MT.InitThreadData();
                    MT.SetRendering(
                        scenes[Math.Min(tid, scenes.Length - 1)],
                        imageFunctions[Math.Min(tid, imageFunctions.Length - 1)],
                        renderers[Math.Min(tid, renderers.Length - 1)]);

                    Consume();

                    // Signal finishing the work.
                    handle.Set();
                });

                newThread.Name = "RenderThread #" + i;
                pool[i]        = newThread;
                newThread.Start();

                waitHandles[i] = handle;
            }

            mainRenderThread = pool[0];

            Thread imageReceiver = new Thread(RenderedImageReceiver);

            imageReceiver.Name = "ImageReceiver";
            imageReceiver.Start();

            WaitHandle.WaitAll(waitHandles);

            if (networkWorkers?.Count > 0)
            {
                foreach (NetworkWorker worker in networkWorkers) // sends ending assignment to all clients
                {
                    worker.SendSpecialAssignment(Assignment.AssignmentType.Ending);
                }
            }

            // Reset the pool-thread.
            pool = null;
        }
示例#6
0
文件: Form1.cs 项目: Popa611/grcis
        /// <summary>
        /// [Re]-renders the whole image (in separate thread). OLD VERSION!!!
        /// </summary>
        private void RenderImage_OLD()
        {
            Cursor.Current = Cursors.WaitCursor;

            // Determine output image size.
            int width = ImageWidth;

            if (width <= 0)
            {
                width = panel1.Width;
            }

            int height = ImageHeight;

            if (height <= 0)
            {
                height = panel1.Height;
            }

            Bitmap newImage = new Bitmap(width, height, PixelFormat.Format24bppRgb);

            int threads = CheckMultithreading.Checked ? Environment.ProcessorCount : 1;
            int t; // thread ordinal number
            int superSampling = (int)NumericSupersampling.Value;

            WorkerThreadInit[] wti = new WorkerThreadInit[threads];

            // 1. preprocessing - compute simulation, animation data, etc.
            _ = FormSupport.getScene(true, out _, out _, superSampling, TextParam.Text);

            // Separate renderer, image function and the scene for each thread (safety precaution).
            for (t = 0; t < threads; t++)
            {
                // 2. initialize data for regular frames (using the pre-computed context).
                IRayScene sc = FormSupport.getScene(
                    false,
                    out IImageFunction imf,
                    out IRenderer rend,
                    superSampling,
                    TextParam.Text);

                // IImageFunction.
                imf        = getImageFunction(imf, sc);
                imf.Width  = width;
                imf.Height = height;

                // IRenderer.
                if (rend == null) // not defined in the script
                {
                    rend = getRenderer();
                }
                rend.ImageFunction = imf;
                rend.Width         = width;
                rend.Height        = height;
                rend.Adaptive      = 8;
                rend.ProgressData  = progress;

                wti[t] = new WorkerThreadInit(rend, sc as ITimeDependent, imf as ITimeDependent, newImage, width, height, t, threads);
            }

            progress.SyncInterval = ((width * (long)height) > (2L << 20)) ? 3000L : 1000L;
            progress.Reset();
            CSGInnerNode.ResetStatistics();

            lock (sw)
                sw.Restart();

            if (threads > 1)
            {
                Thread[] pool = new Thread[threads];
                for (t = 0; t < threads; t++)
                {
                    pool[t] = new Thread(new ParameterizedThreadStart(RenderWorker));
                }
                for (t = threads; --t >= 0;)
                {
                    pool[t].Start(wti[t]);
                }

                for (t = 0; t < threads; t++)
                {
                    pool[t].Join();
                    pool[t] = null;
                }
            }
            else
            {
                MT.InitThreadData();
                wti[0].rend.RenderRectangle(newImage, 0, 0, width, height);
            }

            long elapsed;

            lock (sw)
            {
                sw.Stop();
                elapsed = sw.ElapsedMilliseconds;
            }

            string msg = string.Format(CultureInfo.InvariantCulture,
                                       "{0:f1}s  [ {1}x{2}, mt{3}, r{4:#,#}k, i{5:#,#}k, bb{6:#,#}k, t{7:#,#}k ]",
                                       1.0e-3 * elapsed, width, height, threads,
                                       (Intersection.countRays + 500L) / 1000L,
                                       (Intersection.countIntersections + 500L) / 1000L,
                                       (CSGInnerNode.countBoundingBoxes + 500L) / 1000L,
                                       (CSGInnerNode.countTriangles + 500L) / 1000L);

            SetText(msg);
            Console.WriteLine(@"Rendering finished: " + msg);
            SetImage(newImage);

            Cursor.Current = Cursors.Default;

            StopRendering();
        }