通过循环展开来加速do-while循环

时间:2019-05-25 09:26:44

标签: c++ do-while loop-unrolling

我正在尝试加速可能被多次调用(可能超过一百万次)的函数中的代码。该代码与将两个变量设置为随机数并找到平方距离有关。我的第一个想法是循环展开,但是由于规定了while条件,我对应该如何执行它有些困惑。

为了加快程序速度,我用一个自定义函数替换了rand()函数内置的c ++,但是我对如何使程序更快感到困惑。

do {
    x = customRand();
    y = customRand();
    distance = x * x + y * y; // euclidean square distance
} while (distance >= 1.0);

2 个答案:

答案 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,但是我将首先关注您有关循环加速的问题。我仍然会做一些数学运算。

因此,如果continuex中的任何一个大于或等于y,则基本提速可能会使用早期的1.0。当x*x + y*y < 1.0x中的一个大于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库也可能导致某些提速。