C++ 使用 Parallel For 多线程 计算 圆周率 – Monte Carlo


计算圆周率是个老掉牙的课题. 最为简单的 直接易懂的无非就是通过 Monte Carlo 来随机撒点 然后 计算 在圆内的点和总共的点数的比例再乘于4就能得到一个估计的值. 当然随机数的产生一定要质量好 虽然计算机没有真正的随机算法 但是一些 伪随机 算法 比如 xorshift 就很不错.

Monte-Carlo01 C++ 使用 Parallel For 多线程 计算 圆周率 - Monte Carlo 学习笔记 数据结构与算法 程序设计 计算机

Monte-Carlo01

单机版本的计算 简单明了.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
int monte_carlo_count_pi(int n)
{
    int c = 0;
    for (int i = 0; i < n; i ++)
    {
        double x = (double)rand() / (RAND_MAX);
        double y = (double)rand() / (RAND_MAX);
        if (x * x + y * y <= 1.0)
        {
            c++;
        }
    }
    return c;
}
int monte_carlo_count_pi(int n)
{
	int c = 0;
	for (int i = 0; i < n; i ++)
	{
		double x = (double)rand() / (RAND_MAX);
		double y = (double)rand() / (RAND_MAX);
		if (x * x + y * y <= 1.0)
		{
			c++;
		}
	}
	return c;
}

然后借助于 Parallel.For 我们就可以很简单的把这个算法并行化了.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int main()
{
    srand(time(NULL));// 种子
    const int N1 = 1000;
    const int N2 = 100000;
    int n = 0;
    int c = 0;
    Concurrency::critical_section cs;
    // N1 值小于 N2 会有比较好的多线程效率
    Concurrency::parallel_for(0, N1, [&](int i)
    {
        int t = monte_carlo_count_pi(N2);
        cs.lock(); // race condition
        n += N2;   // total sampling points
        c += t;    // points fall in the circle
        cs.unlock();
    });
    cout < < "圆周率 约等于 " << setprecision(9) << (double)c / n * 4.0 << endl;
    return 0;
}
int main()
{
	srand(time(NULL));// 种子
	const int N1 = 1000;
	const int N2 = 100000;
	int n = 0;
	int c = 0;
	Concurrency::critical_section cs;
	// N1 值小于 N2 会有比较好的多线程效率
	Concurrency::parallel_for(0, N1, [&](int i)
	{
		int t = monte_carlo_count_pi(N2);
		cs.lock(); // race condition
		n += N2;   // total sampling points
		c += t;    // points fall in the circle
		cs.unlock();
	});
	cout < < "圆周率 约等于 " << setprecision(9) << (double)c / n * 4.0 << endl;
	return 0;
}

完整代码在 github: https://github.com/DoctorLai/coding_exercise/blob/master/parallel_monte_carlo_pi.cpp

实现的关键就在于 把所要撒的点 分成每一份 N2 个点数 然后我们需要有一个critical_section 来保证同时只有一个线程 来修改我们统计的两个变量.

如果你运行这个程序 你就会发现CPU利用率 90% 左右 如果只是单线程的话 计算 N1*N2=100000K 则需要很久. 这样简单的使用Parallel.For 则可以大大的利用多核CPU. 比如这个HPZ800.

能得到多少倍提升呢? 我们还需要考虑 阿姆达尔定律

英文: C++ 使用 Parallel For 多线程 计算 圆周率 - Monte Carlo

GD Star Rating
loading...
本文一共 313 个汉字, 你数一下对不对.
C++ 使用 Parallel For 多线程 计算 圆周率 – Monte Carlo. (AMP 移动加速版本)
上一篇: 在PHP里执行SQL文件
下一篇: CLOUDFLARE 又有免费的保护可用 - DNSSEC

扫描二维码,分享本文到微信朋友圈
aba2998b05a30bde23e52ceff6c5d0fe C++ 使用 Parallel For 多线程 计算 圆周率 - Monte Carlo 学习笔记 数据结构与算法 程序设计 计算机

评论