c++ 快速可分性测试(2,3,4,5,…,16)?

什么是最快的可分性测试?说,给定一个小端结构和一个32位有符号整数:如何计算非常快,一个数字可以被2,3,4,5,…最多可以16?

警告:给定代码仅为EXAMPLE。每一行都是独立的!使用模运算的明显解决方案在许多处理器上很慢,这些处理器没有DIV硬件(如许多ARM)。一些编译器也不能做这样的优化(比如,如果除数是一个函数的参数或依赖于某些东西)。

Divisible_by_1 = do();
Divisible_by_2 = if (!(number & 1)) do();
Divisible_by_3 = ?
Divisible_by_4 = ?
Divisible_by_5 = ?
Divisible_by_6 = ?
Divisible_by_7 = ?
Divisible_by_8 = ?
Divisible_by_9 = ?
Divisible_by_10 = ?
Divisible_by_11 = ?
Divisible_by_12 = ?
Divisible_by_13 = ?
Divisible_by_14 = ?
Divisible_by_15 = ?
Divisible_by_16 = if(!number & 0x0000000F) do();

和特殊情况:

Divisible_by_2k = if(number & (tk-1)) do();  //tk=2**k=(2*2*2*...) k times
这不是一个坏主意,所有解决分区指令的替代(包括模x86 / x64),因为他们是非常慢。比大多数人意识到的慢(甚至慢得多)。那些建议“%n”其中n是一个变量的人给出愚蠢的建议,因为它将不可避免地导致使用除法指令。另一方面,“%c”(其中c是常数)将允许编译器确定其所有组成部分中可用的最佳算法。有时它会是分割指令,但很多时候它不会。

this documentTorbjörnGranlund表明,无符号32位多态性:divs所需的时钟周期比率在Sandybridge为4:26(6.5x),在K10为3:45(15x)。对于64位,各自的比率是4:92(23x)和5:77(14.4x)。

“L”列表示等待时间。 “T”列表示吞吐量。这与处理器处理并行处理多个指令的能力有关。 Sandybridge可以每隔一个周期发出一个32位乘法,或者每个周期发送一个64位乘法。对于K10,相应的吞吐量相反。对于分割,K10需要在开始另一个序列之前完成整个序列。我怀疑Sandybridge是一样的。

使用K10作为示例,这意味着在32位除法(45)所需的周期期间,可以发出相同数量(45)的乘法,并且这些乘法中的倒数第二个和最后一个将完成一个和两个分频完成后的时钟周期。可以在45次乘法中执行大量的工作。

还有趣的是,从K8-K9到K10的演进,div已经变得不太有效:对于32位和64位,从39到45和71到77个时钟周期。

Granlund的page在gmplib.org和在Royal Institute of Technology在斯德哥尔摩包含更多的好东西,其中一些已被并入gcc编译器。

http://stackoverflow.com/questions/6896533/fast-divisibility-tests-by-2-3-4-5-16

本站文章除注明转载外,均为本站原创或编译
转载请明显位置注明出处:c++ 快速可分性测试(2,3,4,5,…,16)?