优化:为什么<比多个贵!=

时间:2013-08-01 01:42:00

标签: c++ c arrays performance optimization

我有一个二维数组的字符,我需要做一些操作。在某些情况下,我需要检查字符是否为a-h。我过去通过检查字符是否与其他任何字符(仅有5个其他字符)相同来完成此操作。但是,我最近有一个想法,我可以检查字符是否< 'j'得到相同的结果,希望更少的装配说明。

在某些地方,我说,它确实导致了一个小的加速,但在其他地方,它导致了相当大的减速。任何想法为什么会这样?什么是相对费用!=而不是<在if语句中?

以下是一个示例代码段:

if( arr[r][c] == arr[r][c+1] && arr[r][c] == arr[r][c+2]
         && arr[r][c] != 'q' && arr[r][c] != 'r' && arr[r][c] != 's' && arr[r][c] != 't')

VS

if( arr[r][c] == arr[r][c+1] && arr[r][c] == arr[r][c+2]
         && arr[r][c] < 'j')

3 个答案:

答案 0 :(得分:5)

如果我正确理解了您的问题,您似乎希望检查数组列的所有元素是否在字符'a'和'h'之间并且是相同的,并且您希望优化此过程。

如果您碰巧知道某种汇编语言,我强烈建议您使用反汇编程序来查找执行期间函数中出现完全的内容。所有编译器和优化级别略有不同。但是,在内存中比较两个值的最小操作包括:

。将内存中的两个变量加载到处理器寄存器(几个时钟周期)

。对两个寄存器中的值执行相等测试(1个时钟周期)

。基于标志寄存器(英特尔处理器)执行跳转命令(另一个时钟周期)

现在这对于处理器来说就像操作一样简单,但由于你有堆叠比较操作,所以这些检查所需的时间会累积(特别是内存访问所需的时钟周期。

因此,为了减少这些比较所需的时间,需要减少比较次数。请记住,字符'a'到'h'的ascii值介于0x61和0x68之间(十进制97到104)。您可以通过以下方式确定角色是否在“a”到“h”之间进行了大约三次比较:

if(arr[r][c] >= 97 && arr[r][c] <= 104)

只检查列的一个值,并使用这个bit-twiddling技巧来确定列中的所有元素是否相同:

if(((arr[r][c] ^ arr[r][c+1]) + (arr[r][c] ^ arr[r][c+2]) + ...*etc*) == 0)

“xor”('^')比较采用单个时钟周期,添加也是如此,如果任意两个列实体之间存在任何差异,则操作将导致非零结果。此方法应随着列元素的数量增加线性时间,并且作为额外的好处,优化编译器可能能够在操作期间将'arr [r] [c]'保留在其中一个寄存器中。

答案 1 :(得分:1)

现代编译器/ CPU使用分支预测来预先获取有利于某些执行路径的候选结果。您的编辑预测了不同的结果,从而产生了不同的结结果可能取决于2D阵列的内容。此外,优点可能在不同的编译器/ CPU上有所不同。搜索分支预测 - 那里有一些很好的答案。

答案 2 :(得分:1)

不要过分关注速度。编写一个程序,首先解决一个实际的,有意义的任务。完成后,使用分析器确定该程序的哪些部分是最重要的瓶颈。在您编写一个程序来解决实际的,有意义的任务之前,您应该专注于编写可移植的,定义良好的代码而不是快速的代码。

你的速度概念不符合C标准。事实上,这里没有关于速度的保证。有快速编译器和慢速编译器,甚至快速和慢速C解释器。因此,您关于速度的问题无效。如果你的C编译器在这种情况下不会产生大致相同的代码(就速度而言),那么要么学习如何启用完全优化,要么学习新的C编译器。

这看起来不便携:

if( arr[r][c] == arr[r][c+1] && arr[r][c] == arr[r][c+2]
     && arr[r][c] < 'j')

在使用EBCDIC的系统上,您认为是'j' - 'i'的{​​{1}}实际上是145 - 137(十二)。您的测试包括11个不按字母顺序排列的其他字符。我建议您使用strchr("abcdefghi", a[r][c]),直到您担心效果为止。如果你担心这个速度(你不应该这样,因为它在解决实际问题的任何事情上都是一个小任务),你可以尝试使用开关将其转换为跳转表:

if (arr[r][c] == arr[r][c+1] && arr[r][c] == arr[r][c+2]) {
    switch (a[r][c]) {
        case 'a': case 'b': case 'c':
        case 'd': case 'e': case 'f':
        case 'g': case 'h': case 'i':
        /* XXX: Insert code that runs when a[r][c] is in "abcdefghi"... */
        break;
    }
}

要衡量此优化,您可以使用第一段中建议的分析器。