使用Ruby NArray相比于Array有哪些优势?

7

我刚刚了解到Ruby的NArray库 - 请原谅我对这个问题的无知 :)

使用NArray库与标准Ruby数组实现相比,有什么优点?

我看到NArray是针对数值计算的,但是查看API,似乎只有一些针对数值的Array扩展,没有什么是你不能用Array做到的。

  1. 为什么不直接使用Array?
  2. 是否有巨大的速度优势?
  3. 是否有巨大的内存优势?
  4. 除了使用常规的Ruby Array类之外,还有其他优点吗?

谷歌并没有真正提供有用的解释。

我找到的参考资料:

http://rubydoc.info/gems/narray-ruby19/0.5.9.7/NArray

http://narray.rubyforge.org/index.html.en

http://raa.ruby-lang.org/project/narray/


Ruby语言中有一个更新的数值数组库叫做NMatrix,可能会很有用。 :P - Carlos Agarie
3个回答

10

参见有关NArray的幻灯片:http://www.slideshare.net/masa16tanaka/narray-and-scientific-computing-with-ruby

看起来似乎只有几个扩展是基于数组进行的。

不,它与数组完全不同。NArray具有许多数值函数和多维特性。另一方面,NArray是静态的;它没有push/pop方法等。NArray的方法列表在http://narray.rubyforge.org/SPEC.en

_1. 为什么不直接使用Array?

数组包含Ruby对象。保存数值效率低下。

_2. 是否存在巨大的速度优势?

是的。上述幻灯片的第36页显示,NArray的速度快了50倍。

请注意,如果循环是用Ruby编写的,则Array比NArray更快。

_3. 是否存在巨大的内存优势?

是的。对于浮点值,在我的64位Linux机器上,Array消耗的内存约为NArray的4倍。

_4. 是否有其他优于使用常规Ruby Array类的优势?

  • 支持多维数组
  • 支持数值函数
  • 不需要进行垃圾回收。对于大型数组,GC需要很长时间。
  • 等等。

5
我看到 NArray 是针对数值计算的,但是从 API 看来,它似乎只是在 Array 的基础上添加了一些针对数值的扩展,有些东西甚至用 Array 也可以实现。
你错过了最重要的一点:NArray 不仅仅是为了数值处理而“扩展”,还进行了“限制”。具体来说:
- NArray 元素只能是固定大小的整数或浮点数 - NArray 本身也是固定大小的,不能缩小或扩大
NArray 的实现可以利用这些限制提供优越的性能。

1
对于大型的数值数组创建,NArray 可能更快,但对于小型数组创建(例如临时中间对象),Ruby 数组似乎更快。
基准测试代码:
require 'benchmark'

n1 = 1000000
n2 = 10000
Benchmark.bm do |x|
  x.report("NArray short float length 5:") { n1.times { NArray.sfloat(5) } }
  x.report("NArray long float length 5 :") { n1.times { NArray.float(5) } }
  x.report("NArray short int length 5  :") { n1.times { NArray.sint(5) } }
  x.report("NArray long int length 5   :") { n1.times { NArray.int(5) } }
  x.report("NArray object length 5     :") { n1.times { NArray.object(5) } }
  x.report("Ruby Array length 5        :") { n1.times { Array.new(5) } }  

  x.report("NArray short float length 10000:") { n2.times { NArray.sfloat(10000) } }
  x.report("NArray long float length 10000 :") { n2.times { NArray.float(10000) } }
  x.report("NArray short int length 10000  :") { n2.times { NArray.sint(10000) } }
  x.report("NArray long int length 10000   :") { n2.times { NArray.int(10000) } }
  x.report("NArray object length 10000     :") { n2.times { NArray.object(10000) } }
  x.report("Ruby Array length 10000        :") { n2.times { Array.new(10000) } }
end

结果:

                              user       system     total     real
NArray short float length 5:  0.740000   0.020000   0.760000 (  0.756466)
NArray long float length 5 :  0.770000   0.020000   0.790000 (  0.791446)
NArray short int length 5  :  0.750000   0.020000   0.770000 (  0.772591)
NArray long int length 5   :  0.760000   0.020000   0.780000 (  0.777375)
NArray object length 5     :  0.780000   0.020000   0.800000 (  0.801149)
Ruby Array length 5        :  0.450000   0.010000   0.460000 (  0.461501)    <====
NArray short float length 10000:  0.230000   0.050000   0.280000 (  0.281369)
NArray long float length 10000 :  0.430000   0.000000   0.430000 (  0.428917)
NArray short int length 10000  :  0.110000   0.010000   0.120000 (  0.113683)
NArray long int length 10000   :  0.230000   0.040000   0.270000 (  0.275942)
NArray object length 10000     :  0.460000   0.110000   0.570000 (  0.570558)
Ruby Array length 10000        :  0.440000   0.040000   0.480000 (  0.476690)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接