【问题标题】:Fetching array for input return wrong result获取输入数组返回错误结果
【发布时间】:2019-09-15 21:07:28
【问题描述】:

我尝试使用蒙特卡罗方法评估 pi 值。更准确地说,使用圆周法。

最初我写了一个迭代次数是固定的代码。现在,我试图模拟代码在输入增长时的行为。

为此,我编写了这段代码,但它不起作用:

#define _XOPEN_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <mpi.h>

#define SEED time(NULL)

int main(int argc, char **argv) {

  int rank, size;
  unsigned int seed;
  double x, y, start, end;
  long long int i, j, all_point, points = 0, all_intern;

  long long int dim[] = {5, 50, 500, 5000, 50000, 500000, 5000000, 50000000};

  MPI_Init(&argc, &argv);
  start = MPI_Wtime();

  MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  MPI_Comm_size(MPI_COMM_WORLD, &size);

  seed = SEED + rank;

  for ( j = 0; j < 8; j++ ) {
    for ( i = 0; i < dim[j]; i++ ) {
      x = (double) rand_r(&seed) / RAND_MAX;
      y = (double) rand_r(&seed) / RAND_MAX;

      if ( x * x + y * y <= 1.0 ) points++;
    }

    MPI_Reduce(&points, &all_intern, 1, MPI_LONG_LONG_INT, MPI_SUM, 0, MPI_COMM_WORLD);
    all_point = dim[j] * size;

    MPI_Barrier(MPI_COMM_WORLD);
    end = MPI_Wtime();

    if ( rank == 0 ) {
      printf("\u03C0 \u2248 %Lf\n", (long double) all_intern / all_point * 4.0);
      printf("Time elapsed: %.4f\n", end - start);
    }
  }

  MPI_Finalize();
  return 0;
}

【问题讨论】:

  • 不起作用是什么意思?
  • @Chelmy88 它评估了错误的 pi 值。如果您固定迭代次数,则打印的 pi 值是正确的
  • 我认为当你进入j循环时points应该重置为0,或者如果你想保留以前的迭代,所有all_points应该是dim&lt;=j的总和。跨度>
  • @Chelmy88 你能解释得更好吗?
  • "它评估错误的 pi 值" --> 发布您的输出和预期输出会有所帮助。

标签: c mpi simulation


【解决方案1】:

问题在于points 的值在每次迭代之间不会重置为零,而all_point 仅计算当前迭代的总点数。因此,要么重置points 的值,要么正确计算all_point。由于在 cmets 中并不清楚,因此您可以在下面找到我进行修改的代码中带有 cmets 的两个变体。我删除了所有MPI 内容,因为这不是MPI 问题。

变体 1:重置圆中点的计数器

#define _XOPEN_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define SEED time(NULL)

int main(int argc, char **argv) {

  unsigned int seed;
  double x, y, start, end;
  long long int i, j, all_point, points = 0, all_intern;

  long long int dim[] = {5, 50, 500, 5000,50000,500000,5000000,50000000};

  seed = SEED + 1;

  for ( j = 0; j < 8; j++ ) {
    // reset points to 0 here
    points=0;
    for ( i = 0; i < dim[j]; i++ ) {
      x = (double) rand_r(&seed) / RAND_MAX;
      y = (double) rand_r(&seed) / RAND_MAX;

      if ( x * x + y * y <= 1.0 ) points++;
    }

    all_point = dim[j];

    printf("\u03C0 \u2248 %Lf\n", (long double) points / all_point * 4.0);

  }

  return 0;
}

变体 2:保留先前迭代的结果,但调整总点数

#define _XOPEN_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define SEED time(NULL)

int main(int argc, char **argv) {

  unsigned int seed;
  double x, y, start, end;
  long long int i, j, all_point, points = 0, all_intern;

  long long int dim[] = {5, 50, 500, 5000,50000,500000,5000000,50000000};

  seed = SEED + 1;

  for ( j = 0; j < 8; j++ ) {
    for ( i = 0; i < dim[j]; i++ ) {
      x = (double) rand_r(&seed) / RAND_MAX;
      y = (double) rand_r(&seed) / RAND_MAX;

      if ( x * x + y * y <= 1.0 ) points++;
    }
    // Correctly count the total of points used
    // since the beginning
    all_point=0;
    for ( int k = 0; k <= j; k++ ) {
        all_point += dim[k];
    }

    printf("\u03C0 \u2248 %Lf\n", (long double) points / all_point * 4.0);

  }

  return 0;
}

在这两种情况下,输出都是相似且正确的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-05
    • 1970-01-01
    • 2018-05-04
    • 2013-01-11
    相关资源
    最近更新 更多