12-01-2009 12:16 PM - edited 12-01-2009 12:21 PM
Since the OP has leave Planet Earth, let's hijack this thread a bit ![]()
I modify my code based on your inputs resulting in a new version that calculates primes to 5E6 in 225ms, that's 94ms faster than the code you posted.
The biggest modification comes from your comment "Simply calculate the multiple indices directly"
Instead of calculating the result of "Value X divided by possible prime P" I just replace the multiples of possible prime P by 0 in the array. So far so good ![]()
From the table below I build up my algorithm
Possible prime : Indices to replace
3 : 4 7 10 13 16
5 : 7 12 17 22 27
7 : 10 17 24 31 38
9: 13 22 31 40 49
11: 16 27 38 49 60
So the algorithm is:
First index: Possible prime + Loop counter + 1
All next indices: Previous index + Possible prime
My stop condition was based on : "Repeat steps 3 and 4 until p2 is greater than n." found on Wikipedia.
But apparently it's faster to check the whole array than to do those operations.
There are still one thing unclear to me:
"Once you are at half-size, there are no multiples left, don't keep looking for them."
I suppose you do this with the code at the Count terminal of the inner For loop.
Let say we check multiples of possible prime 63. With a maximum of 5E6 we have 79365 multiples of 63, according to you one should loop only 39682 through the inner for loop? How come??
It make sense since all even numbers aren't in the array but I think this is also related to the way you calculate the indices to replace because when I use your code at the Count terminal and my way to determine the indices to replace, it go wrong ![]()
12-01-2009 03:38 PM
Alain S wrote:Let say we check multiples of possible prime 63. With a maximum of 5E6 we have 79365 multiples of 63, according to you one should loop only 39682 through the inner for loop? How come??
NO, that's not what I meant! I meant if the current prime is more than half the upper limit, there are no multiples to consider.
I am sure my code can be streamlined quite a bit more. I wrote this many years ago. 😉
(Haven't looked at your code yet....)
12-01-2009 04:20 PM - edited 12-01-2009 04:21 PM
altenbach wrote:(Haven't looked at your code yet....)
OK, your code looks pretty neat. Congratulations! LabVIEW is easy, right 😄
One minor flaw: you can eliminate the "add" in front of the innermost loop if you tap into the add result inside the loop to get the index. This means that the add does not need to execute at all if the inner loop spins zero times. Does not really make a difference though. 😉
I am sure it can be futher improved. 🙂
I also encourage you to use a local variable instead of a property node to reset the switch.
12-02-2009 11:38 AM
altenbach wrote:
Congratulations! LabVIEW is easy, right 😄
One minor flaw: you can eliminate the "add" in front of the innermost loop if you tap into the add result inside the loop to get the index. This means that the add does not need to execute at all if the inner loop spins zero times. Does not really make a difference though. 😉
Easy yes, but sometime tricky 😞
The code with only one Add instruction runs SLOWER then the one with two Add instructions.
This graph was made by running both versions 12 times.
As one can see there's a significant difference between both methods!
The average time with 1 add is about 836ms while it's only 806ms with 2 add's ?? ![]()
Is this a possible explanation fot this:
With only one Add the Replace array subset has to wait for the result of the addition so that both are executed subsequently.
With two add's on the other hand the index is already known so both the Add and Replace array subset are executed in parallel.
Just one wild wild guess!
12-02-2009 01:44 PM
Alain S wrote:With two add's on the other hand the index is already known so both the Add and Replace array subset are executed in parallel.
Just one wild wild guess!
It's a good guess but I have no idea if it is true. 😉
I was running on a single core machine, so it would be interesting to compare if the number of CPUs makes a difference.
For bechmarking, instead of taking the average, I would take the shortest time for each case. Statistically, all external influences tend to add to the time, so the shortest time approaches the limit of no external influences for an infinite number of runs. 😉
You can also tighten up the timing distribution width by elevating the priority of the VI. (I already disable debugging, which also has a big influence here).