Skip to content

Instantly share code, notes, and snippets.

@stone3311
Created May 1, 2016 20:35
Show Gist options
  • Select an option

  • Save stone3311/38744ef8041ff7c00be7e6218c4ef843 to your computer and use it in GitHub Desktop.

Select an option

Save stone3311/38744ef8041ff7c00be7e6218c4ef843 to your computer and use it in GitHub Desktop.
This is a program which calculates primes using MPI.
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <mpi.h>
#define PRIME_MAX 1000000
#define SEND_CHUNK_SIZE 10000
#define SAVE_CHUNK_SIZE 1000
#define CHUNKS_PER_FILE 100
inline int isprime (unsigned long number) {
if (number < 2) return 0;
if (number == 2) return 1;
if (!(number % 2)) return 0;
int max = ceil(sqrt(number));
for (int i = 2; i <= max; i++) {
if (number % i == 0) return 0;
}
return 1;
}
int main (int argc, char** argv) {
MPI_Init(&argc, &argv);
int rank = 0;
int size;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
if (size < 2) {
printf("Controller: Not enough nodes; Exiting\n");
MPI_Finalize();
exit(-1);
}
if (rank == 0) {
unsigned long buf[SAVE_CHUNK_SIZE];
int buf_size = 0;
unsigned int chunks_written = 0;
unsigned int chunks_written_cur_file = 0;
unsigned int fileno = 0;
unsigned int calculating = size - 1;
FILE *file = fopen("/tmp/prime0.bin", "a");
printf("Controller: Ready\n");
MPI_Barrier(MPI_COMM_WORLD); // Sync
printf("Controller: Prime calculation started\n");
do {
MPI_Status status;
unsigned long tmp_buf[SEND_CHUNK_SIZE];
MPI_Recv(&tmp_buf, SEND_CHUNK_SIZE, MPI_UNSIGNED_LONG, MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
if (tmp_buf[0] == 0) {
calculating--;
continue;
}
int count = 0;
MPI_Get_count(&status, MPI_UNSIGNED_LONG, &count);
for (int i=0; i < count; i++) {
unsigned long *cur_ptr = buf + buf_size;
*cur_ptr = tmp_buf[i];
buf_size++;
if (buf_size == SAVE_CHUNK_SIZE) {
if (chunks_written_cur_file == CHUNKS_PER_FILE) {
fclose(file);
fileno++;
chunks_written_cur_file = 0;
char filename[100];
sprintf(filename, "/tmp/prime%d.bin", fileno);
file = fopen(filename, "a");
}
fwrite(buf, sizeof(unsigned long), SAVE_CHUNK_SIZE, file);
buf_size = 0;
chunks_written++;
chunks_written_cur_file++;
printf("Controller: Chunk %d written to file %d\n", chunks_written, fileno);
}
}
} while (calculating > 0);
if (buf_size > 0) {
fwrite(buf, sizeof(unsigned long), buf_size, file);
}
fclose(file);
printf("Controller: Calculation done. %d chunks written to %d files.\n", chunks_written, fileno+1);
}
else {
unsigned long my_start;
if (rank == 1) {
my_start = 0;
} else {
MPI_Recv(&my_start, 1, MPI_UNSIGNED_LONG, rank-1, MPI_ANY_TAG, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}
const unsigned long num_sum = PRIME_MAX*(PRIME_MAX*0.5+0.5);
// sqrt(2*(rank/size)*SUMME+0,25)-0,5
const unsigned long my_stop = ceil(sqrt(2.0*((double)rank/(size-1.0))*(double)num_sum+0.25)-0.5);
if (rank != size-1) {
const unsigned long send_buf = my_stop + 1;
MPI_Send(&send_buf, 1, MPI_UNSIGNED_LONG, rank+1, 0, MPI_COMM_WORLD);
}
unsigned long buf[SEND_CHUNK_SIZE];
unsigned int buf_size = 0;
printf("Node %d: Ready: I will be calculating %ld to %ld\n", rank, my_start, my_stop);
MPI_Barrier(MPI_COMM_WORLD); // Sync
for (unsigned long number = my_start; number <= my_stop; number++) {
if (isprime(number)) {
buf[buf_size] = number;
buf_size++;
if (buf_size == SEND_CHUNK_SIZE) {
MPI_Send(&buf, SEND_CHUNK_SIZE, MPI_UNSIGNED_LONG, 0, 0, MPI_COMM_WORLD);
buf_size = 0;
}
}
}
if (buf_size > 0) {
MPI_Send(&buf, buf_size, MPI_UNSIGNED_LONG, 0, 0, MPI_COMM_WORLD);
}
const unsigned long quit_msg = 0;
MPI_Send(&quit_msg, 1, MPI_UNSIGNED_LONG, 0, 0, MPI_COMM_WORLD);
printf("Node %d: Done\n", rank);
}
MPI_Finalize();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment