我目前正在做一些涉及邻接矩阵的图形计算,并且我正在优化它的每一点。
我认为可以优化的指令之一是标题中的指令,它的原始形式:
if ((adjMatrix[i][k] > 0) && (adjMatrix[k][j] > 0) && (adjMatrix[i][k] + adjMatrix[k][j] == w))
但为方便起见,我将坚持标题中提供的表格:
if (a > 0 && b > 0 && a + b == c)
我不喜欢的是 > 0 部分(作为邻接矩阵,在它的初始形式中它只包含 0 和 1,但随着程序的进行,零被替换为从 2 开始的数字,直到不再有零。
我已经做了一个测试并删除了 a 和 b 的 > 0 部分,并且有显着的改进。超过 60088 次迭代减少了 792ms,从 3672ms 减少到 2880ms,这是原始时间的 78%,这对我来说非常好。
所以我的问题是:你能想出某种方法来优化这样的语句并在 C# 中获得相同的结果吗?也许一些按位运算或类似的东西,我对它们不太熟悉。
回答你脑海中闪过的每一个想法,即使它不合适。我会自己做速度测试,然后告诉你结果。
编辑:这是一个编译器,我将自己在我的计算机上运行它。我刚才描述的不是我抱怨的问题/瓶颈。当前形式的程序可以很好地满足我的需求,但我只是想推动它前进并使其尽可能基本和优化。希望这能澄清一点。
编辑我相信提供完整的代码是一件有用的事情,所以在这里,但请记住我在下面用粗体字说的话。我想严格专注于 if 语句。该程序本质上采用邻接矩阵并存储所有存在的路线组合。然后根据一些系数进行排序和修剪,但是这个我没有包括在内。
int w, i, j, li, k;
int[][] adjMatrix = Data.AdjacencyMatrix;
List<List<List<int[]>>> output = new List<List<List<int[]>>>(c);
for (w = 2; w <= 5; w++)
{
int[] plan;
for (i = 0; i < c; i++)
{
for (j = 0; j < c; j++)
{
if (j == i) continue;
if (adjMatrix[i][j] == 0)
{
for (k = 0; k < c; k++) // 11.7%
{
if (
adjMatrix[i][k] > 0 &&
adjMatrix[k][j] > 0 &&
adjMatrix[i][k] + adjMatrix[k][j] == w) // 26.4%
{
adjMatrix[i][j] = w;
foreach (int[] first in output[i][k])
foreach (int[] second in output[k][j]) // 33.9%
{
plan = new int[w - 1];
li = 0;
foreach (int l in first) plan[li++] = l;
plan[li++] = k;
foreach (int l in second) plan[li++] = l;
output[i][j].Add(plan);
}
}
}
// Here the sorting and trimming occurs, but for the sake of
// discussion, this is only a simple IEnumerable<T>.Take()
if (adjMatrix[i][j] == w)
output[i][j] = output[i][j].Take(10).ToList();
}
}
}
}
添加了带有探查器的注释以优化构建。
顺便说一句,正是通过这段代码获得了计时结果(没有排序和修剪,这大大增加了执行时间)。我的测量中没有其他零件。在这段代码之前有一个 Stopwatch.StartNew() ,之后有一个 Console.WriteLine(EllapsedMilliseconds) 。
如果你想知道大小,邻接矩阵有 406 行/列。所以基本上只有 for 指令组合起来执行很多次迭代,所以我没有很多优化选项。速度目前不是问题,但我想确保我准备好了。
为了排除“优化其他部分”的问题,这个主题也有讨论的余地,但对于这个具体问题,我只想找到一个抽象问题/概念的解决方案。它可以帮助我和其他人了解 C# 编译器如何工作以及如何处理 if 语句和比较,这就是我的目标。