Пример #1
0
        public unsafe void ComputeMandelbrotSet(
            uint[,] iterations,
            int width, int height,
            double offsetX, double offsetY, double zoom,
            uint maxIterations,
            bool doublePrecision,
            ref bool cancel)
        {
            Resize(width, height);

            // Precompute the pixels coordinates.
            double startX = -(width / (height * zoom)) + offsetX;
            double startY = -1.0 / zoom + offsetY;
            double scale  = 2 / (height * zoom);

            if (doublePrecision)
            {
                _doubleKernel(new Index2(width, height), _deviceMemory.View, width, height, startX, startY, scale, maxIterations);
            }
            else
            {
                _singleKernel(new Index2(width, height), _deviceMemory.View, width, height, (float)startX, (float)startY, (float)scale, maxIterations);
            }

            fixed(uint *ptr = iterations)
            {
                using var viewArrayWrapper = ViewPointerWrapper.Create(new IntPtr(ptr));
                var arrayView = new ArrayView <uint>(viewArrayWrapper, 0, iterations.Length);

                _deviceMemory.CopyTo(arrayView, 0);
                _gpu.Synchronize();
            }
        }
Пример #2
0
        public unsafe void ComputeMandelbrotSet(
            uint[,] iterations,
            int width, int height,
            double offsetX, double offsetY, double zoom,
            uint maxIterations,
            bool doublePrecision,
            ref bool cancel)
        {
            Resize(width, height);

            var doubleOverhead   = doublePrecision ? 32 : 1;
            var cores            = _gpu.NumMultiprocessors * 128; // TODO ILGPU proper number of CUDA cores per multi processor.
            var maxPixelPerBatch = 200L * _gpu.ClockRate * cores / (doubleOverhead * maxIterations);

            var blockSizeX = 16;
            var blockSizeY = 8;
            var gridX      = DivUp(width, blockSizeX);
            var gridY      = DivUp(height, blockSizeY);
            var maxBlocks  = DivUp(checked ((int)maxPixelPerBatch), blockSizeX * blockSizeY);
            var maxBlocksY = DivUp(maxBlocks, gridX);

            // Precompute the pixels coordinates.
            double startX = -(width / (height * zoom)) + offsetX;
            double startY = -1.0 / zoom + offsetY;
            double scale  = 2 / (height * zoom);

            // Batch the mandelbrot computation into sets of block so that we avoid hitting the Windows watchdog timer for CUDA (5 seconds on Windows 10).
            for (int blockOffsetY = 0; blockOffsetY < gridY; blockOffsetY += maxBlocksY)
            {
                if (cancel)
                {
                    break;
                }

                var lp = ((gridX, Math.Min(gridY, maxBlocksY)), (blockSizeX, blockSizeY));

                if (doublePrecision)
                {
                    _gpu.Launch(DoubleKernel, lp, _deviceMemory.View, width, height, blockOffsetY * blockSizeY, startX, startY, scale, maxIterations);
                }
                else
                {
                    _gpu.Launch(SingleKernel, lp, _deviceMemory.View, width, height, blockOffsetY * blockSizeY, startX, startY, scale, maxIterations);
                }
            }

            fixed(uint *ptr = iterations)
            {
                using var viewArrayWrapper = ViewPointerWrapper.Create(new IntPtr(ptr));
                var arrayView = new ArrayView <uint>(viewArrayWrapper, 0, iterations.Length);

                _deviceMemory.CopyTo(arrayView, 0);
            }
        }