2016-06-17 14 views
1

私は大量のデータを扱っています。私は自分の業務の効率を心配しています。ベンチマーク後、このコード列を実行する平均時間は約0.004秒です。このコード行の目的は、各配列位置の2つの値の差を見つけることです。以前の操作では、111.111が無効なデータを含む場所の配列にロードされました。いくつかの奇妙な時間領域の問題のために、私は値を取り除くことができず、識別可能なプレースホルダが必要だったので、これを行う必要がありました。おそらく、ここでは 'nil'を代わりに使うことができます。とにかく、説明に戻る。このコード行は、いずれの配列も現在の場所にこの111.111のプレースホルダーがないことを確認します。値が有効であれば、私は数学演算を実行します。そうでなければ、値を削除したい(または、少なくとも私が書いている新しい配列からそれらを除外したい)。私はその場所に 'nil'を置き、その後に配列を圧縮することでこれを達成しました。Ruby:効率の向上

各アレイの4000データポイントの0.004秒の時間はひどいわけではありませんが、このコード行は25M回実行されます。私は誰かがこのコード行をどのように最適化するかについていくつかの洞察を提供できることを期待しています。

temp_row = row_1.zip(row_2).map do |x, y| 
    x == 111.111 || y == 111.111 ? nil : (x - y).abs 
end.compact 
+0

「zip」は完全には必要ありません。 –

+0

そして、5000スレッドの作成から4000%の改善 - それは幻想です:) –

+0

ジップなし:http://pastie.org/10881223 –

答えて

0

あなたは、あなたがそれらを削除するcompactを使用して、その後、三元の文にnilを生成するCPUを無駄にしているparallel宝石https://github.com/grosser/parallelを試してみて、複数のスレッド

+0

ああ、これは間違いなく非常に便利な宝石ですが、サポートされていないようですruby 2.3.0p0(2015-12-25リビジョン53290)[x64-mingw32] –

+0

@ srm985それは残念です – Ruslan

+0

複数のスレッドで実行すると必ずしも高速化されるとは限りません。幸せなバランスがあり、テストで見つけることができます。 –

2

上でそれを実行することができます。代わりにrejectまたはselectを使用して、111.111を含む要素を見つけ、次にmapなどの要素を探します。

temp_row = row_1.zip(row_2) 
       .reject{ |x,y| x == 111.111 || y == 111.111 } 
       .map{ |x,y| (x - y).abs } 
temp_row # => [1, 2] 

または::私は開始したい

row_1 = [1, 111.111, 2] 
row_2 = [2, 111.111, 4] 

temp_row = row_1.zip(row_2).map do |x, y| 
    x == 111.111 || y == 111.111 ? nil : (x - y).abs 
end.compact 
temp_row # => [1, 2] 

代わりの

temp_row = row_1.zip(row_2) 
       .each_with_object([]) { |(x,y), ary| 
        ary << (x - y).abs unless (x == 111.111 || y == 111.111) 
       } 
temp_row # => [1, 2] 

ベンチマーク異なるサイズの配列を知るには良いものを示しています

require 'benchmark' 

DECIMAL_SHIFT = 100 
DATA_ARRAY = (1 .. 1000).to_a 
ROW_1 = (DATA_ARRAY + [111.111]).shuffle 
ROW_2 = (DATA_ARRAY.map{ |i| i * 2 } + [111.111]).shuffle 

Benchmark.bm(16) do |b| 
    b.report('ternary:') do 
    DECIMAL_SHIFT.times do 
     ROW_1.zip(ROW_2).map do |x, y| 
     x == 111.111 || y == 111.111 ? nil : (x - y).abs 
     end.compact 
    end 
    end 

    b.report('reject:') do 
    DECIMAL_SHIFT.times do 
     ROW_1.zip(ROW_2).reject{ |x,y| x == 111.111 || y == 111.111 }.map{ |x,y| (x - y).abs } 
    end 
    end 

    b.report('each_with_index:') do 
    DECIMAL_SHIFT.times do 
     ROW_1.zip(ROW_2) 
      .each_with_object([]) { |(x,y), ary| 
      ary += [(x - y).abs] unless (x == 111.111 || y == 111.111) 
      } 
    end 
    end 
end 

# >>      user  system  total  real 
# >> ternary:   0.240000 0.000000 0.240000 ( 0.244476) 
# >> reject:   0.060000 0.000000 0.060000 ( 0.058842) 
# >> each_with_index: 0.350000 0.000000 0.350000 ( 0.349363) 

DECIMAL_SHIFTDATA_ARRAYのサイズを調整し、111.111の配置を調整し、データサイズと構造に最適な表現が得られ、必要に応じてコードを微調整する方法を確認します。

+0

'nil'と 'compact'を使用すると実行時間が0.000867secになり、 'reject'を使用すると実行時間は0.001219secになりました。これらは約4000ポイントの配列で実行されました。 –

+0

ベンチマーキングの結果が低いと私は疑わしい。使用可能なサンプルデータとベンチマークコードがなければ、実際にリンゴとリンゴを比較することはできません。 –

+0

私は2000回の反復でそれを実行し、完全なループをベンチマークしました。結果はそれぞれ8.922337秒と10.834802秒でした。私はサンプルデータを提供していないとちょっと難しいと思っています。私はこれについてのすべての助けに感謝します。 –

関連する問題