Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/153.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 加速montecarlo-Pi_C++_Multithreading - Fatal编程技术网

C++ 加速montecarlo-Pi

C++ 加速montecarlo-Pi,c++,multithreading,C++,Multithreading,我已经编写了一个C++程序,通过“将随机点抛入四分之一个圆中,然后计数等”来计算pi。现在我的程序在我看来有点慢,我已经考虑了一些改进来加速它(下面是源代码)。 我的第一个想法是使用OpenMP使其成为多线程,即将(i)和(II)之间的代码拆分为多个线程,这样我就可以在不必等待更长时间的情况下(在八核系统上)拥有近十倍的轮数。 我的另一个想法是使用全局变量和指针,所以我只需要复制指针,而不是整数的元组。退税是(idk)? 那么,我还能做些什么来加速程序呢?我主要使用windows,但我也可以使用

我已经编写了一个C++程序,通过“将随机点抛入四分之一个圆中,然后计数等”来计算pi。现在我的程序在我看来有点慢,我已经考虑了一些改进来加速它(下面是源代码)。
我的第一个想法是使用OpenMP使其成为多线程,即将(i)和(II)之间的代码拆分为多个线程,这样我就可以在不必等待更长时间的情况下(在八核系统上)拥有近十倍的轮数。
我的另一个想法是使用全局变量和指针,所以我只需要复制指针,而不是整数的元组。退税是(idk)?
那么,我还能做些什么来加速程序呢?我主要使用windows,但我也可以使用Unix/Linux。
多谢各位

代码部分:

    #include <cstdlib>
    #include <iostream>
    #include <tuple>
    #include <math.h>
    #include <time.h>
    #include <omp.h>
    #include <sys/time.h>

    #define RAND_MAX 32000
    #define LOOPS 1000000

    inline std::tuple<int, int> Throw_points(void)
    {

        int i = 0, j = 0;
        i = rand() % 1000;
        j = rand() % 1000;
        return std::make_tuple(i, j);
    }

    inline bool is_in_circle(std::tuple<int, int> point)
    {
        if ((pow(std::get<0>(point), 2) + pow(std::get<1>(point), 2)) <= pow(1000, 2))
            return true;
        else
            return false;
    }

    inline double pi(void)
    {
        srand(time(NULL));
        long long int in_circle = 0;
        long long int out_circle = 0;
        for (int i = 0; i < LOOPS; i++)
        {
            if (is_in_circle(Throw_points()))
                in_circle++;
            out_circle++;
        }
        return double(in_circle) / double(out_circle) * 4;
    }
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义RAND_MAX 32000
#定义循环1000000
内联标准::元组抛出点(空)
{
int i=0,j=0;
i=rand()%1000;
j=rand()%1000;
返回std::make_tuple(i,j);
}
内联布尔是圆中的(标准::元组点)
{

如果((pow(std::get(point),2)+pow(std::get(point),2))一些随机观察:

  • 通过乘法求平方可能比调用
    pow
    更快。特别是,您不希望每次都计算常量
    pow(1000,2)
  • int
    计数器可能比
    long-long
    快-您已经限制了可由
    int
    表示的循环数
  • 通过引用传递可能会更快。或者可能会更慢,因为类型很小。或者可能不会有什么区别,因为函数应该是内联的
  • if(X)返回true;else返回false;
    而不是
    返回X;
    很奇怪,但可能不会影响性能
  • rand()
    对于蒙特卡罗模拟来说,随机性可能不够;它的目的是速度快,但质量不高。不幸的是,好的伪随机生成器非常慢。C++11库有几个选项

如果你真的让它多线程,那么确保每个线程都有一个不同的随机种子;否则,它们只会复制彼此的工作。你将无法使用
rand()
,因为它不是线程安全的。

我只是对这一点做了一些研究。实际上,原始帖子评论中的所有建议(包括我自己的建议)几乎没有任何区别

然而,去掉元组

inline void Throw_points(int&i, int&j)
{
    i = rand() % 1000;
    j = rand() % 1000;
}

inline bool is_in_circle(int i, int j)
{
    return i*i + j*j < 1000000;        
}
inlinevoid抛出点(int&i,int&j)
{
i=rand()%1000;
j=rand()%1000;
}
内联布尔是圆中的(inti,intj)
{
返回i*i+j*j<1000000;
}
把程序加快了五倍


顺便说一句,我在这里使用了boost::progress\u timer解决方案:

性能观察。使用分析工具;这会告诉您代码在哪里花费时间。通常这总是令人惊讶


如果你在gcc土地使用gprof中,这是一种计算
π
的慢方法;IIRC我的数学课程,精度是
1/sqrt(循环)
(但我可能是错的)。所以读一些数学书来计算
π
更快!阅读wikipage上的内容不会有多大帮助,但你应该缓存
pow(1000,2)的结果
,或者最后将其替换为
1000*1000
,这比
pow
快得多,编译器将为您缓存结果。@basilestrynkevitch:我必须使用此方法,否则我已经切换了…然后使用
#pragma
-sAlso,将a&添加到is#u in_circle的函数参数中。您继续复制y我们的元组现在可以通过引用传递了。@ViníciusGobboA.deOliveira关于省略pow(…)的评论也适用于其他平方运算:我预计
std::get(point)*std::get(point)
pow(std::get(point),2)快得多
。使用兰德是一个先决条件,pi非常好(3.145等)。是的,但我认为迈克的观点是兰德()这不是一个高质量的PRNG。@PeteBecker:我知道,但我们只需要计算圆周率,直到komma之后的第二个数字…@arc_Luse:如果它对这个任务来说足够好,那就好了。但是值得记住的是,当你需要统计上良好的随机性时,它不是很好。
rand()
。对于这个特定的任务来说,它是足够随机的,但对于实际问题,我根本不相信它。除了使用
rand
,一个可能更严重的问题是使用%运算符来限制范围:某些值会比其他值(稍微)更频繁地出现。