【问题标题】:Iterate through an array randomly but fast随机但快速地遍历数组
【发布时间】:2021-08-28 02:35:59
【问题描述】:

我有一个需要随机迭代的二维数组。这是一个小模拟中更新循环的一部分,所以它每秒运行大约 200 次。目前,我通过创建一个适当大小的数组,用一个范围填充它,并将其改组以用于为我的其他数组下标来实现这一点。

std::array<int, 250> nums;
std::iota(nums.begin(), nums.end(), 0);

timer += fElapsedTime;
if (timer >= 0.005f)
{
    std::shuffle(nums.begin(), nums.end(), engine);

    for (int xi : nums)
    {
        std::shuffle(nums.begin(), nums.end(), engine);

        for (int yi : nums)
        {
            // use xi and yi as array subscript and do stuff
        }
    }

    timer = 0.0f;
}

这个解决方案的问题是真的很。仅删除 std::shuffle 就可以将 fps 提高近 2.5 倍,因此与仅这些 shuffle 相比,整个程序逻辑几乎是微不足道的。

是否有某种类型的代码可以让我生成固定范围 (0 - 249) 的非重复随机生成的整数,我可以直接使用或写入数组然后迭代?

【问题讨论】:

  • 所以它每秒运行大约 200 次 -- 您是在计时发布构建还是调试、未优化构建?每秒 200 次这样简单的事情对我来说听起来很奇怪。
  • 您正在改组您正在迭代的范围。几乎没有这种情况是正确的。几乎可以肯定,您不会访问for (int xi : nums) 中的每个值,并且您会多次访问其中的一些值。看起来内部洗牌的目的是随机化 y 订单,但它也在洗牌 x 订单。在我看来,你应该有一个索引或迭代器数组,你可以为每个xi 洗牌。这不会解决您的速度问题,但会解决您尚未注意到的错误。
  • 使用分析器找出代码的哪一部分运行缓慢。也许engine 对您的应用程序来说太慢了。或许可以试试std::linear_congruential_engine 之类的std::minstd_rand,它应该非常快,但不像其他引擎那样随机。
  • @FrançoisAndrieux 我没有注意到这一点。我的模拟产生了几乎很好的结果,但有些地方不对劲。这绝对是谢谢你。
  • 您的阵列大小是否固定为 250x250?目标是随机访问数组的所有元素而不访问位置两次吗?

标签: c++ arrays performance random


【解决方案1】:

您应该打乱整个矩阵,而不是一次遍历一行/列。这应该工作得很快。它是 125k,应该是合理的缓存友好的。

constexpr int N = 250;
std::array<uint16_t, N* N> nums;
std::iota(nums.begin(), nums.end(), 0);
std::shuffle(nums.begin(), nums.end(), engine);

for (auto x : nums)
{
    auto xi = x / N;
    auto yi = x % N;
    // Do Stuff indexed on x and y
}

【讨论】:

  • 我已经实现并测试了这一点,以在保持预期效果的同时提供合理的性能改进,所以除非出现更好的结果,否则我会接受这个作为答案。
猜你喜欢
  • 1970-01-01
  • 2017-09-08
  • 2015-05-19
  • 2013-04-07
  • 2014-09-16
  • 2015-08-16
  • 1970-01-01
  • 2011-11-16
相关资源
最近更新 更多