MPI_Gather prime number arrays into one array - c

I am trying to split up a program that calculates whether or not a number is a prime. So, I spread out into each process a range of numbers and find the primes in that range. This works, each process takes the range and finds the correct primes. Then when I want to Gather all of the arrays from each process into one is where I am running into problems.
Either it prints out the proper number of array values, but has extra 0's so it will print out something like 2,3,5,7,0,11,13,0,0,0,17,19... or I get the assertion failed error where the memcpy argument memory ranges overlap.
Here is the relevant code in my main -
thesePrimes = (int*)malloc(sizeof(int) * maxNumberOfTotalPrimes);
//findPrimes returns k which is the number of primes found and
//puts all of the prime numbers from this process into thesePrimes.
//n is the highest number to check if prime (ie n = 100 check for primes
//less than 100)
k = findPrimes(thesePrimes, start, end, n);
//Reduce k to get the total number of primes within the input
MPI_Reduce(&k, &numberOfPrimes, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
//Allocate just enough space to hold all of the primes based on the reduced
//number of primes
allPrimes = (int*)malloc(sizeof(int) * numberOfPrimes);
//Gather each process's thesePrimes into allPrimes using k as the buffer
//size since k is the number of primes for the process, just send k numbers
MPI_Gather(thesePrimes, k, MPI_INT, allPrimes, k, MPI_INT, 0, MPI_COMM_WORLD);
if(myRank == 0) {
printf("Attempting to print...\n");
for(i = 0; i < numberOfPrimes; i++)
printf("allPrimes[%d]=%d\n", i, allPrimes[i]);
printf("There are %d prime numbers in the range 0 to %d\n", numberOfPrimes, n);
}
Here is my function to find the number of primes -
int findPrimes(int primes[], int start, int end, int n){
//k is used to count the number of primes
int i, j, maxJ, k = 0;
int isPrime = 1;
printf("Finding primes from %d to %d\n", start, end);
if(end > n) end = n;
if(start == 0) start = 2;
for(i = start; i <= end; i++) {
maxJ = sqrt(i);
for(j = 2; j <= maxJ; j++) {
if(i%j == 0) {
isPrime = 0;
break;
}
}
printf("Checking if %d is prime...\n", i);
if(isPrime) {
primes[k++] = i;
printf("%d is a prime number.\n", primes[k-1]);
}
else isPrime = 1;
// printf("Prime check complete.\n");
}
printf("k = %d\n", k);
return k;
}

You need to MPI_Gather() the number of prime numbers on each rank, and then you will be able to MPI_Gatherv() the prime numbers.

Related

time-saving way to check whether numbers in an array have common factor?

The aim of this assignment is to find the number of pairs can be formed by every two number in an array. The condition is that these two number can not have common factors.
I have tried using loop comparing number by number in an array with a loop of factor starts from 2. This code works but it exceeds the time limit for 2 out of 10 cases on codecrunch.
double estimate_PI(int list[], int size) {
int i, pair;
pair = size * (size - 1) / 2; //total number of pairs can be formed
int count = pair;
int j, l;
for (i = 0; i < size; i++) { //check the first number in the array
for (j = i + 1; j < size; j++) { //check compare the first number of the rest
// of the numbers in the array
for (l = 2; l < list[j]; l++) { //check for common factors
if (list[i] % l == 0 && list[j] % l == 0) { //if these two values have common factor
count--; //the possible number of pair reduce by 1
break;
}
}
}
}
// printf("%d\n count",count);
double PI = sqrt(6.0000 * pair / count);
return PI;
}
For this method it takes too long for the codecrunch to run and it mark me wrong.
Rather than try every value [2...list[j]), perhaps look for the Greatest common divisor
Example int gcd(int a, int b) Arjun Sreedharan or chux
#if 0
for (l = 2; l < list[j]; l++) { //check for common factors
...
}
#else
if (gcd(list[i], list[j]) <= 1) count--;
#endif
Simplification possible as only the first factor > 1 needs to be found.

how can I make this programme faster? [duplicate]

This question already has answers here:
Algorithm to find all the exact divisors of a given integer
(7 answers)
Closed 5 years ago.
The assignment was to write a program which reads in an integer k, and prints out the number of positive integers
between 1 and 100000 (inclusive) which have exactly k divisors. As an example, the number 24 has 8 divisors:
1, 2, 3, 4, 6, 8, 12, and 24.
I have a running programme, but is there anyway i could make the search faster??
#include <stdio.h>
#include <math.h>
int main(void)
{ int a; //user input//
int divisors; //running total of number of divisors//
int sum; //running total of numbers with the required number of divisors//
printf("Enter the target number of divisors:");
scanf("%d", &a);
printf("\n");
int i;
for (i=1; i<=100000; i++)
{
divisors=2;
int p;
for(p=2; p<i; p++)
{if (i%p==0)
divisors++;}
if (divisors==a)
sum++;}
printf("There are %d numbers between 1 and 100000 inclusive which have exactly %d divisors.", sum, a);
return 0;
}
Example code. Moved declarations for i and p to be compatible with old C type compilers (I'm using Microsoft / Visual Studio). Uses ceil(sqrt(i)) outer loops. The code handles an input of 1 (only the number 1 has 1 divisor). An input of 2 will output the number of prime numbers less than 100,000 (there are 9592 prime numbers less than 100,000).
This method takes a bit over 21 million iterations. Number of iterations ~= .67 n sqrt(n).
#include <stdio.h>
int main(void)
{
int a; /* user input */
int divisors; /* total number of divisors */
int sum; /* count of numbers with required number of divisors */
int i; /* moved here for C compiler */
int p; /* moved here for C compiler */
int sqrti; /* ceil(sqrt(i)) */
printf("Enter the target number of divisors: ");
scanf("%d", &a);
printf("\n");
sum = 0; /* init sum */
sqrti = 1; /* init sqrti */
for (i = 1; i <= 100000; i++)
{
divisors = 0; /* init number of divisors */
if(sqrti*sqrti < i) /* update sqrti as needed */
sqrti += 1;
for(p = 1; p < sqrti; p++)
if(i%p == 0) /* if p is a divisor, count it and i/p */
divisors += 2;
if(p*p == i) /* if p*p == i, count it */
divisors += 1;
if (divisors == a) /* if i has a divisors, increment sum */
sum += 1;
}
printf("There are %d numbers from 1 to 100000 inclusive which have exactly %d divisors.\n", sum, a);
return 0;
}
If an array can be used similar to sieve method for primes, this method takes a bit over 1 million iterations. Number of iterations ~= n ln(n).
#include <stdio.h>
#define n 100000
int main(void)
{
int * cnt = (int *)calloc(n+1, sizeof(int));
int d;
printf("Enter the target number of divisors: ");
scanf("%d", &d);
/* time complexity O(n log(n)) */
{
int i, j;
for (i = 1; i <= n; i++) {
for(j = i; j <= n; j += i) {
cnt[j]++;
}
}
}
{
int i;
int sum = 0;
for (i = 1; i <= n; i++)
sum += (cnt[i] == d) ? 1 : 0;
printf("excactly %d numbers have %d divisors\n", sum, d);
}
free(cnt);
return 0;
}
Rather than checking for the value of p uptil i we can optimize by checking until sqrt(i) and instead of incrementing divisors by 1, we increament it by 2, one for the number say k divided by i and second for the number i/k.
n=1000000;
for (i=1; i<=10000; i++)
{
divisors=2;
int p;
for(p=2; p<=sqrt(i); p++)
{
if (i%p==0)
{
if(p != (i/p)
divisors = divisors + 2;
else
divisors++;
}
}
if (divisors==a)
sum++;
}

C Program to calculate perfect, amicable and sociable numbers

I am using Dev C++ and the program is running without errors. The problem that I have is that it repeats numbers from previous cycles and I have no effective way to calculate how many of those numbers are perfect, amicable or just sociable.
This is the main program:
int main()
{
int per = 0, cyc = 0, ami = 0, rep = 0;
for(int n = 2; n < MAXNUM; n++){
int f = 0;
for(int c = 1; !f && c <= MAXCYC; c++){
rep = c;
long a = n;
while(rep--) a = divs(a);
rep = c;
if(n == a ){
printf("Cycle of length %d: %d", c, n);
while(rep --){
a = divs(a);
printf(" %ld", a);
cyc++;
}
printf("\n");
f = 1;
}
}
}
printf("\nFound %d cycles including \n", cyc);
printf("%d cycles with perfect numbers and \n", per);
printf("%d cycles with amicable numbers\n", ami);
return 0;
}
How can I make it so it won't repeat numbers from previous cycles as starting points for new cycles while having my per and ami counters going up? Also I can't use arrays as I am not allowed to.

MPI_Scatter and MPI_Reduce

I'm trying to find the max of randomly generated numbers. Any thoughts on this...
I am using MPI_Scatter to split the randomly generated numbers into equal processes. I am using MPI_Reduce to get the MAX from each process.
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <mpi.h>
#define atmost 1000
int find(int* partial_max, int from, int to){
int i, max;
printf("%d----%d\n", from, to);
max = partial_max[from];
for (i = from + 1; i <= to; i++)
if (partial_max[i] > max)
max = partial_max[i];
return max;
}
int main(){
int i, j,n, comm_sz, biggest, b, my_rank, q,result;
//1. Declare array of size 1000
int a[atmost];
//2. generate random integer of 0 to 999
srand((unsigned)time(NULL));
n = rand() % atmost;
//n = 10;
for (i = 0; i <= n; i++){
a[i] = rand() % atmost;
printf("My Numbers: %d\n", a[i]);
//a[i] = i;
}
MPI_Init(NULL, NULL);
MPI_Comm_size(MPI_COMM_WORLD, &comm_sz);
MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
//j is the size we will split each segment into
j = (n / (comm_sz-1));
int partial_max[j];
int receive_vector[j];
//Send random numbers equally to each process
MPI_Scatter(a, j, MPI_INT, receive_vector,
j, MPI_INT, 0, MPI_COMM_WORLD);
int localmax;
localmax = -1;
for (i = 0; i <= comm_sz-1; i++)
if (receive_vector[i] > localmax)
localmax = receive_vector[i];
// Get Max from each process
//MPI_Reduce(receive_vector, partial_max, j, MPI_INT, MPI_MAX, 0, MPI_COMM_WORLD);
MPI_Reduce(&localmax, &result, 1, MPI_INT, MPI_MAX, 0, MPI_COMM_WORLD);
if (my_rank == 0)
{
/*
biggest = -1;
for (i = 0; i < comm_sz - 1; i++){
if (i == comm_sz - 2)
b = find(partial_max, i * j, n - 1);
else
b = find(partial_max, i * j, (i + 1) * j - 1);
if (b > biggest)
biggest = b;
}*/
printf("-------------------\n");
printf("The biggest is: %d\n", result);
printf("The n is: %d\n", n);
}
MPI_Finalize();
return 0;
}
You have few bugs there:
You select (a different value of) n in each process. It is better to
select it within rank 0 and bcast to the rest of the processes.
When calculating j you divise by comm_sz-1 instead of comm_sz.
You assume n is divisible by comm_sz and that each process receives the exact same amount of numbers to process.
You loop with i going up to comm_sz-1 instead of going up to j
This is what I could find in a quick look..

Prime numbers in C and is_prime

I'm writing a program to find all of the prime numbers contained within a user input n. I am having trouble with the is_prime function.
#include <stdio.h>
#include <math.h>
main() {
int n;
int k;
// gets user input for length of string
// and stores it as n
printf("Enter the value of n:");
scanf("%d", &n);
for (k = 2; k <= n; k++) {
if (is_Prime(k) == 1) {
printf("Printing primes less than or equal to %d: /n %d, &n, &k");
}
}
I want the output to look like this, but I am not sure how to print the list without using different variables for each prime number.
Printing primes less than or equal to 30:
2, 3, 5, 7, 11, 13, 17, 19, 23, 29.
//here is the is_Prime function
is_Prime (int n)
{
for(j = 2; j <= n/2; j++)
{
if(n%j != 0)
{
return 1;
break;
}
}
if(n%j == 0 )
return 0;
}
I am not sure how to call the is_prime subroutine? Any help?
printf("Printing primes less than or equal to %d:\n", n);
for(k = 2; k <= n; k++)
{
if(is_Prime(k) == 1)
{
printf("%d, ", k);
}
}
printf("Printing primes less than or equal to %d:\n%s", n, (n >= 2 ? "2" : ""));
for (k = 3; k <= n; ++k)
if (is_Prime(k))
printf(", %d", k);
printf("%s\n", (n >= 2 ? "." : ""));
Here's a slightly cleaner version of your is_Prime function:
int is_Prime(int n)
{
if (n < 2)
return 0;
int last = (int) sqrt(n) + 1; /* conservatively safe */
for (int j = 2; j <= last; ++j)
if (0 == n % j)
return 0;
return 1;
}
Note that you only really need to check up to the sqrt() of a number to find all its potential factors.
Also note that this is not a great way to find all the primes less than n, which is the prime purpose of your program, especially when you will repeatedly call this function incrementing n by 1 each time. I recommend trying to implement the Sieve of Eratosthenes or the Sieve of Sundaram instead -- so long as n isn't too large.

Resources