2016-05-31 6 views
1

実行時間は約1秒で行います多くの反復とループは、このコードの実行非常に遅い

start_time = Time.now 

prev = 1 
(1..1000).each do |i| 
    (1..10000).each do |j| 
    result = j * prev 
    result = result + prev 
    result = result - prev 
    result = result/prev 
    prev = j 
    end 
end 

end_time = Time.now 
printf('%f sec', end_time - start_time) 

しかし、書かれたように私は(代わりに2つのループ、1000万回の反復の10000000回の反復で1つのループを使用する場合(約4.5秒):

start_time = Time.now 

prev = 1 
(1..10000000).each do |j| 
    result = j * prev 
    result = result + prev 
    result = result - prev 
    result = result/prev 
    prev = j 
end 

end_time = Time.now 
printf('%f sec', end_time - start_time) 

どうしてですか?トータルの反復回数は同じです。

+1

は、それぞれの場合における 'result'の値を調査してみます。私は '10_000_000 * 9_999_999'が' 10_000 * 9_999'よりも大きいと思います。 –

+1

最初のコードは1.35秒、2番目のコードは1.24秒です。変数 'result'は毎回リセットされるので、過度に大きくならない。 –

+0

基本的に、最初のコードの反復は、1.35秒と1.24秒ですか?奇妙な ロギングの実行を小さなチャンクで試してください。たとえば、合計の20%ごとに実行してください。全体的な負荷は簡単なチェックで均等に増加するはずですので、テストに目に見えるほどの影響はありません。 –

答えて

2

第2の例は、最初のものよりもはるかに大きな数を処理します(@Sergii Kがコメントしました)。 2番目のサンプルコードがシステムの最大Fixnum制限に達する可能性があります。 32ビットシステムでは、maximum signed integer2**(32-1) - 1 = 2147483647であり、第2の例では(第1の例の最大製品ではなく)最大製品j * prevよりはるかに小さい。このような状況では、Fixnumsを内部でBignumsに変換しなければならないため、2番目のサンプルコードが最初のサンプルコードよりも遅くなる可能性があります。

64ビットシステムでは、最大整数がFixnumの制限に達しないため、両方のサンプルがほぼ同じ時間実行されると思います。そういうわけで、他のほとんどのコメント作成者がタイミングの大きな違いを見なかったのかもしれません。

更新:最大Fixnumか番号のみ1073741823である場合に、上記OPによってコメントとして、それはOS自体が64ビットであることを意味する必要があり、おそらくインストールRubyは、64ビットのルビー、 Fixnum番号(実際には64ビットのルビーに8個ではなく)を格納するのに4バイトしか使用しません。最大の整数値は第2の例ではそれほど必要ではないので、実際にはより高い数値をBignumsに変換する必要があり、それは第2のサンプルの遅さがどこから来るかである。あなたは比較すれば

あなたはこれを自分でチェックすることができます。

(2**(0.size * 8 -2) -1).class  # => Fixnum vs: 
(2**(0.size * 8 -2) -1 + 1).class # => should be Bignum 
関連する問題