char* generate_seed() { char *stream = (char*)malloc(82); srand(time(NULL)); char* upperleft = create_random_numbers(); char* center = create_random_numbers(); char* lowerright = create_random_numbers(); int index=0; int iSquare = 0; //first three rows for (int i=0; i<3; i++) { for(int j=0; j<3; j++) stream[index++] = upperleft[iSquare++]; for(int j=0; j < 6 ; j++) stream[index++] = '.'; } iSquare = 0; //second three rows for (int i=0; i<3; i++) { for(int j=0; j < 3 ; j++) stream[index++] = '.'; for(int j=0; j<3; j++) stream[index++] = center[iSquare++]; for(int j=0; j < 3 ; j++) stream[index++] = '.'; } iSquare = 0; //third three rows for (int i=0; i<3; i++) { for(int j=0; j < 6 ; j++) stream[index++] = '.'; for(int j=0; j<3; j++) stream[index++] = upperleft[iSquare++]; } stream[81] = '\0'; free(upperleft); free(center); free(lowerright); return stream; }
int main(int argc, char** argv) { if (argc != 2) { fprintf(stderr, "Usage: bin numbers_per_proc\n"); exit(1); } // Get the amount of random numbers to create per process int numbers_per_proc = atoi(argv[1]); MPI_Init(NULL, NULL); int world_rank; MPI_Comm_rank(MPI_COMM_WORLD, &world_rank); int world_size; MPI_Comm_size(MPI_COMM_WORLD, &world_size); // Seed the random number generator to get different results each time srand(time(NULL) * world_rank); // Create the random numbers on this process. Note that all numbers // will be between 0 and 1 float *rand_nums = create_random_numbers(numbers_per_proc); // Given the array of random numbers, determine how many will be sent // to each process (based on the which process owns the number). // The return value from this function is an array of counts // for each rank in the communicator. // The count represents how many numbers each process will receive // when they are binned from this process. int *send_amounts_per_proc = get_send_amounts_per_proc(rand_nums, numbers_per_proc, world_size); // Determine how many numbers you will receive from each process. This // information is needed to set up the binning call. int *recv_amounts_per_proc = get_recv_amounts_per_proc(send_amounts_per_proc, world_size); // Do a prefix sum for the send/recv amounts to get the send/recv offsets for // the MPI_Alltoallv call (the binning call). int *send_offsets_per_proc = prefix_sum(send_amounts_per_proc, world_size); int *recv_offsets_per_proc = prefix_sum(recv_amounts_per_proc, world_size); // Allocate an array to hold the binned numbers for this process based on the total // amount of numbers this process will receive from others. int total_recv_amount = sum(recv_amounts_per_proc, world_size); float *binned_nums = (float *)malloc(sizeof(float) * total_recv_amount); // The final step before binning - arrange all of the random numbers so that they // are ordered by bin. For simplicity, we are simply going to sort the random // numbers, however, this could be optimized since the numbers don't need to be // fully sorted. qsort(rand_nums, numbers_per_proc, sizeof(float), &compare_float); // Perform the binning step with MPI_Alltoallv. This will send all of the numbers in // the rand_nums array to their proper bin. Each process will only contain numbers // belonging to its bin after this step. For example, if there are 4 processes, process // 0 will contain numbers in the [0, .25) range. MPI_Alltoallv(rand_nums, send_amounts_per_proc, send_offsets_per_proc, MPI_FLOAT, binned_nums, recv_amounts_per_proc, recv_offsets_per_proc, MPI_FLOAT, MPI_COMM_WORLD); // Print results printf("Process %d received %d numbers in bin [%f - %f)\n", world_rank, total_recv_amount, get_bin_start(world_rank, world_size), get_bin_end(world_rank, world_size)); // Check that the bin numbers are correct verify_bin_nums(binned_nums, total_recv_amount, world_rank, world_size); MPI_Barrier(MPI_COMM_WORLD); MPI_Finalize(); // Clean up free(rand_nums); free(send_amounts_per_proc); free(recv_amounts_per_proc); free(send_offsets_per_proc); free(recv_offsets_per_proc); free(binned_nums); }