关于C#:切换大量案例与单个if

Switch with tons of cases vs single if

假设我们需要遍历一个由uint8组成的128元素数组,比较相邻元素并将结果放到另一个数组中。下面的代码是解决这个问题最简单易读的方法。

1
2
3
for (i = 1; i < 128; i++)
  if (arr[i] < arr[i-1] + 64) //don't care about overflow
    arr2[i] = 1;

看起来这段代码1)不会使用分支表。据我所知,CPU不只是读取1个字节,它实际上读取8个字节(假设是64位机器),这2)使CPU做一些额外的工作。

接下来是另一种方法。一次读取2(或4或8)个字节,并创建一个非常巨大的开关(分别为2^16、2^32或2^64种情况),它在我们的数组中有各种可能的字节组合。这有什么意义吗?

对于这个讨论,我们假设如下:1)我们的首要任务是速度2)接下来是RAM消耗。我们不关心可执行文件的大小(除非它们以某种方式影响速度或RAM)


您应该知道,开关实际上非常慢,因为分支可能预测错误。快速切换的原因是跳台:

1
2
3
4
switch (i) {
   case 0: ...
   case 1: ...
}

转换为:

1
2
labels = {&case0, &case1}
goto labels[i]

但是,您不需要将其作为唯一的写入内存单元,您可以编写一个"跳转表",或者更具体地说,是自己预先计算的答案矩阵:

1
2
for (i = 1; i < 128; i++)
   arr2[i] = answers[arr[i]][arr[i-1]];

uint8只有256个可能的值,这给了我们该矩阵所需的64K RAM。