给出以下代码,其中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。我假设我正在进入缓存垃圾领域,这就是为什么我要减少遍布数组的次数。没有*运算符,它只是标准乘法。
注意:我知道由于超出范围,数组的上下边界在这里崩溃并烧毁。我会手动处理这些。
任何建议将不胜感激!我可能不能更快地做到这一点,但我想至少尝试一下!
答案 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];
对于第二个循环也应如此。再次回顾了我的数学,我不完全确定可以将两个循环结合起来。我会继续考虑这个,因为可能有办法做到这一点。希望删除中间存储应该有所帮助。