CC BY 4.0 (除特别声明或转载文章外)
如果这篇博客帮助到你,可以请我喝一杯咖啡~
第一次做不是ACM的题解了。
使用MPI实现2.7.1节讨论的直方图程序,进程0读取输入的数据,并将它们分配到其余进程,最后进程0打印该直方图。 请根据提供的代码,将代码补充完整! 需要补充的部分见注释 PLEASE ADD THE RIGHT CODES 部分。可直接点击下方作业题目跳转至在线编程平台,点击参考代码,补充完整后提交。(或下载附件 prog3.1_mpi_histo(blank).zip)
在参考代码的基础上加了155行和168~175行就解决问题了。这里找对应下标的时候使用了二分,其实是可以直接算出来的。
/*
* File: prog3.1_mpi_histo.c
*
* Purpose: Use MPI to implement a program that creates a histogram
*
* Compile: mpicc -g -Wall -o prog3.1_mpi_histo prog3.1_mpi_histo.c
* Run: mpiexec -n <comm_sz> ./prog3.1_mpi_histo
*
* Input: Number of bins
* Minimum measurement
* Maximum measurement
* Number of data items
*
* Output: Histogram of the data. If DEBUG flag is set, the data
* generated.
*
* Notes:
* 1. The number of data must be evenly divisible by the number of processes
* 2. The program generates random floats x in the range
*
* min measurement <= x < max measurement
*
* 3. If i >= 1, the ith bin contains measurements x in the
* range
*
* bin_maxes[i-1] <= x < bin_maxes[i]
*
* Bin 0 will contain measurements x in the range
*
* min measurement <= x < bin_maxes[0]
*
*
* IPP: Programming Assignment 3.1
*/
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
void Get_input(int *bin_count_p, float *min_meas_p, float *max_meas_p,
int *data_count_p, int *local_data_count_p, int my_rank,
int comm_sz, MPI_Comm comm);
void Check_for_error(int local_ok, char fname[], char message[],
MPI_Comm comm);
void Gen_data(float local_data[], int local_data_count, int data_count,
float min_meas, float max_meas, int my_rank, MPI_Comm comm);
void Set_bins(float bin_maxes[], int loc_bin_cts[], float min_meas,
float max_meas, int bin_count, int my_rank, MPI_Comm comm);
void Find_bins(int bin_counts[], float local_data[], int loc_bin_cts[],
int local_data_count, float bin_maxes[],
int bin_count, float min_meas, MPI_Comm comm);
int Which_bin(float data, float bin_maxes[], int bin_count,
float min_meas);
void Print_histo(float bin_maxes[], int bin_counts[], int bin_count,
float min_meas);
/*---------------------------------------------------------------------*/
int main(void)
{
int bin_count;
float min_meas, max_meas;
float *bin_maxes;
int *bin_counts;
int *loc_bin_cts;
int data_count;
int local_data_count;
float *data;
float *local_data;
int my_rank, comm_sz;
MPI_Comm comm;
MPI_Init(NULL, NULL);
comm = MPI_COMM_WORLD;
MPI_Comm_size(comm, &comm_sz);
MPI_Comm_rank(comm, &my_rank);
// get user inputs for bin_count, max_meas, min_meas, and data_count
Get_input(&bin_count, &min_meas, &max_meas, &data_count,
&local_data_count, my_rank, comm_sz, comm);
// allocate arrays
bin_maxes = malloc(bin_count * sizeof(float));
bin_counts = malloc(bin_count * sizeof(int));
loc_bin_cts = malloc(bin_count * sizeof(int));
data = malloc(data_count * sizeof(float));
local_data = malloc(local_data_count * sizeof(float));
Set_bins(bin_maxes, loc_bin_cts, min_meas, max_meas, bin_count,
my_rank, comm);
Gen_data(local_data, local_data_count, data_count, min_meas,
max_meas, my_rank, comm);
Find_bins(bin_counts, local_data, loc_bin_cts, local_data_count,
bin_maxes, bin_count, min_meas, comm);
if (my_rank == 0)
Print_histo(bin_maxes, bin_counts, bin_count, min_meas);
free(bin_maxes);
free(bin_counts);
free(loc_bin_cts);
free(data);
free(local_data);
MPI_Finalize();
return 0;
} /* main */
/*---------------------------------------------------------------------*/
void Print_histo(
float bin_maxes[] /* in */,
int bin_counts[] /* in */,
int bin_count /* in */,
float min_meas /* in */)
{
int i, j;
float bin_max, bin_min;
for (i = 0; i < bin_count; i++)
{
bin_max = bin_maxes[i];
bin_min = (i == 0) ? min_meas : bin_maxes[i - 1];
printf("%.3f-%.3f:\t", bin_min, bin_max);
for (j = 0; j < bin_counts[i]; j++)
printf("X");
printf("\n");
}
} /* Print_histo */
/*---------------------------------------------------------------------*/
void Find_bins(
int bin_counts[] /* out */,
float local_data[] /* in */,
int loc_bin_cts[] /* out */,
int local_data_count /* in */,
float bin_maxes[] /* in */,
int bin_count /* in */,
float min_meas /* in */,
MPI_Comm comm)
{
int i, bin;
for (i = 0; i < local_data_count; i++)
{
bin = Which_bin(local_data[i], bin_maxes, bin_count, min_meas);
loc_bin_cts[bin]++;
}
/*******************************************************************/
//PLEASE ADD THE RIGHT CODES
MPI_Reduce(loc_bin_cts, bin_counts, bin_count, MPI_INT, MPI_SUM, 0, comm);
/******************************************************************/
} /* Find_bins */
/*---------------------------------------------------------------------*/
int Which_bin(float data, float bin_maxes[], int bin_count,
float min_meas)
{
/*******************************************************************/
//PLEASE ADD THE RIGHT CODES
int b = 0, e = bin_count;
while (e - b > 1)
{
int m = b + (e - b) / 2;
data < bin_maxes[m] ? (b = m) : (e = m);
}
if (b)
return b;
/******************************************************************/
printf("Uh oh . . .\n");
return 0;
} /* Which_bin */
/*---------------------------------------------------------------------*/
void Set_bins(
float bin_maxes[] /* out */,
int loc_bin_cts[] /* out */,
float min_meas /* in */,
float max_meas /* in */,
int bin_count /* in */,
int my_rank /* in */,
MPI_Comm comm /* in */)
{
if (my_rank == 0)
{
int i;
float bin_width;
bin_width = (max_meas - min_meas) / bin_count;
for (i = 0; i < bin_count; i++)
{
loc_bin_cts[i] = 0;
bin_maxes[i] = min_meas + (i + 1) * bin_width;
}
}
// set bin_maxes for each proc
MPI_Bcast(bin_maxes, bin_count, MPI_FLOAT, 0, comm);
// reset loc_bin_cts of each proc
MPI_Bcast(loc_bin_cts, bin_count, MPI_INT, 0, comm);
} /* Set_bins */
/*---------------------------------------------------------------------*/
void Gen_data(
float local_data[] /* out */,
int local_data_count /* in */,
int data_count /* in */,
float min_meas /* in */,
float max_meas /* in */,
int my_rank /* in */,
MPI_Comm comm /* in */)
{
int i;
float *data = NULL;
if (my_rank == 0)
{
data = malloc(data_count * sizeof(float));
srandom(1);
for (i = 0; i < data_count; i++)
data[i] =
min_meas + (max_meas - min_meas) * random() / ((double)RAND_MAX);
#ifdef DEBUG
printf("Generated data:\n ");
for (i = 0; i < data_count; i++)
printf("%.3f ", data[i]);
printf("\n\n");
#endif
MPI_Scatter(data, local_data_count, MPI_FLOAT, local_data,
local_data_count, MPI_FLOAT, 0, comm);
free(data);
}
else
{
MPI_Scatter(data, local_data_count, MPI_FLOAT, local_data,
local_data_count, MPI_FLOAT, 0, comm);
}
} /* Gen_data */
/*---------------------------------------------------------------------*/
void Get_input(int *bin_count_p, float *min_meas_p, float *max_meas_p,
int *data_count_p, int *local_data_count_p, int my_rank,
int comm_sz, MPI_Comm comm)
{
int local_ok = 1;
if (my_rank == 0)
{
printf("Enter the number of bins\n");
scanf("%d", bin_count_p);
printf("Enter the minimum measurement\n");
scanf("%f", min_meas_p);
printf("Enter the maximum measurement\n");
scanf("%f", max_meas_p);
printf("Enter the number of data\n");
scanf("%d", data_count_p);
}
MPI_Bcast(bin_count_p, 1, MPI_INT, 0, comm);
MPI_Bcast(min_meas_p, 1, MPI_INT, 0, comm);
MPI_Bcast(max_meas_p, 1, MPI_INT, 0, comm);
MPI_Bcast(data_count_p, 1, MPI_INT, 0, comm);
if (*data_count_p % comm_sz != 0)
local_ok = 0;
Check_for_error(local_ok, "Get_input",
"data_count must be evenly divisible by comm_sz",
comm);
*local_data_count_p = *data_count_p / comm_sz;
} /* Get_input */
/*---------------------------------------------------------------------*/
void Check_for_error(
int local_ok /* in */,
char fname[] /* in */,
char message[] /* in */,
MPI_Comm comm /* in */)
{
int ok;
MPI_Allreduce(&local_ok, &ok, 1, MPI_INT, MPI_MIN, comm);
if (ok == 0)
{
int my_rank;
MPI_Comm_rank(comm, &my_rank);
if (my_rank == 0)
{
fprintf(stderr, "Proc %d > In %s, %s\n", my_rank, fname,
message);
fflush(stderr);
}
MPI_Finalize();
exit(-1);
}
} /* Check_for_error */