1

我有funcion,它被非常频繁地调用。该函数内部有两个嵌套的 for循环。每个 for 循环都从 0 迭代到 900。代码如下所示:

 for (int j = 0; j < width; j++)
            {
                for (int k = 0; k < height; k++)
                {
                    switch (Dim2[j * width + k])
                    {
                        case 0:
                            cwA = Dim0[j * width + ((k == (height - 1)) ? 0 : (k + 1))];
                            ccwA = Dim0[((j == (width - 1)) ? 0 : (j + 1)) * width + k];
                            oppA = Dim0[((j == (width - 1)) ? 0 : (j + 1)) * width + ((k == (height - 1)) ? 0 : (k + 1))];
                            cwB = Dim3[j * width + ((k == (height - 1)) ? 0 : (k + 1))];
                            ccwB = Dim3[((j == (width - 1)) ? 0 : (j + 1)) * width + k];
                            oppB = Dim3[((j == (width - 1)) ? 0 : (j + 1)) * width + ((k == (height - 1)) ? 0 : (k + 1))];
                            break;

                        case 1:
                            cwA = Dim0[((j == (width - 1)) ? 0 : (j + 1)) * width + k];
                            ccwA = Dim0[j * width + ((k == 0) ? (height - 1) : (k - 1))];
                            oppA = Dim0[((j == (width - 1)) ? 0 : (j + 1)) * width + ((k == 0) ? (height - 1) : (k - 1))];
                            cwB = Dim3[((j == (width - 1)) ? 0 : (j + 1)) * width + k];
                            ccwB = Dim3[j * width + ((k == 0) ? (height - 1) : (k - 1))];
                            oppB = Dim3[((j == (width - 1)) ? 0 : (j + 1)) * width + ((k == 0) ? (height - 1) : (k - 1))];
                            break;

                        case 2:
                            cwA = Dim0[((j == 0) ? (width - 1) : (j - 1)) * width + k];
                            ccwA = Dim0[j * width + ((k == (height - 1)) ? 0 : (k + 1))];
                            oppA = Dim0[((j == 0) ? (width - 1) : (j - 1)) * width + ((k == (height - 1)) ? 0 : (k + 1))];
                            cwB = Dim3[((j == 0) ? (width - 1) : (j - 1)) * width + k];
                            ccwB = Dim3[j * width + ((k == (height - 1)) ? 0 : (k + 1))];
                            oppB = Dim3[((j == 0) ? (width - 1) : (j - 1)) * width + ((k == (height - 1)) ? 0 : (k + 1))];
                            break;

                        case 3:
                            cwA = Dim0[j * width + ((k == 0) ? (height - 1) : (k - 1))];
                            ccwA = Dim0[((j == 0) ? (width - 1) : (j - 1)) * width + k];
                            oppA = Dim0[((j == 0) ? (width - 1) : (j - 1)) * width + ((k == 0) ? (height - 1) : (k - 1))];
                            cwB = Dim3[j * width + ((k == 0) ? (height - 1) : (k - 1))];
                            ccwB = Dim3[((j == 0) ? (width - 1) : (j - 1)) * width + k];
                            oppB = Dim3[((j == 0) ? (width - 1) : (j - 1)) * width + ((k == 0) ? (height - 1) : (k - 1))];
                            break;
                    }
                    woll = (((oppB + ccwB) + cwB) + Dim3[j * width + k]) > 0;
                    collision = ((Dim0[j * width + k] == oppA) && (cwA == ccwA)) && (Dim0[j * width + k] != cwA);
                    Dim6[j * width + k] = (short)(3 - Dim2[j * width + k]);
                    if (woll || collision)
                    {
                        Dim4[j * width + k] = Dim0[j * width + k];
                    }
                    else
                    {
                        Dim4[j * width + k] = _phase ? cwA : ccwA;
                    }
                }
            }

执行这些 for 循环大约需要 0.1 秒,这太慢了。我已经用一维数组替换了二维数组,这显着提高了性能。代码还有其他性能改进吗?如果我将它迁移到 C++ 会更快吗?我应该使用任何其他语言进行数组操作吗?你有什么建议?
在此先感谢,
山姆

4

7 回答 7

2

height - 1将诸如, j + 1, width - 1,之类的东西重构j * width为变量,因此它们只计算一次。会有一点帮助。实际上,您可以添加到此列表中:

(j == (width - 1)) ? 0 : (j + 1)
于 2012-05-21T15:59:08.833 回答
1

你可以在这个项目中使用不安全的上下文吗?您应该能够通过使用指针而不是索引数组来显着提高性能,因为每次从数组中读取时,您将不再需要 .Net 的数组边界检查等。

于 2012-05-21T15:59:11.497 回答
1

如果我将它迁移到 C++ 会更快吗?

如果由 C++ native 引用,它应该。
为什么
1. 没有垃圾收集器
2. 没有内存重新对齐
3. 没有 CLR

然而,CLR 可以在托管代码中进行优化,等效的本机代码应该更快。这就是大多数 BCL CPU 密集型逻辑采用本机代码(由MethodImplOptions .InternalCall 装饰)的确切原因。

于 2012-05-21T15:59:47.143 回答
0

另一种解决方案,尤其是对于具有多核的现代计算机,可能是将外部 for 循环更改为对Parallel.For的调用。

不过,您应该首先进行此处建议的其他优化。

于 2012-05-21T16:18:51.370 回答
0

您可以通过拥有 3 个内部循环副本来完全删除j == 0和测试。如果您将第一次和最后一次迭代从循环中剥离,j == (width - 1)您可以对 执行相同的操作。k当然,如果你两者都做,你会有 9 个内部代码副本,这不是很好,我不会特别推荐 - 删除条件取决于k应该有更大的效果,和/因为你可以移动无论如何,条件取决于j内部循环之外。

于 2012-05-21T16:22:50.853 回答
0

如果您需要显着加速,也许您应该考虑使用多线程,至少对于外循环。另外,请确保您没有使用溢出检查

于 2012-05-21T16:07:03.737 回答
0

我不是 C# 专家,但我会尝试将所有“静态”计算和循环(内联条件和乘法)放在循环之外。

于 2012-05-21T15:59:49.717 回答