public MPIGreedyCD(Intracommunicator comm, Rectangle totalSize, Rectangle imageSection, float[,] psf)
 {
     this.comm         = comm;
     this.imageSection = imageSection;
     psf2 = PSF.CalcPSFSquared(psf);
     aMap = PSF.CalcAMap(psf, totalSize, imageSection);
 }
        public GPUSerialCD(Rectangle totalSize, float[,] psf, float[,] psfSquared, int nrBatchIterations)
        {
            this.totalSize  = totalSize;
            psf2            = psfSquared;
            aMap            = PSF.CalcAMap(psf, totalSize);
            MaxLipschitz    = Residuals.GetMax(psfSquared);
            batchIterations = nrBatchIterations;

            c = new Context(ContextFlags.FastMath);
            var gpuIds = Accelerator.Accelerators.Where(id => id.AcceleratorType != AcceleratorType.CPU);

            if (gpuIds.Any())
            {
                RunsOnGPU   = true;
                accelerator = new CudaAccelerator(c, gpuIds.First().DeviceId);
            }
            else
            {
                Console.WriteLine("GPU vendor not supported. ILGPU switches to a !!!!VERY!!!! slow CPU implementation");
                RunsOnGPU   = false;
                accelerator = new CPUAccelerator(c, 4);
            }

            shrink  = accelerator.LoadAutoGroupedStreamKernel <Index2, ArrayView2D <float>, ArrayView2D <float>, ArrayView2D <float>, ArrayView <float>, ArrayView <Pixel> >(ShrinkKernel);
            updateX = accelerator.LoadAutoGroupedStreamKernel <ILGPU.Index, ArrayView2D <float>, ArrayView <Pixel> >(UpdateXKernel);
            updateB = accelerator.LoadAutoGroupedStreamKernel <Index2, ArrayView2D <float>, ArrayView2D <float>, ArrayView <Pixel> >(UpdateBKernel);
        }
        public FastSerialCD(Rectangle totalSize, Rectangle patchSize, float[,] psf, float[,] psfSquared, int processorLimit = -1)
        {
            this.patch   = patchSize;
            psf2         = psfSquared;
            aMap         = PSF.CalcAMap(psf, totalSize, patchSize);
            MaxLipschitz = Residuals.GetMax(psfSquared);

            parallelOptions = new ParallelOptions();
            parallelOptions.MaxDegreeOfParallelism = processorLimit;
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="totalSize"></param>
        /// <param name="psf"></param>
        /// <param name="processorCount">Number of async. processors to use</param>
        /// <param name="concurrentIterations">Number of async iterations each processor performs in one active set iteration</param>
        /// <param name="searchFraction"></param>
        public ParallelCoordinateDescent(Rectangle totalSize, float[,] psf, int processorCount = 8, int concurrentIterations = 1000, float searchFraction = 0.1f)
        {
            this.totalSize = totalSize;
            this.psf       = psf;
            this.psf2      = PSF.CalcPSFSquared(psf);
            this.aMap      = PSF.CalcAMap(psf, totalSize);

            this.processorCount       = processorCount;
            this.concurrentIterations = concurrentIterations;
            this.searchFraction       = searchFraction;
        }
        public ApproxFast(Rectangle totalSize, float[,] psf, int threadCount, int blockSize, float randomFraction, float searchFraction, bool useCDColdStart, bool useAcceleration = true, bool useRestarting = true)
        {
            this.totalSize = totalSize;
            this.psf       = psf;
            this.psf2      = PSF.CalcPSFSquared(psf);
            MaxLipschitz   = (float)PSF.CalcMaxLipschitz(psf);
            this.aMap      = PSF.CalcAMap(psf, totalSize);

            this.threadCount     = threadCount;
            this.blockSize       = blockSize;
            this.randomFraction  = randomFraction;
            this.searchFraction  = searchFraction;
            this.useAcceleration = useAcceleration;
            this.useRestarting   = useRestarting;
        }
        public void ResetLipschitzMap(float[,] psf)
        {
            var psf2Local = PSF.CalcPSFSquared(psf);
            var maxFull   = Residuals.GetMax(psf2Local);

            MaxLipschitz = maxFull;
            aMap         = PSF.CalcAMap(psf, patch);

            var maxCut = Residuals.GetMax(psf2);

            for (int i = 0; i < psf2.GetLength(0); i++)
            {
                for (int j = 0; j < psf2.GetLength(1); j++)
                {
                    psf2[i, j] *= (maxFull / maxCut);
                }
            }
        }
        public void ResetAMap(float[,] psf)
        {
            var psf2Local = PSF.CalcPSFSquared(psf);
            var maxFull   = Residuals.GetMax(psf2Local);

            aMap     = PSF.CalcAMap(psf, totalSize);
            this.psf = psf;

            var maxCut = Residuals.GetMax(psf2);

            for (int i = 0; i < psf2.GetLength(0); i++)
            {
                for (int j = 0; j < psf2.GetLength(1); j++)
                {
                    psf2[i, j] *= (maxFull / maxCut);
                }
            }
        }