Confused with the Parallel.ForEach loop in C# - c#

I'm new to C# and am basically trying to generate large Integers using the BigInteger class in C#, by feeding it a byte[] array of randomly filled values. I have another method, CheckForPrime(BigIngeger b) that checks for a prime number and simply returns true if the number is prime. So to run everything, I'm using a Parallel ForEach loop which loops infinitely until a condition is false. Here is my code:
private static IEnumerable<bool> IterateUntilFalse(bool condition)
{
while (condition) yield return true;
}
and here is my attempt at a Parallel.ForEach loop that runs till the condition is false:
public void PrintOutPrimes(int numPrimes)
{
byte[] makeBytes = new byte[512];
BigInteger makePrime;
RandomNumberGenerator r = RandomNumberGenerator.Create();
ConcurrentBag<BigInteger> bbag = new ConcurrentBag<BigInteger>();
int trackNum = 0;
bool condition = (trackNum <= numPrimes);
Parallel.ForEach(IterateUntilFalse(condition), (ignored, state) =>
{
if (trackNum > numPrimes) state.Stop();
r.GetNonZeroBytes(makeBytes);
makePrime = BigInteger.Abs(new BigInteger(makeBytes));
if (CheckForPrime(makePrime))
{
bbag.Add(makePrime);
if(bbag.TryPeek(out makePrime))
{
Console.WriteLine(makePrime);
}
Interlocked.Increment(ref trackNum);
}
});
}
I want to generate large prime numbers using the performance of Parallel.ForEach, and then print them out as it finds them. The problem seems like the code is "bypassing" the if statement in the loop and adding non-prime numbers to the concurrent bag too. Is there a way to avoid this and guarantee that only the prime numbers be added to the bag and then printed sequentially?

bool condition is not a condition, it's the result of evaluating the condition once. Basically it is always true and will never change. Therefore, your iterator will yield true forever.
To solve that, you need a real condition that can be evaluated several times, like a Lambda expression. But even with a lambda this won't work well due to race conditions in your local variables.
Actually I don't really see why you use Parallel.Foreach at all. If you want 500 primes, then use Parallel.For, not Parallel.Foreach.
Instead of generating a huge amount of random numbers and checking them for primality, choose a random number and increment it until you find a prime number. That way it's guaranteed that you get one prime number for every random number input.
Concept:
Parallel.For(0, numPrimes, (i, state)=>
{
byte[] makeBytes = new byte[512];
r.GetNonZeroBytes(makeBytes);
BigInteger makePrime = BigInteger.Abs(new BigInteger(makeBytes));
while (!IsPrime(makePrime))
makePrime += 1; // at some point, it will become prime
bbag.Add(makePrime);
});
You probably want to start with an odd number and increment by 2.
You definitely want one RNG per thread instead of accessing a single global RNG, except you have a thread-safe RNG.
You also want the byte[] to be part of the state, so that it does not get recreated per loop and messes with garbage collection.

Related

What is stopping this program from having an output

I made this code to brute force anagrams by printing all possible permutables of the characters in a string, however there is no output. I do not need simplifications as I am a student still learning the basics, I just need help getting it to work this way so I can better understand it.
using System;
using System.Collections.Generic;
namespace anagramSolver
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter anagram:");
string anagram = Console.ReadLine();
string temp = "";
List<string> storeStr = new List<string>(0);
List<int> storeInt = new List<int>(0);
//creates factorial number for anagram
int factorial = 1;
for (int i = anagram.Length; i > 0; i--)
{
factorial *= i;
}
while (storeStr.Count != factorial)
{
Random rnd = new Random();
while(temp.Length != anagram.Length)
{
int num = rnd.Next(anagram.Length - 1);
if (storeInt.Contains(num) == true)
{
}
else
{
storeInt.Add(num);
temp += anagram[num];
}
}
if (storeStr.Contains(temp) == true)
{
temp = "";
}
else
{
storeStr.Add(temp);
Console.WriteLine(temp, storeStr.Count);
temp = "";
}
}
}
}
}
edit: added temp reset after it is deemed contained by storeStr
Two main issues causing infinite loop:
1)
As per Random.Next documentation, the parameter is the "exclusive" upper bound. This means, if you want a random number between 0 and anagram.Length - 1 included, you should use rnd.Next(anagram.Length);.
With rnd.Next(anagram.Length - 1), you'll never hit anagram.Length - 1.
2)
Even if you solve 1, only the first main iteration goes well.
storeInt is never reset. Meaning, after the first main iteration, it will have already all the numbers in it.
So, during the second iteration, you will always hit the case if (storeInt.Contains(num) == true), which does nothing and the inner loop will go on forever.
Several issues here...
The expression rnd.Next(anagram.Length - 1) generates a value between 0 and anagram.Length - 2. For an input with two characters it will always return 0, so you'll never actually generate a full string. Remove the - 1 from it and you'll be fine.
Next, you're using a list to keep track of the character indices you've used already, but you never clear the list. You'll get one output (eventually, when the random number generator covers all the values) and then enter an infinite loop on the next generation pass. Clear storeInt after the generation loop to fix this.
While not a true infinite loop, creating a new instance of the random number generator each time will give you a lot of duplication. new Random() uses the current time as a seed value and you could potentially get through a ton of loops with each seed, generating exactly the same values until the time changes enough to change your random sequence. Create the random number generator once before you start your main loop.
And finally, your code doesn't handle repeated input letters. If the input is "aa" then there is only a single distinct output, but your code won't stop until it gets two. If the input was "aab" there are three distinct permutations ("aab", "aba", "baa") which is half of the expected results. You'll never reach your exit condition in this case. You could do it by keeping track of the indices you've used instead of the generated strings, it just makes it a bit more complex.
There are a few ways to generate permutations that are less error-prone. In general you should try to avoid "keep generating random garbage until I find the result I'm looking for" solutions. Think about how you personally would go about writing down the full list of permutations for 3, 4 or 5 inputs. What steps would you take? Think about how that would work in a computer program.
this loop
while(temp.Length != anagram.Length)
{
int num = rnd.Next(anagram.Length - 1);
if (storeInt.Contains(num) == true)
{
}
else
{
storeInt.Add(num);
temp += anagram[num];
}
}
gets stuck.
once the number is in storeInt you never change storeStr, yet thats what you are testing for loop exit

