预编译多维数组访问

时间:2019-06-01 07:55:05

标签: c++ precompile

想象这样计算三维数组:

for (int i = 0; i < I; i++)
{
    for (int j = 0; j < J; j++)
    {
        for (int k = 0; k < K; k++)
        {
            array[k + j * K + i * K * J] = someValue(i, j, k);
        }
    }
}

但是k + j * K + i * K * J部分有点贵。是否可以告诉编译器将循环转换为类似的内容?

array[0] = someValue(0, 0, 0);
array[1] = someValue(0, 0, 1);
array[2] = someValue(0, 0, 2);
array[3] = someValue(0, 1, 0);
...

这当然会使二进制文件更大,但如果此代码执行很多,则也可以提高性能。是否有可能做到这一点?还是我必须自己生成代码并将其粘贴到源文件中?

1 个答案:

答案 0 :(得分:2)

我相信在您的特殊情况下,我们可以将循环重写为:

auto* scan = array;
for (int i = 0; i < I; i++)
{
    for (int j = 0; j < J; j++)
    {
        for (int k = 0; k < K; k++)
        {
            *scan++ = someValue(i, j, k);
        }
    }
}

这是微优化,您通常不必担心。这就是为什么。

原因1:整数乘法非常便宜。计算k + j * K + i * K * J比从计算机的RAM中检索值便宜,并且与从CPU最快的缓存中检索值一样便宜(如果不便宜的话)。

原因2:编译器非常聪明。他们可以识别出哪些值发生了变化,哪些值保持不变,并优化了循环外的常用子表达式(这样它们就不会多次执行相同的计算)。

原因3::编译器能够利用矢量化指令。根据{{​​1}}的功能,可能可以利用此优势在同一内核上并行计算多个值。对于两种索引到someValue的方法都是如此。

C ++代码并非绝对必要。编译器可以而且确实可以进行重大而复杂的优化以提高代码的效率,并且示例中的代码很容易进行优化。