Created
May 1, 2016 20:35
-
-
Save stone3311/38744ef8041ff7c00be7e6218c4ef843 to your computer and use it in GitHub Desktop.
This is a program which calculates primes using MPI.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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