What are the advantages of using Ruby NArray over Array?

纵然是瞬间 提交于 2019-12-05 05:47:34

See also the slide about NArray: http://www.slideshare.net/masa16tanaka/narray-and-scientific-computing-with-ruby

it looks like there are only a few extensions over Array

No, it's completely different from Array. NArray has many numerical functions and multi-dimensional features. On the other hand, NArray is static; it does not have push/pop methods, etc. NArray's method list is http://narray.rubyforge.org/SPEC.en

_1. Why not just use Array?

Array holds Ruby Objects. It is inefficient to hold numerical values.

_2. Is there a huge speed advantage?

Yes. p.36 of the above slide shows NArray is up to 50 times faster.

Note that Array is faster than NArray if the loop is written in Ruby.

_3. Is there a huge memory advantage?

Yes. As for Float values, Array consumes about 4 times more memory than NArray on my 64bit Linux machine.

_4. Any other advantages over using the regular Ruby Array class?

  • Support of multi-dimensional array
  • Support of Numerical functions
  • No need for garbage collection on Array items. GC takes large time for large Arrays.
  • etc.

I've seen that NArray is geared towards numerical computing, but looking at the API, it looks like there are only a few extensions over Array geared towards numerical values -- nothing that you couldn't do with Array..

You are missing the most important point: NArray is not just extended for numerical processing, it is also restricted. In particular

  • NArray elements can only be fixed-size integers or floats
  • NArrays themselves are also fixed-size, they cannot shrink or grow

An implementation of NArray can exploit those restrictions to provide superior performance.

For large typed array creation NArray can be faster, though for small array creation (e.g. for temporary intermediate objects) Ruby Array seems to be fast is faster.

Benchmark code:

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

Results:

                              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)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!