Multiple cores/optimization in C
2 Attachment(s)
Hi, I've wrote this as an university exercise. It is a program to calculate and say if a number is perfect or not.
Code:
#include <stdio.h> |
Use sqrt function to determine the square-root of the number:
Code:
#include <math.h> |
I don't get it. I tested here and it worked but I am not sure why.
Like, take 28 for example, it is a perfect number. maxdiv is sqrt of 28 which is equal to 5.29150262213 but 28 is also divisible by 7. |
when i=4, you program will execute this:
Code:
sum := sum + 4 + 28/4 |
I am still not sure I got it. Anyways, it still takes some time.
|
Here's my multi-threaded version, there's a bit of a problem with number 6, because how can you even split that between say 4 threads ? If you can figure out an algorithm, good for you.
Code:
bash-4.2$ compile pn.c -fopenmp Code:
|
Gonna give your version a shot. I am a still a C begginer and I am trying to understand the code.
Did you try a really large number like 2305843008139952128? I left it running for hours and it didn't finish (I ended up turning off the PC without noticing it :(). My last attempt: Code:
$ time ./numeroperfeito-1 |
Remember that finding primes and perfect numbers is computationally very expensive. Don't expect the calculation of higher values to be doable on a desktop in a day. If you wanted even more optimization, you could try using some MMX or SSE, but I've found that it is very difficult, requires knowledge of assembly, is less portable, and only with an expert's touch can it truly outperform a compiler except in obvious cases (and the compiler is likely to figure these out anyway). If I have more time, I'll see how plausible it is to use MMX or SSE for this. The main problem is that loading and unloading from these registers is slower than for other registers, so you should keep data in the registers if you want a performance improvement.
|
the openmp sample is already nice and goes into the right direction,
additional try help the compiler by passing -funroll-loops -ftree-vectorize -march=corei7-avx (orwhat ever cool cpu you have) and check if your loops are written in a way that the compiler can unroll and verctorize them, do not write sse code by hand, help the copilerr to generate it additionally, no optimization runs out the best, or a better , algorithm, so you can also check it the way you solve the problem is the best to do |
If I recall correctly, all, even, positive perfect numbers can be factored with the equation y = 2^(2x - 1) - 2^(x - 1) when x is a mersenne prime number.
Quote:
|
Quote:
y = 2^(x-1) * (2^x-1) where x is prime and (2^x-1) is also prime. Your equation is equivalent. y is perfect if and only if (2^x-1) is prime. So the search for even perfect numbers is equivalent to searching prime numbers x for those for which (2^x-1) is prime. That is much much faster than directly testing whether y is perfect. There is no proof (so far as I know) that odd perfect numbers don't exist. But it is pretty easy to prove no odd perfect number is small enough to be found with a simplistic search like the programs discussed earlier in this thread (certainly no odd perfect number is smaller than 2^64, so unsigned long could not hold one). So for practical purposes, perfect numbers are even. |
Quote:
If you really wanted to find more perfect numbers, why not try to construct pernicious numbers and test them ? Like the wiki says: 6 = 110 28 = 11100 496 = 111110000 8128 = 1111111000000 33550336 = 1111111111111000000000000 |
http://primes.utm.edu/mersenne/
Another optimization you can make is that, even, perfect numbers end in ether 6 or 8, the pattern of the series can be described with the equation y = 8 - mod(x + x^2, 4). For example: Code:
$ for x in $(cat mersenne_powers); do ((echo "$x, `bc <<< "2^($x-1) * (2^$x-1)" | tail -c 2`")&); done |
Quote:
Code:
$ time echo "2^(10000000-1) * (2^10000000-1)" | bc > /dev/null |
Quote:
The significant time is in testing whether (2^X-1) is prime. Testing whether 2^(X-1)*(2^X-1) is perfect is mathematically equivalent to testing whether (2^X-1) is prime, but since 2^(X-1)*(2^X-1)is a far larger number, directly testing whether it is perfect would be far slower than directly testing whether (2^X-1) is prime. After discovering that (2^X-1) is prime, computing 2^(X-1)*(2^X-1) is trivial, then converting it to decimal for display is bit harder, but still trivial compared to discovering (2^X-1) is prime. |
All times are GMT -5. The time now is 01:13 PM. |