迭代任意范围的n维数组的最快方法?

时间:2014-11-10 12:38:17

标签: c++ algorithm optimization multidimensional-array n-dimensional

在C ++中,我希望迭代一个n维数组,其任意范围分别为min [n]到max [n],并在整个ord [n]中保持纵坐标。

IE中。一般解决方案:

for (int x = 0; x < 10; x++)
for (int y = 3; y < 20; y++)
for (int z = -2; z < 5; z++)
...
   doSomething(x, y, z ...)

形式:

int min[n] {0,  3, -2 ...}
int max[n] {10, 20, 5 ...}
int ord[n] {0,  0,  0 ...};

int maxIterations = (max[0] - min[0]) * (max[1] - min[1]) * ....
for (int iteration = 0; iteration < maxIterations; iteration++)
   doSomething(ord)
   iterate(n, ord, min, max)

我能想到的最快的iterate()算法是:

inline void iterate(int dimensions, int* ordinates, int* minimums, int* maximums)
{
    // iterate over dimensions in reverse...
    for (int dimension = dimensions - 1; dimension >= 0; dimension--)
    {

        if (ordinates[dimension] < maximums[dimension])
        {
            // If this dimension can handle another increment... then done.
            ordinates[dimension]++;
            break;
        }

        // Otherwise, reset this dimension and bubble up to the next dimension to take a look
        ordinates[dimension] = minimums[dimension];
    }
}

根据需要增加并重置每个纵坐标,避免使用callstack或任何数学。

是否有更快的算法?

1 个答案:

答案 0 :(得分:3)

除非你开始做类似于Gray codes的事情,这会改变你的遍历顺序(并且可能非常复杂),否则你几乎可以获得它会得到的好处。 。实际上,iterate的摊还时间已经O(1),假设每个维度的最小值不等于其最大值。

最糟糕的情况是所有d维度都有maximum = minimum + 1。也就是说,任何特定维度的每个其他增量都将溢出到下一个维度中。但请注意,特定维度x(从1d)所需的数字更改总数为2^(d + 1 - x) - 1。这显然小于2^(d + 1 - x)。对所有维度(1d)求和这是一个简单的几何和,得到2^(d + 1) - 2,显然小于2^(d + 1)。请注意,迭代次数为2^d,因此每次迭代的平均时间是常量:2^(d + 1) / 2^d = 2

如果你真的需要挤压速度,可能最好的是低水平的调整:

  • 已知尺寸的数量是否小于(例如,20或更小)常数?然后,您可以通过展开循环来消除for循环。如果可以推断出dimensions是常量,或者您可能必须创建具有常量维度的iterate的多个版本或手动展开循环,那么您的编译器可能已足够聪明地执行此操作。 (如果你想给它一个很好的API,你可以使用模板。)
  • 您实际上可以在 big 外部循环(其中包含doSomething调用的循环)中删除maxIterations / iteration检查,并允许迭代函数更改布尔值当它用完尺寸时,它会增加。这会将for循环缩减为while (keepGoing) { ... }
  • 传递每个维度的最小值和最大值的结构数组可能会稍微快一些,但我希望缓存能够几乎完全降低这些好处。

当然,在任何此类变更之前和之后的基准测试 - 每个架构和工具链的反应都不同。