Overclock.net › Forums › Software, Programming and Coding › Coding and Programming › [C#]Multi-Threaded Prime Number Algorithm, Need Help!!
New Posts  All Forums:Forum Nav:

[C#]Multi-Threaded Prime Number Algorithm, Need Help!!

post #1 of 3
Thread Starter 
For build 3 of DoubleMark i once again revised the algorithm. I completely eliminated floating points and operations and so on, however i am baffled as to what i have done wrong with multi-threading the algorithm. I will include complete documentation to speed up any help given, since the algorithm is hard to read (so i've been told, since i wrote it my opinion doesn't count.)

When the button is pressed :
Code:
        private void button1_Click(object sender, EventArgs e) //Benchmark Button
        {
            textBox1.Text += System.Environment.NewLine;
            if (checkBox1.Checked == true)
            {
                Thread Thread1 = new Thread(PrimeNumbers);
                Thread1.Start(1);
            }
            else
            {
                for (int i = 0; i < Environment.ProcessorCount; i++)
                {
                    threads[i] = new Thread(PrimeNumbers);
                    threads[i].Start(i + 1);
                    PNumbers[i] = 0;
                    textBox1.Text += System.Environment.NewLine + "Thread #" + Convert.ToString(i)
                        + System.Environment.NewLine + "     has started." + System.Environment.NewLine;
                }
                Thread endrun = new Thread(threadwait);
                endrun.Start();
            }
            button1.Enabled = false;
        }
The thread management code (executed in a different thread to prevent GUI hangs) :
Code:
private void threadwait()
        {
            for (int i = 0; i < Environment.ProcessorCount; i++)
            {
                if (threads[i].IsAlive == true)
                {
                    threads[i].Join();
                }
            }
            int TotalPNumber = 0;
            for (int i = 0; i < Environment.ProcessorCount; i++)
            {
                TotalPNumber += PNumbers[i];
            }
            MessageBox.Show("Test Complete; Prime Numbers Found : " + Convert.ToString(TotalPNumber + 4) + "; Time Taken : ");
            button1.Enabled = true;
        }
And the single-core algorithm, which is flawless :
Code:
private void PrimeNumbers(object threadnumber)
        {
            if (checkBox1.Checked == true)//Single
            {
                foreach (ProcessThread pt in Process.GetCurrentProcess().Threads)
                {
                    int utid = GetCurrentThreadId();
                    if (utid == pt.Id)
                    {
                        pt.ProcessorAffinity = (IntPtr)(Convert.ToInt32(threadnumber));
                    }
                }
                int FNumber = 11;
                int PNumber = 4;
                int SNumber = 3;
                int TNumber = Convert.ToInt32(TestLength * 0.1 - 10);
                for (int i = 0; i < TNumber; i++)
                {
                    for (int u = 0; u < (FNumber * 0.25); u++) // 1
                    {
                        if (FNumber % SNumber == 0)
                        {
                            PNumber -= 1;
                            break;
                        }
                        else
                        {
                            SNumber += 2;
                        }
                    }
                    PNumber += 1;
                    SNumber = 3;
                    FNumber += 2;
                    for (int u = 0; u < (FNumber * 0.25); u++) // 3
                    {
                        if (FNumber % SNumber == 0)
                        {
                            PNumber -= 1;
                            break;
                        }
                        else
                        {
                            SNumber += 2;
                        }
                    }
                    PNumber += 1;
                    SNumber = 3;
                    FNumber += 4;
                    for (int u = 0; u < (FNumber * 0.25); u++) // 7
                    {
                        if (FNumber % SNumber == 0)
                        {
                            PNumber -= 1;
                            break;
                        }
                        else
                        {
                            SNumber += 2;
                        }
                    }
                    PNumber += 1;
                    SNumber = 3;
                    FNumber += 2;
                    for (int u = 0; u < (FNumber * 0.25); u++) // 9
                    {
                        if (FNumber % SNumber == 0)
                        {
                            PNumber -= 1;
                            break;
                        }
                        else
                        {
                            SNumber += 2;
                        }
                    }
                    PNumber += 1;
                    SNumber = 3;
                    FNumber += 2;
                    progressBar1.Value = (FNumber / TestLength * 100);
                }
                progressBar1.Value = 100;
                MessageBox.Show("Test Complete; Prime Numbers Found : " + Convert.ToString(PNumber));
                progressBar1.Value = 0;
                button1.Enabled = true;
            }
}
[If you see #region or #endregion thats for orginization and is not part of the actual code.

And the multi-threaded algorithm :
Code:
else
            {
                int FNumber = Convert.ToInt32(threadnumber) + 1 * 10 + 1;
                int PNumber = 0;
                int SNumber = 3;
                int TNumber = Convert.ToInt32(TestLength * 0.1 / Environment.ProcessorCount); //since the algorithm checks in groups of 10 with 4 numbers from each group divide (or in this case multiply by 0.1) the number to be checked by ten then by the number of threads and you have how many iterations each thread will need
                for (int i = 0; i < TNumber; i++)
                {
                    for (int u = 0; u < (FNumber * 0.25); u++) // 1
                    {
                        if (FNumber % SNumber == 0) //it is simple, if theres no remainder is not a prime number, however if the loop reaches its end with all remainders then that means the number has no other number that can be equally divided into it and it is a prime number (also, in the case the rainder isn't 0 and the loop is continueing it increases the divisor)
                        {
                            PNumber -= 1;
                            break;
                        }
                        else
                        {
                            SNumber += 2;
                        }
                    }
                    PNumber += 1;
                    SNumber = 3;
                    FNumber += 2;
                    for (int u = 0; u < (FNumber * 0.25); u++) // 3
                    {
                        if (FNumber % SNumber == 0)
                        {
                            PNumber -= 1;
                            break;
                        }
                        else
                        {
                            SNumber += 2;
                        }
                    }
                    PNumber += 1;
                    SNumber = 3;
                    FNumber += 4;
                    for (int u = 0; u < (FNumber * 0.25); u++) // 7
                    {
                        if (FNumber % SNumber == 0)
                        {
                            PNumber -= 1;
                            break;
                        }
                        else
                        {
                            SNumber += 2;
                        }
                    }
                    PNumber += 1;
                    SNumber = 3;
                    FNumber += 2;
                    for (int u = 0; u < (FNumber * 0.25); u++) // 9
                    {
                        if (FNumber % SNumber == 0)
                        {
                            PNumber -= 1;
                            break;
                        }
                        else
                        {
                            SNumber += 2;
                        }
                    }
                    PNumber += 1;
                    SNumber = 3;
                    FNumber += Environment.ProcessorCount * 10 + 2; //+2 will increase the 10s place by 1, thus you only need 10 times the processor count plus 2 to acheive the desired effect of each getting its own set of 10s each iteration
                    progressBar1.Value = (FNumber / TestLength * 100);
                }
                PNumbers[Convert.ToInt32(threadnumber) - 1] = PNumber; //Prevents crossthread data access corruption
            }
I hate to ask such a large task of anyone but i have delayed the third build of DoubleMark very long over this issue and i cannot resolve it it seams. Someone more experienced will probably point out some stupid mistake but i'd be happy to have it working.

If you need to know anything else or are interested i provide the following links.

OverClock.Net DoubleMark Topic

OverClock.Net DoubleMark Blog
Lee XT
(17 items)
 
  
CPUMotherboardGraphicsRAM
AMD FX-6300 Asus M5A97 SAPPHIRE Radeon HD 7850 AMD 4GB DDR3 1333MHZ 
RAMRAMRAMHard Drive
AMD 4GB DDR3 1333MHZ AMD 4GB DDR3 1333MHZ AMD 4GB DDR3 1333MHZ OCZ Vertex 4 256GB 
CoolingOSMonitorKeyboard
Corsair H80 Windows 8.1 Pro MCE Dell P2414H WHXV7  Microsoft Generic 
PowerCaseMouseMouse Pad
Ultra 600W Limited Edition NZXT Black Steel Razer Deathadder Razer Goliath 
Audio
Realtek HD Audio 
  hide details  
Reply
Lee XT
(17 items)
 
  
CPUMotherboardGraphicsRAM
AMD FX-6300 Asus M5A97 SAPPHIRE Radeon HD 7850 AMD 4GB DDR3 1333MHZ 
RAMRAMRAMHard Drive
AMD 4GB DDR3 1333MHZ AMD 4GB DDR3 1333MHZ AMD 4GB DDR3 1333MHZ OCZ Vertex 4 256GB 
CoolingOSMonitorKeyboard
Corsair H80 Windows 8.1 Pro MCE Dell P2414H WHXV7  Microsoft Generic 
PowerCaseMouseMouse Pad
Ultra 600W Limited Edition NZXT Black Steel Razer Deathadder Razer Goliath 
Audio
Realtek HD Audio 
  hide details  
Reply
post #2 of 3
You should post what erroneous behavior you're seeing. How does it fail? Does it lock up? Does it show incorrect output? Does it not compile?

I haven't messed around with threading in C#, but one way your code differs from a lot of the web examples I looked at is the lack of a ThreadStart delegate when constructing the threads. For instance,

Code:
Thread endrun = new Thread(new ThreadStart(threadwait));
    
CPUGraphicsRAMHard Drive
Intel 2.4 Core i7 AMD Radeon HD 6750M 8 GB 1067 MHz DDR3 750 GB 
OS
Mac OS-X Lion 
  hide details  
Reply
    
CPUGraphicsRAMHard Drive
Intel 2.4 Core i7 AMD Radeon HD 6750M 8 GB 1067 MHz DDR3 750 GB 
OS
Mac OS-X Lion 
  hide details  
Reply
post #3 of 3
Thread Starter 
Quote:
Originally Posted by Scriptorum View Post
You should post what erroneous behavior you're seeing. How does it fail? Does it lock up? Does it show incorrect output? Does it not compile?

I haven't messed around with threading in C#, but one way your code differs from a lot of the web examples I looked at is the lack of a ThreadStart delegate when constructing the threads. For instance,

Code:
Thread endrun = new Thread(new ThreadStart(threadwait));
I managed to finally correct the issue after crash coursing over a debugger until 4:30am. That was not the issue, the issue was it was counting prime numbers incorrectly. I managed to resolve the issue caused by a order of calculation bug in the final FNumber increase line at the end of the master loop. There were also 2 other bugs of similar nature and one i just had wrong.
Lee XT
(17 items)
 
  
CPUMotherboardGraphicsRAM
AMD FX-6300 Asus M5A97 SAPPHIRE Radeon HD 7850 AMD 4GB DDR3 1333MHZ 
RAMRAMRAMHard Drive
AMD 4GB DDR3 1333MHZ AMD 4GB DDR3 1333MHZ AMD 4GB DDR3 1333MHZ OCZ Vertex 4 256GB 
CoolingOSMonitorKeyboard
Corsair H80 Windows 8.1 Pro MCE Dell P2414H WHXV7  Microsoft Generic 
PowerCaseMouseMouse Pad
Ultra 600W Limited Edition NZXT Black Steel Razer Deathadder Razer Goliath 
Audio
Realtek HD Audio 
  hide details  
Reply
Lee XT
(17 items)
 
  
CPUMotherboardGraphicsRAM
AMD FX-6300 Asus M5A97 SAPPHIRE Radeon HD 7850 AMD 4GB DDR3 1333MHZ 
RAMRAMRAMHard Drive
AMD 4GB DDR3 1333MHZ AMD 4GB DDR3 1333MHZ AMD 4GB DDR3 1333MHZ OCZ Vertex 4 256GB 
CoolingOSMonitorKeyboard
Corsair H80 Windows 8.1 Pro MCE Dell P2414H WHXV7  Microsoft Generic 
PowerCaseMouseMouse Pad
Ultra 600W Limited Edition NZXT Black Steel Razer Deathadder Razer Goliath 
Audio
Realtek HD Audio 
  hide details  
Reply
New Posts  All Forums:Forum Nav:
  Return Home
  Back to Forum: Coding and Programming
Overclock.net › Forums › Software, Programming and Coding › Coding and Programming › [C#]Multi-Threaded Prime Number Algorithm, Need Help!!