我编写了一个C ++程序,用于通过“将随机点扔到四分之一圆并计算它们等”来计算pi。现在我的程序在我看来有点慢,我已经考虑了一些改进以加快它(源代码如下)。
我的第一个想法是使用OpenMP使其成为多线程,即将(I)和(II)之间的代码分成几个线程,这样我就可以获得近十倍的轮次而无需等待更长时间(在octacore系统上)。
我的另一个想法是使用全局变量并使用指针,因此我只需复制指针而不是整数元组。缺点是(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;
}
通过pi()
答案 0 :(得分:1)
我只是玩了一下这个。实际上,对原帖(包括我自己)的评论中的所有建议几乎没有任何区别。
然而,摆脱元组
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;
}
将计划加速了5倍。
顺便说一下,我使用了boost :: progress_timer解决方案:How to get the time elapsed running a function in C++
答案 1 :(得分:1)
对perf的观察使用分析工具;这告诉你代码在哪里花费时间。一般来说这总是令人惊讶。
如果你在gcc土地使用gprof
答案 2 :(得分:0)
一些随机观察:
pow
更快。特别是,您不希望每次都计算常量pow(1000,2)
。int
计数器可能比long long
更快 - 您已经限制了int
可表示的循环数。if (X) return true; else return false;
而不是return X;
很奇怪,但可能不会影响效果。rand()
可能不是随机的蒙特卡罗模拟;它的目的是快速,但不是高质量。不幸的是,好的伪随机生成器非常慢。 C ++ 11库有几个选项。如果你确实使它成为多线程的,那么确保每个线程都有一个不同的随机种子;否则,他们只是重复彼此的工作。您将无法使用rand()
,因为它不是线程安全的。