How can I implement odd-even sorting in C# using threads?

I am practicing about threads and concurrency in C# and tried to implement the basic odd-even sort algorithm using a thread for even and another for odd sorting.
static bool Sort(int startPosition, List<int> list)
{
bool result = true;
do
{
for (int i = startPosition; i <= list.Count - 2; i = i + 2)
{
if (list[i] > list[i + 1])
{
int temp = list[i];
list[i] = list[i + 1];
list[i + 1] = temp;
result = false;
}
}
} while (!result);
return result;
}
While the main method is like this:
static void Main(string[] args)
{
bool isOddSorted = false;
bool isEvenSorted = false;
List<int> list = new List<int>();
while (list.Count < 15)
{
list.Add(new Random().Next(0, 20));
}
var evenThread = new Thread(() =>
{
isEvenSorted = Sort(0, list);
});
evenThread.Start();
var oddThread = new Thread(() =>
{
isOddSorted = Sort(1, list);
});
oddThread.Start();
while (true)
{
if (isEvenSorted && isOddSorted)
{
foreach (int i in list)
{
Console.WriteLine(i);
}
break;
}
}
}
Understandably, the loop in Sort method works forever because the result variable is never set to true. However the way it works manages to sort the list. It just doesn't break at any time.
However the moment I add a "result = true" to the first line of do-scope of Sort function, the sorting messes up.
I couldn't figure out how to fix this.
You cannot do odd-even sort easily in a multi-threaded manner. Why?
Because the odd-even sort is in essence the repetition of two sorting passes (the odd and the even pass), with any subsequent pass depending on the result of the preceding pass. You cannot run two passes in parallel/concurrently in practical terms, as each pass has to follow each other.
There are of course ways to employ multi-threading, even with odd-even-sort, although that wouldn't probably make much practical sense. For example, you could divide the list into several partitions, with each partition being odd-even-sorted independently. The sorting of each partition could be done in a multi-threaded manner. As a final step it would require merging the sorted partitions in a way that would result in the fully sorted list.
(By the way, that you eventually get a sorted list if you only let the do while loops in your Sort method run many, many times is just that given enough time, even with "overlapping" concurrent passes you reach eventually a sorted list, but maybe not with all the same numbers from the original list. Because given enough repetions of the loop, eventually the elements will be compared with each other and shuffled to the right positions. However, since you have not synchronized list access, you might lose some numbers from the list, being replaced with duplicates of other numbers, depending on the runtime behavior and timing of list accesses between the two threads.)
You are trying to modify non-thread safe collection across threads.
Even if the assumption is good - you are using basic swap in Sort method (but you did not implement it entirely correct), you have to take under account that while one of the threads is doing the swap, other one could swap a value that is being in temp variable in this exact moment.
You would need to familiarize ourself with either locks and/or thread-Safe Collections.
Look at your result variable and the logic you have implemented with regard to result.
The outer do ... while (!result) loop will only exit when result is being true.
Now imagine your inner for loop finds two numbers that need swapping. So it does and swaps the numbers. And sets result to false. And here is my question to you: After result has been set to false when two numbers have been swapped, when and where is result ever being set to true?
Also, while you sort each the numbers on even list positions, and each the numbers on odd positions, your code does not do a final sort across the entire list. So, basically, if after doing the even and odd sorting, a larger number on an even position n is followed by a smaller number on odd position n+1, your code leaves it at that, leaving the list essentially still (partially) unsorted...

