我有一个2d数组自定义Vector类,大约250个,250个维度。 Vector类只存储向量的x和y float组件。我的项目要求我对数组执行平滑功能,以便通过获取数组中每个向量的i索引的局部平均值来创建新数组。我的问题是我当前的解决方案计算速度不够快,并且想知道是否有更好的计算方法。
我当前解决方案的伪代码如下所示。我在C#中实现这一点,任何帮助将不胜感激。我的实际解决方案使用1d数组来加速,但我没有在这里包含它。
function smoothVectorArray(Vector[,] myVectorArray, int averagingDistance) {
newVectorArray = new Vector[250,250];
for (x = 0; x < 250; x++)
{
for (y = 0; y < 250; y++)
{
vectorCount = 0;
vectorXTotal = 0;
vectorYTotal = 0;
for (i = -averageDistance; i < averagingDistance+ 1; i++)
{
for (j = -averageDistance; j < averagingDistance+ 1; j++)
{
tempX = x + i;
tempY = y + j;
if (inArrayBounds(tempX, tempY)) {
vectorCount++;
vectorXTotal += myVectorArray[tempX, tempY].x;
vectorYTotal += myVectorArray[tempX, tempY].y;
}
}
}
newVectorArray[x, y] = new Vector(vectorXTotal / vectorCount, vectorYTotal / vectorCount);
}
}
return newVectorArray;
}
答案 0 :(得分:2)
你的内心循环所做的是计算矩形的总和:
blue
您可以在O(n ^ 2)中有效地预先计算它们。让我们介绍一个数组S [N] [N](在你的情况下N = 250)。
为了简单起见,我假设只有一个坐标。您可以通过构建2个数组轻松地将其调整为对(x,y)。
S [i,j] - 将是子矩形(0,0)的总和 - (i,j)
我们可以有效地构建这个数组:
for (i = -averageDistance; i < averagingDistance+ 1; i++)
for (j = -averageDistance; j < averagingDistance+ 1; j++)
一旦我们计算了这个部分和数组,我们就可以得到O(1)中的子矩形和。让我们说我们想得到矩形(a,b) - (c,d)
的和为了得到它,我们从大矩形(0,0) - (c,d)开始,我们需要从中减去(0,0) - (a-1,d-1)和(0,0) - (c-1,b-1)并添加后加矩形(0,0) - (a-1,b-1),因为它被减去了两次。
这样你就可以摆脱你的内心循环。
答案 1 :(得分:0)
您肯定希望利用CPU缓存来解决这个问题,听起来您的一维阵列解决方案就是这么想的。尝试安排算法一次处理连续内存块,而不是在数组周围跳跃。到目前为止,您应该使用Vector结构而不是类,或者使用两个浮点数组,一个用于x值,另一个用于y值。通过使用类,您的数组存储指向堆中各个点的指针。因此,即使按顺序迭代数组,当您跳转到Vector对象的位置时,仍然始终缺少缓存。每次缓存未命中都会浪费大约200个cpu周期。这将是首先解决的主要问题。
之后,您可以考虑进行一些微观优化
在inArrayBounds方法中使用内联提示:[MethodImpl(MethodImplOptions.AggressiveInlining)]
使用不安全模式并使用指针算法迭代以避免数组边界检查开销
最后两个想法可能会或可能不会产生任何重大影响,您应该进行测试。