patterncsharpMinor
My first attempt at multithreading in C# with Prime Numbers
Viewed 0 times
withnumbersattemptfirstmultithreadingprime
Problem
This is my first attempt at multithreading in C#. This entire program does several things with prime numbers, but the part I'm going to post is mainly focused with printing out all prime numbers starting at a high number all the way until it reaches 1. This was not originally intended to be a multi-threaded program, but I wanted to check out some large numbers (I actually have an overload that takes a
`public void printAllPrimes(int number)
{
Console.WriteLine(
isItPrime(number)
? "{0} is prime. Below are all prime numbers between it and 1:\n"
: "{0} is not prime but below are all prime numbers between it and 1:\n", number);
int holder = number;
while (--holder > 1){
if (isItPrime(holder))
Console.WriteLine("{0} \t Thread {1}", holder, Thread.CurrentThread.ManagedThreadId);
}
}
public bool isItPrime(int number)
{
if (number 1){
//Divisible = divide by a number and get no remainder.
if (number % holder == 0){
return false;
}
}
return true;
}
static void Main(string[] args)
{
Program program = new Program();
Console.WriteLine("Enter an integer and find out whether it is prime, and find primes all the way down to 1!\n");
int userEntry = 0;
while (!Int32.TryParse(Console.ReadLine(), out userEntry)){
Console.WriteLine("Enter a valid integer!");
}
int split = userEntry / 6;
int[] workChunk = new int[6];
for (int i = 0; i program.printAllPrimes(workChunk[0]));
Thread t2 = new Thread(p => program.printAllPrimes(workChunk[1]));
Thread t3 = new Thread(p => program.printAllPrimes(workChunk[2]));
Thread t4 = new Thread(p => program.printAllPrimes(workChunk[3]));
Thread t5 = new Thread(p => program.printAllPrimes(workChunk[4]));
Thread
BigInteger type I will eventually use) and I was watching the computer get bogged down whilst only using 20% of the CPU. In comes multithreading.`public void printAllPrimes(int number)
{
Console.WriteLine(
isItPrime(number)
? "{0} is prime. Below are all prime numbers between it and 1:\n"
: "{0} is not prime but below are all prime numbers between it and 1:\n", number);
int holder = number;
while (--holder > 1){
if (isItPrime(holder))
Console.WriteLine("{0} \t Thread {1}", holder, Thread.CurrentThread.ManagedThreadId);
}
}
public bool isItPrime(int number)
{
if (number 1){
//Divisible = divide by a number and get no remainder.
if (number % holder == 0){
return false;
}
}
return true;
}
static void Main(string[] args)
{
Program program = new Program();
Console.WriteLine("Enter an integer and find out whether it is prime, and find primes all the way down to 1!\n");
int userEntry = 0;
while (!Int32.TryParse(Console.ReadLine(), out userEntry)){
Console.WriteLine("Enter a valid integer!");
}
int split = userEntry / 6;
int[] workChunk = new int[6];
for (int i = 0; i program.printAllPrimes(workChunk[0]));
Thread t2 = new Thread(p => program.printAllPrimes(workChunk[1]));
Thread t3 = new Thread(p => program.printAllPrimes(workChunk[2]));
Thread t4 = new Thread(p => program.printAllPrimes(workChunk[3]));
Thread t5 = new Thread(p => program.printAllPrimes(workChunk[4]));
Thread
Solution
int split = userEntry / 6;
int[] workChunk = new int[6];
for (int i = 0; i < 6; i++){
workChunk[i] = (userEntry - split);
userEntry -= split;This is not a very flexible and up-to-date solution. You not only need to calcucalte the number of threads/parallel tasks manually but the number of cpus is hardcoded and cannot be easily used on other machines.
One way to improve it would be to use the
Environment.ProcessorCount.But what you really need is the newer TPL. There is already a Partitioner Class for creating such chunks.
If you wanted to calculate primes for the range 1-4000 you would write (the last one is exclusive, thus +1)
var partitioner = Partitioner.Create(1, 4001);Then you let C# handle the threads with
Parallel.ForEachParallel.ForEach(partitions, p =>
{
Console.WriteLine($"Partition {p} [{Thread.CurrentThread.ManagedThreadId}]");
Task.Delay(2000).Wait();
for (int i = p.Item1; i < p.Item2; i++)
{
//Console.WriteLine($"IsPrime({i}) = {IsPrime(i)}");
}
});The
Task.Delay(2000).Wait() pretends the loop is doing some heavy work. If it's not then it might not be necessary to spawn/use more threads so after all it might run with only one or two threads.If you don't want to use all cpus you can specify another parameter and limit them with
new ParallelOptions { MaxDegreeOfParallelism = 4 },On my machine for example (4 cpus) the delay causes that four parallel executions take place:
Partition (1, 334) [12]
Partition (1000, 1333) [14]
Partition (334, 667) [16]
Partition (667, 1000) [15]
Partition (1333, 1666) [10]
Partition (1666, 1999) [17]
Partition (1999, 2332) [15]
Partition (2332, 2665) [12]
Partition (2998, 3331) [16]
Partition (3331, 3664) [14]
Partition (2665, 2998) [19]
Partition (3664, 3997) [10]
Partition (3997, 4001) [17]
without it there are just two:
Partition (1, 334) [12]
Partition (334, 667) [12]
Partition (667, 1000) [12]
Partition (1000, 1333) [12]
Partition (1333, 1666) [12]
Partition (1666, 1999) [12]
Partition (1999, 2332) [12]
Partition (2332, 2665) [12]
Partition (2665, 2998) [12]
Partition (2998, 3331) [6]
Partition (3331, 3664) [12]
Partition (3664, 3997) [6]
Partition (3997, 4001) [12]
Code Snippets
int split = userEntry / 6;
int[] workChunk = new int[6];
for (int i = 0; i < 6; i++){
workChunk[i] = (userEntry - split);
userEntry -= split;var partitioner = Partitioner.Create(1, 4001);Parallel.ForEach(partitions, p =>
{
Console.WriteLine($"Partition {p} [{Thread.CurrentThread.ManagedThreadId}]");
Task.Delay(2000).Wait();
for (int i = p.Item1; i < p.Item2; i++)
{
//Console.WriteLine($"IsPrime({i}) = {IsPrime(i)}");
}
});new ParallelOptions { MaxDegreeOfParallelism = 4 },Context
StackExchange Code Review Q#152598, answer score: 2
Revisions (0)
No revisions yet.