我正在尝试加速可能被多次调用(可能超过一百万次)的函数中的代码。该代码与将两个变量设置为随机数并找到平方距离有关。我的第一个想法是循环展开,但是由于规定了while
条件,我对应该如何执行它有些困惑。
为了加快程序速度,我用一个自定义函数替换了rand()函数内置的c ++,但是我对如何使程序更快感到困惑。
do {
x = customRand();
y = customRand();
distance = x * x + y * y; // euclidean square distance
} while (distance >= 1.0);
答案 0 :(得分:1)
您不应该期望通过循环展开来使程序更快,因为对于随机数生成器输出,如果选择了适当的范围([-1, 1]
),则循环的主体将在3/4中执行一次的情况。
您可能想帮助编译器的工作是将您的while
条件标记为“不太可能”。例如,在GCC中,它将是:
#define unlikely(x) __builtin_expect((x),0)
do {
x = customRand();
y = customRand();
distance = x * x + y * y; // euclidean square distance
} while (unlikely(distance >= 1.0));
尽管如此,即使这样也不太可能以可衡量的方式加快代码的速度。
如果您要保证的时间而不是速度,那么对于一个圆内的均匀随机分布,customRand()
均匀分布在[-1, 1]
r = std::sqrt(std::abs(customRand()));
t = M_PI * customRand();
x = r * std::cos(t);
y = r * std::sin(t);
可以解决问题。
答案 1 :(得分:0)
它闻起来像是基于数学的XY problem,但是我将首先关注您有关循环加速的问题。我仍然会做一些数学运算。
因此,如果continue
或x
中的任何一个大于或等于y
,则基本提速可能会使用早期的1.0
。当x*x + y*y < 1.0
或x
中的一个大于y
时,1
不可能。
do {
float x = customRand();
if (x >= 1.0) {
continue;
}
float y = customRand();
if (y >= 1.0) {
continue;
}
distance = x * x + y * y; // euclidean square distance
} while (distance >= 1.0);
不幸的是,它很可能搞砸了现代CPU分支预测机制,但仍可能无法大幅提高速度。和往常一样,基准是必需的。
此外,由于最快的代码是不会运行的代码,因此让我们讨论潜在的XY问题。您似乎生成了以半径为1.0
的圆为边界的点。在笛卡尔系统中,这是一项艰巨的任务,但在极坐标系统中,这确实很容易,其中圆盘上的每个点都用半径和角度描述,并且可以轻松转换为笛卡尔坐标。我不知道您期望在磁盘区域上分配什么,但是请在此处查看此问题的答案:Generate a random point within a circle (uniformly)
PS。关于<random>
有一些有效的评论,而std
库也可能导致某些提速。