public static void Execute(int[,] clusters)
        {
            using (MemoryBuffer2D <int> clusterBuff = HardwareAcceleratorManager.GPUAccelerator.Allocate <int>(clusters.GetLength(0), clusters.GetLength(1)))
            {
                clusterBuff.CopyFrom(clusters, Index2.Zero, Index2.Zero, clusterBuff.Extent);
                using (MemoryBuffer3D <int> diffs = HardwareAcceleratorManager.GPUAccelerator.Allocate <int>(clusterBuff.Extent.X, clusterBuff.Extent.X, 5))
                    using (MemoryBuffer2D <int> bests = HardwareAcceleratorManager.GPUAccelerator.Allocate <int>(clusterBuff.Extent.X, 3 + clusterBuff.Extent.X))
                    {
                        bool change = true;
                        while (change)
                        {
                            change = false;
                            diffs.MemSetToZero();
                            bests.MemSetToZero();
                            kernel(new Index2(clusterBuff.Extent.X, clusterBuff.Extent.X), clusterBuff, diffs);
                            HardwareAcceleratorManager.GPUAccelerator.Synchronize();
                            kernelBests(bests.Extent.X, diffs, bests);
                            HardwareAcceleratorManager.GPUAccelerator.Synchronize();

                            int[,] best = new int[bests.Extent.X, bests.Extent.Y];
                            bests.CopyTo(best, Index2.Zero, Index2.Zero, bests.Extent);

                            int eq    = -1;
                            int diffl = -1;
                            int ts    = -1;
                            for (int i = 0; i < best.GetLength(0); i++)
                            {
                                if (best[i, 0] > eq)
                                {
                                    eq    = best[i, 0];
                                    diffl = best[i, 1];
                                    ts    = best[i, 2];
                                }
                                else if (best[i, 0] == eq && best[i, 1] > diffl)
                                {
                                    diffl = best[i, 1];
                                    ts    = best[i, 2];
                                }
                                else if (best[i, 0] == eq && best[i, 1] == diffl && ts < best[i, 2])
                                {
                                    ts = best[i, 2];
                                }
                            }

                            if (eq >= 0)
                            {
                                change = true;

                                List <int> bestofbest   = new List <int>();
                                List <int> bestofbestID = new List <int>();

                                for (int i = 0; i < best.GetLength(0); i++)
                                {
                                    if (eq == best[i, 0] && diffl == best[i, 1] && ts == best[i, 2])
                                    {
                                        for (int j = 3; j < best.GetLength(1); j++)
                                        {
                                            if (best[i, j] < 0)
                                            {
                                                break;
                                            }
                                            else
                                            {
                                                bestofbest.Add(i);
                                                bestofbestID.Add(best[i, j]);
                                            }
                                        }
                                    }
                                }

                                int[] bob1 = bestofbest.ToArray();
                                int[] bob2 = bestofbestID.ToArray();
                                int[] bob3 = new int[bob1.Length];
                                bool  repeated;

                                for (int i = 0, k = 0; i < bob1.Length; i++)
                                {
                                    bob3[i]  = bob1[i];
                                    repeated = false;
                                    for (int j = 0; j < i; j++)
                                    {
                                        if (bob3[i] == bob3[j])
                                        {
                                            repeated = true;
                                        }
                                    }
                                    if (repeated)
                                    {
                                        for (int j = k; j < bob2.Length; j++)
                                        {
                                            repeated = false;
                                            for (int q = 0; q < i; q++)
                                            {
                                                if (bob3[q] == bob2[j])
                                                {
                                                    repeated = true;
                                                    break;
                                                }
                                            }
                                            if (!repeated)
                                            {
                                                bob3[i] = bob2[j];
                                                k       = j;
                                                break;
                                            }
                                        }
                                    }
                                }

                                using (MemoryBuffer <int> bobbuff1 = HardwareAcceleratorManager.GPUAccelerator.Allocate <int>(bestofbest.Count))
                                    using (MemoryBuffer <int> bobbuff2 = HardwareAcceleratorManager.GPUAccelerator.Allocate <int>(bestofbestID.Count))
                                        using (MemoryBuffer <int> newPos = HardwareAcceleratorManager.GPUAccelerator.Allocate <int>(bestofbest.Count))
                                            using (MemoryBuffer2D <int> newPals = HardwareAcceleratorManager.GPUAccelerator.Allocate <int>(bestofbestID.Count, clusterBuff.Extent.Y))
                                            {
                                                newPals.MemSetToZero();
                                                bobbuff1.CopyFrom(bob1, 0, 0, bobbuff1.Extent);
                                                bobbuff2.CopyFrom(bob2, 0, 0, bobbuff2.Extent);
                                                newPos.CopyFrom(bob3, 0, 0, newPos.Extent);
                                                kernelInvalidateCluster(bobbuff1.Extent, bobbuff1, bobbuff2, newPals, clusterBuff);
                                                HardwareAcceleratorManager.GPUAccelerator.Synchronize();
                                                kernelCopyNewPal(newPos.Extent, newPos, newPals, clusterBuff);
                                                HardwareAcceleratorManager.GPUAccelerator.Synchronize();
                                                kernelFilter(bobbuff1.Extent, bobbuff1, newPos, clusterBuff);
                                                HardwareAcceleratorManager.GPUAccelerator.Synchronize();
                                                kernelFilter(bobbuff2.Extent, bobbuff2, newPos, clusterBuff);
                                                HardwareAcceleratorManager.GPUAccelerator.Synchronize();
                                            }
                                kernelRemoveRepeated(new Index2(clusterBuff.Extent.X, clusterBuff.Extent.X), clusterBuff);
                                HardwareAcceleratorManager.GPUAccelerator.Synchronize();
                            }
                        }
                    }
                clusterBuff.CopyTo(clusters, Index2.Zero, Index2.Zero, clusterBuff.Extent);
            }
        }
        public static void Execute(ConcurrentDictionary <ConcurrentDictionary <Int32, int>, ConcurrentDictionary <TileKey, int> > tilesperPal, ConcurrentDictionary <TileKey, ConcurrentDictionary <Int32, int> > tilePals)
        {
            int l = 0;

            TileKey[] tilespositions = new TileKey[tilePals.Count];
            int       i = 0;

            foreach (var kvp in tilePals)
            {
                tilespositions[i] = kvp.Key;
                i++;
            }

            foreach (var kvp in tilesperPal)
            {
                if (kvp.Key.Count > l)
                {
                    l = kvp.Key.Count;
                }
            }

            int[,] pals = new int[tilesperPal.Count, l];

            Parallel.For(0, pals.GetLength(0), k =>
            {
                Parallel.For(0, pals.GetLength(1), q =>
                {
                    pals[k, q] = 0;
                });
            });
            i = 0;
            int j;

            int[,] tilepals = new int[tilePals.Count, l];

            l = 0;
            foreach (var kvp1 in tilesperPal)
            {
                j = 0;
                foreach (var kvp2 in kvp1.Key)
                {
                    pals[i, j] = kvp2.Key;
                    j++;
                }
                if (kvp1.Value.Count > l)
                {
                    l = kvp1.Value.Count;
                }
                i++;
            }

            int[,] tilesPerPal = new int[tilesperPal.Count, l];

            Parallel.For(0, tilepals.GetLength(0), k =>
            {
                Parallel.For(0, tilepals.GetLength(1), q =>
                {
                    tilepals[k, q] = 0;
                });
            });

            Parallel.For(0, tilesPerPal.GetLength(0), k =>
            {
                Parallel.For(0, tilesPerPal.GetLength(1), q =>
                {
                    tilesPerPal[k, q] = -1;
                });
            });

            i = 0;
            foreach (var kvp1 in tilePals)
            {
                j = 0;
                foreach (var kvp2 in kvp1.Value)
                {
                    tilepals[i, j] = kvp2.Key;
                    j++;
                }
                i++;
            }

            i = 0;
            foreach (var kvp1 in tilesperPal)
            {
                j = 0;
                foreach (var kvp2 in kvp1.Value)
                {
                    for (int k = 0; k < tilespositions.GetLength(0); k++)
                    {
                        if (kvp2.Key.X == tilespositions[k].X && kvp2.Key.Y == tilespositions[k].Y)
                        {
                            tilesPerPal[i, j] = k;
                            break;
                        }
                    }
                    j++;
                }
                i++;
            }

            int[,,] results  = new int[pals.GetLength(0), pals.GetLength(0), 1 + pals.GetLength(1)];
            int[,,] results2 = new int[pals.GetLength(0), pals.GetLength(0), tilesPerPal.GetLength(1)];

            using (MemoryBuffer2D <int> palsBuff = HardwareAcceleratorManager.GPUAccelerator.Allocate <int>(pals.GetLength(0), pals.GetLength(1)))
                using (MemoryBuffer2D <int> tilepalsBuff = HardwareAcceleratorManager.GPUAccelerator.Allocate <int>(tilepals.GetLength(0), tilepals.GetLength(1)))
                    using (MemoryBuffer2D <int> tilesPerPalBuff = HardwareAcceleratorManager.GPUAccelerator.Allocate <int>(tilesPerPal.GetLength(0), tilesPerPal.GetLength(1)))
                        using (MemoryBuffer3D <int> palres = HardwareAcceleratorManager.GPUAccelerator.Allocate <int>(pals.GetLength(0), pals.GetLength(0), 1 + pals.GetLength(1)))
                            using (MemoryBuffer3D <int> palres2 = HardwareAcceleratorManager.GPUAccelerator.Allocate <int>(pals.GetLength(0), pals.GetLength(0), tilesPerPal.GetLength(1)))
                            {
                                palsBuff.CopyFrom(pals, Index2.Zero, Index2.Zero, palsBuff.Extent);
                                tilepalsBuff.CopyFrom(tilepals, Index2.Zero, Index2.Zero, tilepalsBuff.Extent);
                                tilesPerPalBuff.CopyFrom(tilesPerPal, Index2.Zero, Index2.Zero, tilesPerPalBuff.Extent);

                                bool change = true;
                                while (change)
                                {
                                    palres.MemSetToZero();
                                    palres2.MemSetToZero();
                                    change = false;
                                    kernel(palres.Extent.XY, palres, palres2, palsBuff, tilepalsBuff, tilesPerPalBuff);
                                    HardwareAcceleratorManager.GPUAccelerator.Synchronize();
                                    kernelBestEach(palres.Extent.X, palres);
                                    HardwareAcceleratorManager.GPUAccelerator.Synchronize();

                                    palres.CopyTo(results, Index3.Zero, Index3.Zero, palres.Extent);
                                    palres2.CopyTo(results2, Index3.Zero, Index3.Zero, palres2.Extent);

                                    int        bestOfBest = int.MaxValue;
                                    List <int> inds       = new List <int>();
                                    List <int> inds2      = new List <int>();

                                    for (i = 0; i < results.GetLength(0); i++)
                                    {
                                        if (results[i, i, 0] >= 0)
                                        {
                                            if (results[i, i, 1] < bestOfBest)
                                            {
                                                bestOfBest = results[i, i, 1];
                                                inds2.Clear();
                                                inds.Clear();
                                                inds.Add(i);
                                                inds2.Add(results[i, i, 0]);
                                            }
                                            else if (results[i, i, 1] == bestOfBest)
                                            {
                                                inds.Add(i);
                                                inds2.Add(results[i, i, 0]);
                                            }
                                        }
                                    }
                                    if (inds.Count > 0)
                                    {
                                        change = true;
                                        while (change)
                                        {
                                            change = false;

                                            int addMax   = 0;
                                            int remIndex = 0;
                                            int add      = 0;
                                            int curindex = 0;
                                            foreach (var id1 in inds)
                                            {
                                                add = 0;
                                                foreach (var id2 in inds2)
                                                {
                                                    if (id1 == id2)
                                                    {
                                                        add++;
                                                    }
                                                }
                                                if (add > addMax)
                                                {
                                                    addMax   = add;
                                                    remIndex = curindex;
                                                }
                                                curindex++;
                                            }
                                            if (addMax > 0)
                                            {
                                                change = true;
                                                inds.RemoveAt(remIndex);
                                                inds2.RemoveAt(remIndex);
                                            }
                                        }

                                        int[,] reduceInds = new int[inds.Count, 2];

                                        IEnumerator <int> en1 = inds.GetEnumerator();
                                        IEnumerator <int> en2 = inds2.GetEnumerator();
                                        en1.Reset();
                                        en2.Reset();
                                        for (int en = 0; en < inds.Count; en++)
                                        {
                                            en1.MoveNext();
                                            en2.MoveNext();
                                            reduceInds[en, 0] = en1.Current;
                                            reduceInds[en, 1] = en2.Current;
                                        }

                                        using (MemoryBuffer2D <int> indsbuff = HardwareAcceleratorManager.GPUAccelerator.Allocate <int>(reduceInds.GetLength(0), reduceInds.GetLength(1)))
                                        {
                                            indsbuff.CopyFrom(reduceInds, Index2.Zero, Index2.Zero, indsbuff.Extent);
                                            kernelReduceColors(indsbuff.Extent.X, palres, palres2, palsBuff, indsbuff, tilesPerPalBuff);
                                            HardwareAcceleratorManager.GPUAccelerator.Synchronize();
                                        }
                                        change = true;
                                    }
                                    else
                                    {
                                        palsBuff.CopyTo(pals, Index2.Zero, Index2.Zero, palsBuff.Extent);
                                        tilesPerPalBuff.CopyTo(tilesPerPal, Index2.Zero, Index2.Zero, tilesPerPalBuff.Extent);
                                    }
                                }
                            }
            tilesperPal.Clear();
            ConcurrentDictionary <Int32, int>   curpal;
            ConcurrentDictionary <TileKey, int> curtiles;

            for (i = 0; i < tilesPerPal.GetLength(0); i++)
            {
                curpal   = new ConcurrentDictionary <Int32, int>();
                curtiles = new ConcurrentDictionary <TileKey, int>();
                if (tilesPerPal[i, 0] >= 0)
                {
                    for (j = 0; j < tilesPerPal.GetLength(1); j++)
                    {
                        if (tilesPerPal[i, j] >= 0)
                        {
                            curtiles.TryAdd(tilespositions[tilesPerPal[i, j]], 0);
                        }
                    }
                    for (j = 0; j < pals.GetLength(1); j++)
                    {
                        if (pals[i, j] != 0)
                        {
                            curpal.TryAdd(pals[i, j], 0);
                        }
                    }
                    tilesperPal.TryAdd(curpal, curtiles);
                }
            }
        }