需要有关提高c#代码性能的建议

时间:2012-05-21 15:55:33

标签: c# .net arrays performance

我有功能,这是非常频繁的。此函数内部有两个嵌套的 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;
                    }
                }
            }

执行这些循环需要大约0.1秒,这太慢了。我用1维替换了二维阵列,这显着改善了性能。代码是否还有其他性能改进?如果我将它迁移到c ++会更快吗?我应该使用任何其他语言进行数组操作吗?你会建议什么?
提前谢谢,
萨姆

7 个答案:

答案 0 :(得分:2)

height - 1j + 1width - 1j * width等内容重构为变量,因此它们只计算一次。它会有所帮助。实际上,您可以添加到此列表中:

(j == (width - 1)) ? 0 : (j + 1)

答案 1 :(得分:1)

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

答案 2 :(得分:1)

  
    

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

  

如果引用C ++ native,它应该 为什么
垃圾收集器不在那里 2.内存调整不存在 3. CLR不存在

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

如果您需要显着的加速,也许您应该考虑使用多个线程,至少对于外部循环。另外,请确保您没有使用overflow checks

答案 5 :(得分:0)

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

但是,您应首先在此处建议其他优化。

答案 6 :(得分:0)

您可以通过拥有3个内循环副本来完全删除j == 0j == (width - 1)测试。如果从循环中剥离第一次和最后一次迭代,则可以使用k执行相同的操作。当然,如果你同时做两件事你都会有9份内部代码,这不是很好,我不会特别推荐 - 根据k删除条件应该会产生更大的影响,并且/因为你可以根据j将条件移动到内循环之外。