Fibonacci program does not complete execution

Problem Description
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms
Program
using System;
class fibonacci {
// function to return Nth value of fibonacci
public static long fibo_n(long N) {
long fibon=0;
switch (N) {
case 1: fibon=1; break;
case 2: fibon=2; break;
}
while(N>2) {
fibon=fibo_n(N-1)+fibo_n(N-2);
}
return fibon;
}
}
class fibo_tester {
static void Main() {
int N=2;
long sum=0;
while(fibonacci.fibo_n(N) <= 13) {
sum = sum + fibonacci.fibo_n(N);
N=N+3;
}
Console.WriteLine("Sum is {0}: ", sum);
}
}
I reduced the number to 13 for testing instead of 4 million, but it still hangs. Could someone please advise?
EDIT 2
switch (N) {
case 1: fibon=1; break;
case 2: fibon=2; break;
default: fibon=fibo_n(N-1)+fibo_n(N-2); break;
}
while(N>2) {
fibon=fibo_n(N-1)+fibo_n(N-2);
}
Is going to loop indefinitely, N is never updated in the loop. You probably need to remove the While() clause and change it all to return fibo_n(N-1)+fibo_n(N-2); I'm not sure what you are doing with the switch statements, etc. But that should be a start.
I would actually replace it with this (if you want to use the switch):
class fibonacci
{
// function to return Nth value of fibonacci
public static long fibo_n(long N)
{
switch (N)
{
case 0:
return 0;
case 1:
return 1;
default:
return fibo_n(N - 1) + fibo_n(N - 2);
}
}
}
You might want to consider storing the values for each value of N in a dictionary or some sort of set so that you can look them up later. Since in your main program it seems like you are going to be looping over the values (successively larger N's that may have already been calculated). I'm not sure what the N+3 is about in your main loop, but you probably are going to miss something there (false assumption of the N-1, N-2 in the recursion perhaps?)
Also, if summing and dependent on your platform and how large of a value you test for (sicne your testing the sum of the first X Fibonacci numbers) you may have to use a ulong or find some other datatype that can handle larger numbers. If I don't change everything from long to ulong on my system, the values wrap around. Fibonacci number can't be negative anyways, so why not use a ulong, or uint64 or something with more bits.
You are using BOTH a loop AND recursion - you'll need to pick one or the other. The problem spot in your code is here:
while (N>2) {
fibon = fibo_n(N-1)+fibo_n(N-2);
}
In this spot the value of N never actually changes - that happens in the recursive step. One example (not good) way to write this is:
public static long fibo_n(long N) {
if (N <= 0) return 0;
if (N == 1) return 1;
if (N <= 4) return N - 1;
return fibo_n(N-1) + fibo_n(N-2);
}
Best of luck!
Performance Note:
The reason this isn't a good approach is because function calls use memory in C# and they also take time. Looping is always faster than recursion and in this case there isn't a good reason to solve this with recursion (as opposed to a simple loop). I'll leave the code as is so you can compare to what you have, but I think you can find much better better code options elsewhere (although not all of these will be in C#).
Let's say you call your method with N equal to 3.
The switch doesn't do anything.
N is greater than 2, so we go into the while loop. The while loop does something; it computes a value, assigns it to fibon. Then N, since it hasn't changed, is still greater than 2, so we compute it again. It'll still be greater than two, so we compute it again. We never stop computing it.
Every time you assign a value to fibon you should instead be returning that value, because you're done; you have nothing left to compute. There's also no need for the while loop. You never need to execute that code more than once.
Your implementation is also super inefficient. To compute fib(5) you compute fib(4) and fib(3). To Then when computing fib(4) you compute fib(3) [again] and fib(2), when computing fib(3) both times they each compute fib(2) (so that's three times there), and if we do the math we end up seeing that you perform on the order of 2^n computations when computing fib(n). On top of that, you're calling fib n times as you're counting up from zero in your main loop. That's tons and tons and tons of needless work re-computing the same values. If you just have a simple loop adding the numbers together as you go you can compute the result with on the order of N computations.

C# How to use Interlocked.CompareExchange

My goal is the following:
There is a certain range of integers, and I have to test every integer in that range for something random. I want to use multiple threads for this, and divide the work equally among the threads using a shared counter. I set the counter at the beginning value, and let every thread take a number, increase it, do some calculations, and return a result. This shared counter has to be incremented with locks, because otherwise there will be gaps / overlaps in the range of integers to test.
I have no idea where to start. Let's say I want 12 threads to do the work, I do:
for (int t = 0; t < threads; t++)
{
Thread thr = new Thread(new ThreadStart(startThread));
}
startThread() isthe method I use for the calculations.
Can you help me on my way? I know I have to use the Interlocked class, but that's all….
Say you have an int field somewhere (initialized to -1 initially) then:
int newVal = Interlocked.Increment(ref theField);
is a thread-safe increment; assuming you don't mind the (very small) risk of overflowing the upper int limit, then:
int next;
while((next = Interlocked.Increment(ref theField)) <= upperInclusive) {
// do item with index "next"
}
However, Parallel.For will do all of this a lot more conveniently:
Parallel.For(lowerInclusive, upperExclusive, i => DoWork(i));
or (to constrain to 12 threads):
var options = new ParallelOptions { MaxDegreeOfParallelism = 12 };
Parallel.For(lowerInclusive, upperExclusive, options, i => DoWork(i));

Ensure uniform (ish) distribution with random number generation

I have a list of objects and I would like to access the objects in a random order continuously.
I was wondering if there was a way of ensuring that the random value were not always similar.
Example.
My list is a list of Queues, and I am trying to interleave the values to produce a real-world scenario for testing.
I don't particularly want all of the items in Queues 1 and 2 before any other item.
Is there a guaruanteed way to do this?
Thanks
EDIT ::
The List of Queues I have is a basically a list of files that i am transmitting to a webservice. Files need to be in a certain order hence the Queues.
So I have
Queue1 = "set1_1.xml", set1_2.xml", ... "set1_n.xml"
Queue2 ...
...
QueueN
While each file needs to be transmitted in order in terms of the other files in its queue, I would like to simulate a real world simulation where files would be received from different sources at different times and so have them interleaved.
At the moment I am just using a simple rand on 0 to (number of Queues) to determine which file to dequeue next. This works but I was asking if there might have been away to get some more uniformity rather than having 50 files from Queue 1 and 2 and then 5 files from Queue 3.
I do realise though that altering the randomness no longer makes it random.
Thank you for all your answers.
Well, it isn't entire clear what the scenario is, but the thing with random is you never can tell ;-p. Anything you try to do to "guarantee" thins will probably reduce the randomness.
How are you doing it? Personally I'd do something like:
static IEnumerable<T> GetItems<T>(IEnumerable<Queue<T>> queues)
{
int remaining = queues.Sum(q => q.Count);
Random rand = new Random();
while (remaining > 0)
{
int index = rand.Next(remaining);
foreach (Queue<T> q in queues)
{
if (index < q.Count)
{
yield return q.Dequeue();
remaining--;
break;
}
else
{
index -= q.Count;
}
}
}
}
This should be fairly uniform over the entire set. The trick here is that by treating the queues as a single large queue, the tendency is that the queue's with lots of items will get dequeued more quickly (since there is more chance of getting an index in their range). This means that it should automatically balance consumption between the queues so that they all run dry at (roughly) the same time. If you don't have LINQ, just change the first line:
int remaining = 0;
foreach(Queue<T> q in queues) {remaining += q.Count;}
Example usage:
static void Main()
{
List<Queue<int>> queues = new List<Queue<int>> {
Build(1,2,3,4,5), Build(6,7,8), Build(9,10,11,12,13)
};
foreach (int i in GetItems(queues))
{
Console.WriteLine(i);
}
}
static Queue<T> Build<T>(params T[] items)
{
Queue<T> queue = new Queue<T>();
foreach (T item in items)
{
queue.Enqueue(item);
}
return queue;
}
It depends on what you really want...
If the "random" values are truly random then you will get uniform distribution with enough iterations.
If you're talking about controlling or manipulating the distribution then the values will no longer be truly random!
So, you can either have:
Truly random values with uniform distribution, or
Controlled distribution, but no longer truly random
Are you trying to shuffle your list?
If so you can do it by sorting it on a random value.
Try something like this:
private Random random = new Random();
public int RandomSort(Queue q1, Queue q2)
{
if (q1 == q2) { return 0; }
return random.Next().CompareTo(random.Next());
}
And then use the RandomSort as the argument in a call to List.Sort();
If the items to be queued have a GetHashCode() algorithm which distributes values evenly across all integers, you can take the modulus operator on the hash value to specify which queue to add the item to. This is basically the same principle which hash tables use to assure an even distribution of values.

Categories

Resources