在Ruby中乘以两个数组并获得乘积值之和的有效方法是什么?

前端之家收集整理的这篇文章主要介绍了在Ruby中乘以两个数组并获得乘积值之和的有效方法是什么?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
Ruby中乘以两个数组并获得乘法值之和的有效方法是什么?
我在Ruby中有两个数组:
array_A = [1,2,1,4,5,3,6,8,9]
array_B = [3,7,4]

我的目标是得到array_A * array_B的和值,即1 * 3 2 * 2 1 * 4 … 8 * 5 9 * 4.

因为我需要在我的应用程序中计算它们数百万次,所以进行此类计算的最有效方法是什么?

它就像一个矩阵计算:1 * N矩阵* N * 1矩阵或矢量点积.

解决方法

更新

我刚刚根据新评论更新了基准测试.在Joshua’s comment之后,注入方法将获得25%的加速,参见下表中没有to_a的数组行走.

然而,由于速度是OP的主要目标,我们有a new winner for the contest,它在我的基准测试中将运行时间从.34减少到.22.

我仍然更喜欢注入方法,因为它更像ruby-ish,但如果速度很重要,那么while循环似乎就是这样.

新答案

您可以随时对所有这些答案进行基准测试,我是出于好奇而做到的:

> ./matrix.rb 
Rehearsal --------------------------------------------------------------
matrix method                1.500000   0.000000   1.500000 (  1.510685)
array walking                0.470000   0.010000   0.480000 (  0.475307)
array walking without to_a   0.340000   0.000000   0.340000 (  0.337244)
array zip                    0.590000   0.000000   0.590000 (  0.594954)
array zip 2                  0.500000   0.000000   0.500000 (  0.509500)
while loop                   0.220000   0.000000   0.220000 (  0.219851)
----------------------------------------------------- total: 3.630000sec

                                 user     system      total        real
matrix method                1.500000   0.000000   1.500000 (  1.501340)
array walking                0.480000   0.000000   0.480000 (  0.480052)
array walking without to_a   0.340000   0.000000   0.340000 (  0.338614)
array zip                    0.610000   0.010000   0.620000 (  0.625805)
array zip 2                  0.510000   0.000000   0.510000 (  0.506430)
while loop                   0.220000   0.000000   0.220000 (  0.220873)

简单的数组行走胜利,Matrix方法更糟糕,因为它包括对象实例化.我认为,如果你想击败注入方法(在这里击败意味着一个数量级最快),你需要实现一个C扩展并将其绑定在你的ruby程序中.

这是我用过的剧本

#!/usr/bin/env ruby

require 'benchmark'
require 'matrix'

array_A = [1,4]

def matrix_method a1,a2
  (Matrix.row_vector(a1) * Matrix.column_vector(a2)).element(0,0)
end

n = 100000

Benchmark.bmbm do |b|
  b.report('matrix method') { n.times { matrix_method(array_A,array_B) } }
  b.report('array walking') { n.times { (0...array_A.count).to_a.inject(0) {|r,i| r + array_A[i]*array_B[i]} } }
  b.report('array walking without to_a') { n.times { (0...array_A.count).inject(0) {|r,i| r + array_A[i]*array_B[i]} } }
  b.report('array zip') { n.times { array_A.zip(array_B).map{|i,j| i*j }.inject(:+) } }  
  b.report('array zip 2') { n.times { array_A.zip(array_B).inject(0) {|r,(a,b)| r + (a * b)} } }
  b.report('while loop') do
    n.times do
      sum,i,size = 0,array_A.size
      while i < size
        sum += array_A[i] * array_B[i]
        i += 1
      end
      sum
    end
  end
end

猜你在找的Ruby相关文章