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]]; |