C语言中模算子的性能

C语言中模算子的性能,c,modulo,C,Modulo,从执行时间的角度来看,如果我要做大量的模运算,大约10^6次,使用模运算还是手动方式更有益? 手动执行编号%mod_编号: while(number >= mod_number) { number = number - mod_number; } 使用%operator执行相同的操作: number = number % mod_number; 根据我的测试,手动操作可以提供更好的时间性能。 模运算符是如何定义的?我知道负数的输出是实现定义的,我询问操作员的工作情况,即其复杂

从执行时间的角度来看,如果我要做大量的模运算,大约10^6次,使用模运算还是手动方式更有益? 手动执行编号%mod_编号:

while(number >= mod_number) {
     number = number - mod_number;
}
使用%operator执行相同的操作:

number = number % mod_number;
根据我的测试,手动操作可以提供更好的时间性能。 模运算符是如何定义的?我知道负数的输出是实现定义的,我询问操作员的工作情况,即其复杂性,以便证明更好的手动性能。 注意:该问题专门针对C中的实现。 代码片段:


上述循环执行2*10^5*t次,每次“t”的“idx”逐渐增加到100。使用t=10。

根据我的经验,使用模运算符应该可以获得更好的性能。编写C编译器的人应该考虑优化他们正在执行的操作


但是您的测试结果显示了另一种情况,这可能取决于您编写的代码。找到原因会更容易些?如果您显示您的代码…

当数字比mod_数字大很多倍时,如果循环效率更高,我会非常惊讶。您可能使用的任何CPU都有一个内置的除法运算,它在固定时间内返回商和余数,这将用于实现%运算符。您的循环占用Onumber/mod_number时间


我建议您查看两个版本生成的汇编代码,您将看到这一点。

这取决于实现。在没有给定系统的情况下讨论性能是毫无意义的

模数运算符可能通过CPU的除法指令实现,与其他CPU指令相比,除法指令在大多数CPU上相对较慢。然而,像您的示例中那样的循环似乎不太可能更有效率


更可能的是,您遇到的性能差异要么与错误的优化设置有关,要么与错误的基准测试有关

您刚才的示例没有显示,虽然在顶部循环,但底部的代码段是除数最多只减去一次的情况。这基本上是重复减法0或1次的一种情况,重复减法的特殊情况可以并且通常是,但不一定比基于除法的模快。显然,它取决于目标上的除法速度,测试/分支或测试/谓词指令在目标上的速度,对于分支,它甚至取决于分支的可预测性

编译器不太可能进行这种优化,但也不是不可能,因为只有在已知减法最多只发生一次或可能不止一次的情况下才有意义,如果除法在目标上特别慢,但仍然需要一些较低的界限,这对于编译器来说通常是很难找到的

举一些例子,在Haswell 32位有符号除法上,因此模运算需要22到29个周期,分支预测失误可能需要20个周期,但这是最坏的情况,分支不应该总是预测失误。此外,如果分支预测错误,您可以避免它,并做一些类似的未经测试的事情,只是为了给您一些想法

sub eax, edx
lea edx, [eax + edx]
cmovl eax, edx

这应该只需要大约4个周期,与任何可预测性无关。如果可以很好地预测分支,那么使用分支可能会更快。

这不取决于编译器/实现吗?另外:请显示您的基准测试代码……您测量了吗?第一个代码段的平均运行速度如何?以INT_MAX%3为例,与简单除法相比,需要减法多少次?如果CPU的除法是常数时间,那么Onumber/mod_数也是常数时间。因为这个数字显然是以一个常数为界的。
sub eax, edx
lea edx, [eax + edx]
cmovl eax, edx