Skip to content
WJunction - Webmaster Forum

[c#] CHALLENGE - Beat the time! #2

Status
Not open for further replies.

22 comments

The express edition is free.

Made a few optimizations yesterday:
PHP:
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Text;

namespace Hyperz.RGen
{
    public unsafe class RGen
    {
        private uint* pSeedX;
        private uint* pSeedY;

        public uint SeedX
        {
            get { return *pSeedX; }
            set { *pSeedX = value; }
        }

        public uint SeedY
        {
            get { return *pSeedY; }
            set { *pSeedY = value; }
        }

        public RGen(uint seed)
        {
            uint* pX = stackalloc uint[1];
            uint* pY = stackalloc uint[1];

            pSeedX = pX;
            pSeedY = pY;

            this.SeedX = seed;
            this.SeedY = 362436069;
        }

        public RGen(int seed) : this((uint)seed) { }

        public RGen() : this(Environment.TickCount) { }

        public uint Generate()
        {
            *pSeedX = 36969 * (*pSeedX & 65535) + (*pSeedX >> 16);
            *pSeedY = 18000 * (*pSeedY & 65535) + (*pSeedY >> 16);

            return (*pSeedX << 16) + (*pSeedY & 65535);
        }

        private void GenerateAt(uint* pDest)
        {
            *pSeedX = 36969 * (*pSeedX & 65535) + (*pSeedX >> 16);
            *pSeedY = 18000 * (*pSeedY & 65535) + (*pSeedY >> 16);

            *pDest = (*pSeedX << 16) + (*pSeedY & 65535);
        }

        public uint[] GenerateMultiple(int amount, int threadLimit = 32)
        {
            if (threadLimit == 1 || amount < threadLimit)
            {
                uint[] results = new uint[amount];

                fixed (uint* pR = results)
                {
                    for (uint* i = pR; i < pR + amount; i++) *i = this.Generate();
                }

                return results;
            }
            else
            {
                int amountPerInstance = amount / threadLimit;
                int addToLast = amount - (amountPerInstance * threadLimit);
                bool addOneToLast = (amount & 1) == 1;
                var po = new ParallelOptions() { MaxDegreeOfParallelism = threadLimit };

                uint[] results = new uint[amount];

                Parallel.For(0, threadLimit, po, num =>
                {
                    var r = new RGen(this.Generate());
                    int count = (addOneToLast && num == threadLimit - 1) ?
                        amountPerInstance + addToLast : amountPerInstance;

                    uint[] numbers = new uint[count];

                    fixed (uint* pN = numbers)
                    {
                        for (uint* i = pN; i < pN + count; i++) *i = r.Generate();
                    }

                    fixed (uint* pN = numbers, pR = results)
                    {
                        uint* pn = pN;
                        uint* pr = pR + (num * amountPerInstance);
                        uint* cnt = pn + count;

                        for (; pn < cnt; pn++, pr++) *pr = *pn;
                    }
                });

                return results;
            }
        }


        // OOOOLLLLLLDDDDDD
        /*public uint[] GenerateMultiple(int amount, int threadLimit = 32)
        {
            if (amount < threadLimit) threadLimit = 1;

            int amountPerInstance = amount / threadLimit;
            int addToLast = amount - (amountPerInstance * threadLimit);
            bool addOneToLast = (amount & 1) == 1;
            var po = new ParallelOptions() { MaxDegreeOfParallelism = threadLimit };

            uint[] results = new uint[amount];

            Parallel.For(0, threadLimit, po, num =>
            {
                var r = new RGen(this.Generate());
                int count = (addOneToLast && num == threadLimit - 1) ?
                    amountPerInstance + addToLast : amountPerInstance;

                uint[] numbers = new uint[count];

                for (int i = 0; i < count; i++) numbers[i] = r.Generate();

                lock (results) numbers.CopyTo(results, num * amountPerInstance);
            });

            return results;
        }*/
    }
}

Made the 2 seed properties pointers rather than values. The memory for those seed properties is now allocated on the stack rather than on the heap (faster). Removed the address locking from the Generate function. And finally optimized the GenerateMultiple function a bit.

Single thread: 0.69 seconds
4 threads: 0.38 seconds

I think this is as fast as I'll get this algorithm with C# :-?.
 
Status
Not open for further replies.

About the author

Hyperz
Active Member · Joined
2,477
Messages
617
Reactions
113
Points

Advertise on WJunction

Reach 1000's of webmasters, hosts & affiliates. Banner & sponsored-thread slots available.

Contact us
Back
Top Bottom