繁体   English   中英

在以 4000 作为除数的 cuda gpu 上计算快速模运算。 eq: (ab)%4000

[英]Calculate fast modulo arithmetic on cuda gpu having 4000 as divisor . eq: (a-b)%4000

我正在尝试在 pascal 架构(nvidia 1060)上优化 cuda 中的模运算,因为传统的 (%) 运算符会显着减慢代码速度。 我看过一些优化的例子,但它们仅在除数是 2 或 (2^k)-1 的幂时才适用。 在我的代码中,除数是 4000。

好心,建议我一个优化的方法来计算下面的等式中的余数

  remainder = (a-b)%4000

我假设您可以证明与使用编译器优化和使用位掩码的模 4096 相比有多慢? 如果它只慢 2 到 3 倍,你真的无法击败它,

为了好玩,因为我怀疑你会超过上述指标:

在现代处理器上,除法通常不会那么慢,但要注意的一件事是,当它变慢时,它取决于被除数的大小。 另一个是无符号除法比有符号除法更快。

减少数字大小的一种方法是考虑如何建立模数。

如果你执行 div 和 mod 4096,那么你可以问,什么是 4096 mod 4000 = 96。所以你的原始数字的 mod 4000 是(96 * div4096 + mod4096) mod 4000其中这些是比你开始时更小的数字并且可能,只是也许更快,因为它使用更少的位。 注意,在这个阶段你也可以使用4000 = 32 * 125的关系,所以低5位将是模的低5位,你只需要除以125。

现在在 8 位处理器上,除以小于 128 比除以更大的数字要快得多! 不过,我怀疑您是否拥有其中之一。

另一种选择是使用高精度逆乘法。 具有较差除法的处理器可能具有可接受的乘法。 这个技巧是你可以使用最大的整数来执行 2^n/4000 的乘法,其中 n 是大整数类型宽度的一半,或者可以更高,如果你需要除以的最大数是小于 2^n。 该数字的顶部 (>>n) 是除法的(近似)结果,如果分辨率足够高,应该“足够接近”。 再次将该值乘以 4000 并从原始值中减去,您的模数为 +/- 4000 的几倍,这是 2 次大乘法与 1 次小除法的成本。 在 intel 上有一个乘法输入 16 位值ax*dx并输出 32 位值dx:ax ,并为64-bit edx*eax => 128 bit edx:eax复制,但当然是 intel 386 及更高版本无论如何都有足够快的分歧。

还有另一种通用方法,当您想要的除数接近 2 的幂时,在您的情况下,4000 是 4096 的 97%:

loop:
  do the div4096 by bit shift
  multiply 4000 by div4096
  subtract
until result < 3*4096 
use if statement to get final mod value

这将执行重复乘法,但每次,div4096 都是 div4000 的低估计量,降低 3%,0.03,大约 64 位或 6 位中的 1 个,在下一次迭代时会被清除,因此它可能会循环此循环 7 次对于 64 位最大值。 如果 mul 比 div 快 7*,那么你就赢了。 如果您想要 mod 或 div 的值比 2 的幂低几个百分点,那么迭代次数就太高了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM