如何通过常数优化数组乘法?

时间:2015-03-12 13:51:26

标签: c++ arrays optimization

给出以下代码,其中a,b,c,d等是常量:

Data[] dataArray;
Intermediate[] interArray;
Output[] outputArray;

for (int i = 0; i < length; i++)
{
  interArray[i] = (c * dataArray[i]) + (a * dataArray[i+1]);
  interArray[i] -= (b * interArray[i - 1]) + (d * interArray[i - 2]);
  outputArray[i] = interArray[i];
}

for (int i = ln-1; i > 0; i--)
{
  interArray[i - 1] = (e * dataArray[i]) + (f * dataArray[i-1]);
  interArray[i - 1] -= (g * interArray[i]) + (h * interArray[i+1]);
  outputArray[i] += interArray[i]; 
} 

如何优化此功能?

我只想一次走数组。不幸的是,我依赖于第二个循环要求interArray被第一个循环填充的事实。

我想这样做的原因是因为这个过程占我总运行时间的20%,而我正在尝试优化它。阵列可能非常大,类型通常是大型POD。我假设我正在进入缓存垃圾领域,这就是为什么我要减少遍布数组的次数。没有*运算符,它只是标准乘法。

注意:我知道由于超出范围,数组的上下边界在这里崩溃并烧毁。我会手动处理这些。

任何建议将不胜感激!我可能不能更快地做到这一点,但我想至少尝试一下!

1 个答案:

答案 0 :(得分:2)

我不确定这会给你节省大量时间,但我认为你可以通过扩展条款一次性完成计算。与8次乘法相比,这可以将其降低到6次乘法和累加。另外,您不需要中间阵列。它看起来像这样(请仔细检查扩展)

Data[] dataArray;
Output[] outputArray;
auto DMinus2 = -c * d;
auto DMinus1 = -a - b*c;
auto D = c - a * b + f;
...

for (int i = 0; i < length; i++)
{
    outputArray[i] = DMinus2 * dataArray[i-2] + 
        DMinus1[i-1] * dataArray[i-1] +
        D * dataArray[i] + ....
        DPlus3 + dataArray[i+3];
}

编辑:

首先,道歉,我的第一个答案并不完全正确。但是,我相信可以简化循环。

例如,在第一个循环中

interArray[i] = (c * dataArray[i]) + (a * dataArray[i+1]);
interArray[i] -= (b * interArray[i - 1]) + (d * interArray[i - 2]);
outputArray[i] = interArray[i];

可以简化为

interArray[i] = (c * dataArray[i]) + (a * dataArray[i+1]) -
    (b * interArray[i - 1]) + (d * interArray[i - 2]);
outputArray[i] = interArray[i];

我假设范围之外的值为0 考虑i = 0然后我们有

outputArray[0] = (c * dataArray[0]) + (a * dataArray[1]);

i = 1给出

outputArray[1] = (c * dataArray[1]) + (a * dataArray[2]) - 
    b * outputArray[0];

i = 2给出

outputArray[2] = (c * dataArray[2]) + (a * dataArray[3]) - 
    b * outputArray[1] - d * outputArray[0];

所以,我认为我们可以推广第一个循环去除中间数组

outputArray[i] = (c * dataArray[i]) + (a * dataArray[i+1]) - 
    b * outputArray[i-1] - d * outputArray[i-2];

对于第二个循环也应如此。再次回顾了我的数学,我不完全确定可以将两个循环结合起来。我会继续考虑这个,因为可能有办法做到这一点。希望删除中间存储应该有所帮助。