【问题标题】:Why is the binary GCD algorithm so much slower for me?为什么二进制 GCD 算法对我来说这么慢?
【发布时间】:2011-10-18 22:32:24
【问题描述】:

http://en.wikipedia.org/wiki/Binary_GCD_algorithm

根据 Wikipedia,它应该比 Euclid 的算法快一点(不多,但我至少期望获得相同的性能)。对我来说,它慢了一个数量级。你们能帮我弄清楚原因吗?

我尝试在 Ruby 中实现它。首先,我采用了递归解决方案

def gcd_recursive(u, v)
return u|v if u==0 or v==0

if u.even?
  if v.even?
    return gcd(u>>1, v>>1)<<1
  else
    return gcd(u>>1, v) if v.odd?
  end
elsif u.odd? and v.even?
  return gcd(u, v>>1)
else
  if u < v
    u, v = v, u
  end
  return gcd((u-v)>>1, v)
end
end

效果不太好,所以我想检查一下如果它是一个循环会多快

def gcd(u, v)
  return u|v if u==0 or v==0
  shift=0
  while ((u|v)&1)==0 do
    u=u >> 1;
    v=v >> 1;
    shift += 1
  end
  while ((u&1) == 0) do 
    u=u >> 1
  end
  begin
    while ((v & 1) == 0) do
      v=v >> 1
    end

    if u < v
      v -= u
    else
      diff = u - v
      u = v
      v = diff
    end
  end while v != 0
  u<<shift
end

这些是基准测试结果

       user     system      total        real
std  0.300000   0.000000   0.300000 (  0.313091)
rbn  0.850000   0.000000   0.850000 (  0.872319)
bin  2.730000   0.000000   2.730000 (  2.782937)
rec  3.070000   0.000000   3.070000 (  3.136301)

std 是原生 ruby​​ 1.9.3 C 实现。

rbn 基本上是一样的东西(欧几里得算法),但是是用 Ruby 写的。

bin 是你在上面看到的循环代码。

rec 是递归版本。

编辑:我在 matz 的 ruby​​ 1.9.3 上运行了基准测试。我尝试在 Rubinius 上运行相同的测试,这就是我得到的。这也令人困惑...

 rbn  1.268079   0.024001   1.292080 (  1.585107)
 bin  1.300082   0.000000   1.300082 (  1.775378)
 rec  1.396087   0.000000   1.396087 (  2.348785)

【问题讨论】:

    标签: ruby performance algorithm greatest-common-divisor


    【解决方案1】:

    这只是一个猜测,但我怀疑这是两个原因的结合:

    1. 二进制 GCD 算法比 Euclid 算法更复杂,并且涉及较低级别的操作,因此在使用 Ruby 等高级语言实现时,其解释开销更大。
    2. 现代计算机往往具有快速除法(和模)指令,这使得标准欧几里得算法难以与之竞争。

    【讨论】:

    • 这几乎肯定是#1,几乎肯定不是#2。如果大多数计算机都有快速除法和取模指令,那么所有计算机都有非常快速的移位指令,其中许多具有单周期实现。
    • bcr,我不确定...看看我的小“编辑”。我还做了一些关于 rubinius 和 matz ruby​​ 如何处理 xor 和 AND 的实验。事实证明 matz 使用 xors 更快,而 rubinius 使用 and 操作要快得多。 gist.github.com/1297201
    • This 表示每个 64 位 DIV 有 77-191 个时钟;比我预期的要慢得多! Bignum 性能(例如,使用 GMP)和手动调整的装配一样有趣,但我并不那么感到无聊。内存分配是另一个潜在的开销,特别是如果您使用 bignums。
    • 我错了还是所有的东西都写在这里:en.wikipedia.org/wiki/Binary_GCD_algorithm#Efficiency?
    猜你喜欢
    • 2021-02-17
    • 2022-11-27
    • 2018-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-19
    • 2019-07-10
    相关资源
    最近更新 更多