Monte Carlo pi 近似的并行化

2023-12-21

我正在编写一个 C 脚本来与 OpenMp 并行化 pi 近似。我认为我的代码运行良好,输出令人信服。我现在用 4 个线程运行它。我不确定的是,这段代码是否容易受到竞争条件的影响?如果是,我如何协调这段代码中的线程操作?

代码如下:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <omp.h>

double sample_interval(double a, double b) {

  double x = ((double) rand())/((double) RAND_MAX);
  return (b-a)*x + a;

}

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


  int N = atoi( argv[1] ); // convert command-line input to N = number of points
  int i;
  int NumThreads = 4;
  const double pi = 3.141592653589793;
  double x, y, z;
  double counter = 0;



  #pragma omp parallel firstprivate(x, y, z, i) reduction(+:counter) num_threads(NumThreads)
 {
  srand(time(NULL));
  for (int i=0; i < N; ++i) 
  {
    x = sample_interval(-1.,1.);
    y = sample_interval(-1.,1.);
    z = ((x*x)+(y*y));

    if (z<= 1) 
   {
      counter++;
    }
  }

 } 
  double approx_pi = 4.0 * counter/ (double)N;

  printf("%i %1.6e %1.6e\n ", N, 4.0 * counter/ (double)N, fabs(4.0 * counter/ (double)N - pi) / pi);


  return 0;

}

我还想知道随机数的种子是否应该在并行化内部或外部声明。我的输出如下所示:

10 3.600000e+00 1.459156e-01
100 3.160000e+00 5.859240e-03
1000 3.108000e+00 1.069287e-02
10000 3.142400e+00 2.569863e-04
100000 3.144120e+00 8.044793e-04
1000000 3.142628e+00 3.295610e-04
10000000 3.141379e+00 6.794439e-05
100000000 3.141467e+00 3.994585e-05
1000000000 3.141686e+00 2.971945e-05

目前看起来还不错。非常欢迎您对比赛条件和种子安置提出建议。


我可以看到您的代码中存在一些问题。从我的角度来看,主要的一点是它不是并行的。或者更准确地说,您在编译 OpenMP 时没有启用通过 OpenMP 引入的并行性。人们可以通过以下方式看到这一点:

代码并行化的方式,主要for循环应该由所有线程完整执行(这里没有工作共享,没有#pragma omp parallel for,只有一个#pragma omp parallel)。因此,考虑到您将线程数设置为 4,则全局迭代次数应为4*N。因此,你的输出应该慢慢向 4*Pi 收敛,而不是向 Pi 收敛。

事实上,我在我的笔记本电脑上尝试了您的代码,并使用 OpenMP 支持对其进行了编译,这几乎就是我得到的结果。但是,当我不启用 OpenMP 时,我会得到与您类似的输出。所以总而言之,你需要:

  1. 在编译时启用 OpenMP 以获得代码的并行版本。
  2. 将你的结果除以NumThreads获得 Pi 的“有效”近似值(或将循环分布在N with a #pragma omp for例如)

但这是指您的代码在其他地方是否正确,但目前还不是。 正如 BitTickler 已经暗示的那样,rand()不是线程安全的。所以你必须寻找另一个随机数生成器,这将允许你将其状态私有化。那可能是rand_r()例如。也就是说,这仍然存在很多问题:

  1. rand() / rand_r() is a terribleRNG 的随机性和周期性。在增加尝试次数的同时,您将快速经历 RNG 的周期并一遍又一遍地重复相同的序列。你需要更强大的东西来完成任何严肃的事情。
  2. 即使使用“好的”RNG,并行性方面也可能是一个问题,因为您希望并行的序列彼此之间不相关。仅在每个线程使用不同的种子值并不能保证这一点(尽管使用足够宽的 RNG,您有一些空间)

无论如何,底线是:

  • 使用更好的线程安全 RNG(我发现drand48_r() or random_r()对于 Linux 上的玩具代码来说是可以的)
  • 例如,根据线程 ID 初始化每个线程的状态,同时请记住,这不能确保在某些情况下随机序列的正确解相关(并且调用函数的次数越多,就越有可能你最终会有重叠的系列)。

完成此操作(以及一些小的修复),您的代码将如下所示:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <math.h>
#include <omp.h>

typedef struct drand48_data RNGstate;

double sample_interval(double a, double b, RNGstate *state) {
    double x;
    drand48_r(state, &x);
    return (b-a)*x + a;
}

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

    int N = atoi( argv[1] ); // convert command-line input to N = number of points
    int NumThreads = 4;
    const double pi = 3.141592653589793;
    double x, y, z;
    double counter = 0;
    time_t ctime = time(NULL);

    #pragma omp parallel private(x, y, z) reduction(+:counter) num_threads(NumThreads)
    {
        RNGstate state;
        srand48_r(ctime+omp_get_thread_num(), &state);
        for (int i=0; i < N; ++i) {
            x = sample_interval(-1, 1, &state);
            y = sample_interval(-1, 1, &state);
            z = ((x*x)+(y*y));

            if (z<= 1) {
                counter++;
            }
        }

    } 
    double approx_pi = 4.0 * counter / (NumThreads * N);

    printf("%i %1.6e %1.6e\n ", N, approx_pi, fabs(approx_pi - pi) / pi);

    return 0;
}

我这样编译:

gcc -std=gnu99 -fopenmp -O3 -Wall pi.c -o pi_omp
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Monte Carlo pi 近似的并行化 的相关文章

  • 创建 DirectoryEntry 实例以供测试使用

    我正在尝试创建 DirectoryEntry 的实例 以便可以使用它来测试将传递 DirectoryEntry 的一些代码 然而 尽管进行了很多尝试 我还是找不到实例化 DE 并初始化它的 PropertyCollection 的方法 我有
  • Cygwin 下使用 CMake 编译库

    我一直在尝试使用 CMake 来编译 TinyXML 作为一种迷你项目 尝试学习 CMake 作为补充 我试图将其编译成动态库并自行安装 以便它可以工作 到目前为止 我已经设法编译和安装它 但它编译成 dll 和 dll a 让它工作的唯一
  • 如何在 WPF RichTextBox 中跟踪 TextPointer?

    我正在尝试了解 WPF RichTextBox 中的 TextPointer 类 我希望能够跟踪它们 以便我可以将信息与文本中的区域相关联 我目前正在使用一个非常简单的示例来尝试弄清楚发生了什么 在 PreviewKeyDown 事件中 我
  • 使用 C# 在 WinRT 中获取可用磁盘空间

    DllImport kernel32 dll SetLastError true static extern bool GetDiskFreeSpaceEx string lpDirectoryName out ulong lpFreeBy
  • C# 用数组封送结构体

    假设我有一个类似于 public struct MyStruct public float a 我想用一些自定义数组大小实例化一个这样的结构 在本例中假设为 2 然后我将其封送到字节数组中 MyStruct s new MyStruct s
  • A* 之间的差异 pA = 新 A;和 A* pA = 新 A();

    在 C 中 以下两个动态对象创建之间的确切区别是什么 A pA new A A pA new A 我做了一些测试 但似乎在这两种情况下 都调用了默认构造函数 并且仅调用了它 我正在寻找性能方面的任何差异 Thanks If A是 POD 类
  • 使用向量的 merge_sort 在少于 9 个输入的情况下效果很好

    不知何故 我使用向量实现了合并排序 问题是 它可以在少于 9 个输入的情况下正常工作 但在有 9 个或更多输入的情况下 它会执行一些我不明白的操作 如下所示 Input 5 4 3 2 1 6 5 4 3 2 1 9 8 7 6 5 4 3
  • 初始化变量的不同方式

    在 C 中初始化变量有多种方法 int z 3 与 int 相同z 3 Is int z z 3 same as int z z 3 您可以使用 int z z 3 Or just int z 3 Or int z 3 Or int z i
  • 更改窗口的内容 (WPF)

    我创建了一个简单的 WPF 应用程序 它有两个 Windows 用户在第一个窗口中填写一些信息 然后单击 确定 这会将他们带到第二个窗口 这工作正常 但我试图将两个窗口合并到一个窗口中 这样只是内容发生了变化 我设法找到了这个更改窗口内容时
  • .NET 选项将视频文件流式传输为网络摄像头图像

    我有兴趣开发一个应用程序 它允许我从 xml 构建视频列表 包含视频标题 持续时间等 并将该列表作为我的网络摄像头流播放 这意味着 如果我要访问 ustream tv 或在实时通讯软件上激活我的网络摄像头 我的视频播放列表将注册为我的活动网
  • 可空属性与可空局部变量

    我对以下行为感到困惑Nullable types class TestClass public int value 0 TestClass test new TestClass Now Nullable GetUnderlyingType
  • 什么是 C 语言的高效工作流程? - Makefile + bash脚本

    我正在开发我的第一个项目 该项目将跨越多个 C 文件 对于我的前几个练习程序 我只是在中编写了我的代码main c并使用编译gcc main c o main 当我学习时 这对我有用 现在 我正在独自开展一个更大的项目 我想继续自己进行编译
  • EPPlus Excel 更改单元格颜色

    我正在尝试将给定单元格的颜色设置为另一个单元格的颜色 该单元格已在模板中着色 但worksheet Cells row col Style Fill BackgroundColor似乎没有get财产 是否可以做到这一点 或者我是否必须在互联
  • char指针或char变量的默认值是什么[重复]

    这个问题在这里已经有答案了 下面是我尝试打印 char 变量和指针的默认值 值的代码 但无法在控制台上看到它 它是否有默认值或只是无法读取 ASCII 范围 include
  • 方法参数内的变量赋值

    我刚刚发现 通过发现错误 你可以这样做 string s 3 int i int TryParse s hello out i returns false 使用赋值的返回值是否合法 Obviously i is but is this th
  • 如何在 C# 中播放在线资源中的 .mp3 文件?

    我的问题与此非常相似question https stackoverflow com questions 7556672 mp3 play from stream on c sharp 我有音乐网址 网址如http site com aud
  • 更改显示的 DPI 缩放大小使 Qt 应用程序的字体大小渲染得更大

    我使用 Qt 创建了一些 GUI 应用程序 我的 GUI 应用程序包含按钮和单选按钮等控件 当我运行应用程序时 按钮内的按钮和字体看起来正常 当我将显示器的 DPI 缩放大小从 100 更改为 150 或 200 时 无论分辨率如何 控件的
  • 如何将字符串“07:35”(HH:MM) 转换为 TimeSpan

    我想知道是否有办法将 24 小时时间格式的字符串转换为 TimeSpan 现在我有一种 旧时尚风格 string stringTime 07 35 string values stringTime Split TimeSpan ts new
  • 如何连接字符串和常量字符?

    我需要将 hello world 放入c中 我怎样才能做到这一点 string a hello const char b world const char C string a hello const char b world a b co
  • 为什么 strtok 会导致分段错误?

    为什么下面的代码给出了Seg 最后一行有问题吗 char m ReadName printf nRead String s n m Writes OK char token token strtok m 如前所述 读取字符串打印没有问题 但

随机推荐

  • 向量迭代器不可递增

    编辑 我删除了 else 部分 迭代器被迭代了两次 运行时出错 文件 c program files x86 microsoft Visual Studio 10 0 vc include vector 线路 99 表达式 向量迭代器不可递
  • 如何使用Polymer1.0实现长按事件?

    长按事件似乎不属于聚合物规范的一部分 你会如何实施 我考虑过使用一种行为并使用down and up与一些人发生的事件debounce管理此类新事件的技巧 但这意味着我必须创建一个自定义元素才能使用此行为 并且不能直接在我想要的任何元素上使
  • 如何限制用户访问HTTP服务器上的文件?

    我正在编写一个网络应用程序 允许用户在应用程序上上传文件 用户单击 上传 按钮后 文件将上传到 HTTP 服务器上 用户可以通过从路径获取文件来接收文件 例如 http www demo com user abc download the
  • Rails 阻止在 before_create 回调中创建对象

    我想检查新记录的一些属性 如果某些条件成立 则阻止创建对象 before create check if exists def check if exists if condition logic for not creating the
  • 如何在 Swift 3 中检查当前线程?

    如何检查 Swift 3 中当前线程是哪一个 在 Swift 的早期版本中 可以通过执行以下操作来检查当前线程是否为主线程 NSThread isMainThread 看起来好像很简单Thread isMainThread在斯威夫特 3 中
  • Entity Framework Core 中的动态 DbSet

    string tableName TblStudents Dictionary
  • Docker镜像缓存失效何时发生?

    也许我的Google Foo不够强大 但我找不到关于缓存中的Docker镜像何时失效的明确列表 具体来说 我至少对以下场景感兴趣 无效的原因是时间变化 https stackoverflow com a 26612694 371137 vs
  • 为什么 Object.GetType() 不是虚拟的?

    代码示例取自 MSDN public class Test public static void Main MyBaseClass myBase new MyBaseClass MyDerivedClass myDerived new My
  • 我们通常应该对浮点数使用浮点文字而不是更简单的双精度文字吗?

    In C or maybe only our compilers VC8 and VC10 3 14 is a double literal and 3 14f is a float literal 现在我有一个同事说 我们应该使用浮点文字
  • MySQL错误111无法连接到服务器

    我有一个 connection php 文件 该文件应该连接到远程数据库 这是代码 现在我相信我的所有变量都是正确的 因为我可以通过以下方式连接到数据库Toad http www quest com toad E2 80 8E 我通过 lo
  • Android 将设备坐标系转换为“用户”坐标系

    我的问题类似于改变android中的传感器坐标系 https stackoverflow com questions 10762133 changing sensor coordinate system in android 我希望能够比较
  • 如何将 Flutter 应用程序与 Python 代码集成 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想制作一个使用 Python 模块的 Flutter 应用程序 集成 Python 代码的选项有哪些 如何在 2 个运行时之间编组数
  • 多处理模块中的 ThreadPool 与 Pool 有什么区别?

    有什么区别ThreadPool and Pool in multiprocessing模块 当我尝试我的代码时 这是我看到的主要区别 from multiprocessing import Pool import os time print
  • Python 版本性能

    在哪里可以找到 python 版本之间的比较速度基准 例如2 6 2 7 3 0 3 1和3 2版本之间的性能 Python 软件基金会在以下位置设有一个速度比较网站 https speed python org comparison ht
  • 如何使用 while 循环读取文本文件

    我需要能够从文件中读取 3 个独立的文本块 并使用 while 循环将它们显示出来 包括计算结果 目前我只能显示一段文本 我不知道如何在这里完全像文本文件中一样格式化它 所以请原谅图像 文本文件 https i stack imgur co
  • 获取图像的压缩比

    我使用 LibJPEG 来读取 JPEG 压缩图像 有没有办法获取未更改图像的当前压缩率 您指的是编码质量 通常是 0 100 的数字吗 它不会被存储 它被用作图像编码的指南 以了解波的准确度 然后将其丢弃 任何 JFIF 标头结构中都没有
  • WPF TextBlock 中的文本垂直对齐

    如何为 TextBlock 内的文本指定垂直居中对齐 我找到了 TextAlignment 属性 但它用于水平文本对齐 如何实现垂直文本对齐 Textblock 本身无法进行垂直对齐 我发现最好的方法是将文本块放在边框内 这样边框就会为您进
  • 未找到类型的构造函数

    异常消息 Constructor on type StateLog not found 我有以下代码 该代码仅适用于一个类 List
  • 操作错误,没有这样的列。姜戈

    我正在浏览位于以下位置的 Django REST 框架教程 http www django rest framework org http www django rest framework org 我快完成了 刚刚添加了身份验证 现在我得
  • Monte Carlo pi 近似的并行化

    我正在编写一个 C 脚本来与 OpenMp 并行化 pi 近似 我认为我的代码运行良好 输出令人信服 我现在用 4 个线程运行它 我不确定的是 这段代码是否容易受到竞争条件的影响 如果是 我如何协调这段代码中的线程操作 代码如下 inclu