Using ruby for scientific computing

Hi all,

For pedagogic purposes, I am trying to solve simple partial differential
equations (say a diffusion equation on a regular mesh in 2D) with Ruby.
Using the NArray gem, I have built a satisfactory tool from an interface
(and ease of use) point of view but the performance are suboptimal.

I am now wondering what is the right way to improve my code
performance-wise. I am doing a lot of matrix-vector and vector-vector
products.

From 2 2D NArrays describing two scalar fields, dot-product is implemented as :

def dot_product(vec_a, vec_b)
        dot_product=(vec_a*vec_b">vec_a*vec_b).sum
end

and as I am working with sparse matrices, (for the time being) a matrix
is an Array of Hashes. Each key of the hash contains the index of the
non-vanishing coefficients (the value of this coefficient is the value
of the Hash) of the matrix. For the identity matrix it gives

def identity(sizeX, sizeY)
        mat=[]
        (0..sizeX*sizeY">sizeX*sizeY).each { |ind|
            mat << {ind=>1.0}
        }
        mat
end

Matrix vector product is then defined as

def matrix_vector_product(mat, vector)
        ff=NArray.float(100,100)
        (0..100*100).each { |ind|
            matrix[ind].each do |key,value|
                ff[[ind]]+=value*vector[[key]][0]
            end
        }
        ff
end

I am wondering what is the best way to tackle this performance problem :
1. Improve the ruby code (and how? :slight_smile: Should I avoid using hashes?
2. Write an extension to perform these operations in C. BTW is there a
way to access directly NArray data (without copy) from a C extension?
3. Use a wrapper like Ruby-lapack
(
https://rubyforge.org/projects/ruby-lapack/
).

What do you think?

Thanks for your help !

···

--
  Olivier Saut
  
osaut@airpost.net
                                       - Olivier

Hello,

Hi all,

For pedagogic purposes, I am trying to solve simple partial differential
equations (say a diffusion equation on a regular mesh in 2D) with Ruby.
Using the NArray gem, I have built a satisfactory tool from an interface
(and ease of use) point of view but the performance are suboptimal.

Is the code available on a public repo?

I am now wondering what is the right way to improve my code
performance-wise. I am doing a lot of matrix-vector and vector-vector
products.

From 2 2D NArrays describing two scalar fields, dot-product is implemented as :

def dot_product(vec_a, vec_b)
       dot_product=(vec_a*vec_b">vec_a*vec_b).sum
end

and as I am working with sparse matrices, (for the time being) a matrix
is an Array of Hashes. Each key of the hash contains the index of the
non-vanishing coefficients (the value of this coefficient is the value
of the Hash) of the matrix. For the identity matrix it gives

def identity(sizeX, sizeY)
       mat=
       (0..sizeX*sizeY">sizeX*sizeY).each { |ind|
           mat << {ind=>1.0}
       }
       mat
end

Matrix vector product is then defined as

def matrix_vector_product(mat, vector)
       ff=NArray.float(100,100)
       (0..100*100).each { |ind|
           matrix[ind].each do |key,value|
               ff[[ind]]+=value*vector[[key]][0]
           end
       }
       ff
end

I am wondering what is the best way to tackle this performance problem :
1. Improve the ruby code (and how? :slight_smile: Should I avoid using hashes?
2. Write an extension to perform these operations in C. BTW is there a
way to access directly NArray data (without copy) from a C extension?
3. Use a wrapper like Ruby-lapack
(
https://rubyforge.org/projects/ruby-lapack/
).

What do you think?

Thanks for your help !

--
Olivier Saut

osaut@airpost.net
                                       - Olivier

Panagiotis Atmatzidis

···

On 8 Σεπ 2012, at 18:06 , Olivier Saut <osaut@airpost.net> wrote:
-----------------------------
Pharmacy Student at VFU

email4lists: ml@convalesco.org
More info: http://about.me/atmosx

The wise man said: "Never argue with an idiot, he brings you down to his level and beat you with experience."

Olivier Saut wrote in post #1075138:

Hi all,

For pedagogic purposes, I am trying to solve simple partial differential
equations (say a diffusion equation on a regular mesh in 2D) with Ruby.
Using the NArray gem, I have built a satisfactory tool from an interface
(and ease of use) point of view but the performance are suboptimal.

.......

I am wondering what is the best way to tackle this performance problem :
1. Improve the ruby code (and how? :slight_smile: Should I avoid using hashes?
2. Write an extension to perform these operations in C. BTW is there a
way to access directly NArray data (without copy) from a C extension?
3. Use a wrapper like Ruby-lapack
(
https://rubyforge.org/projects/ruby-lapack/
).

What do you think?

Thanks for your help !

Hi,

Because it seems that you emphasize on performance, I think the best way
is to use GNU Octave for dealing with the sparse matrices. There is a
Ruby gem (octave-ruby) to bridge between Ruby and Octave objects.

I really like Ruby, but for scientific computing I think for now Python
has better libraries.

Regards,

Bill

···

--
Posted via http://www.ruby-forum.com/\.

Have you taken a look at stdlib's matrix.rb?

= MMaattrriixx  <<  OObbjjeecctt

(from ruby core)

···

On Sep 8, 2012, at 09:06 , Olivier Saut <osaut@airpost.net> wrote:

Hi all,

For pedagogic purposes, I am trying to solve simple partial differential
equations (say a diffusion equation on a regular mesh in 2D) with Ruby.
Using the NArray gem, I have built a satisfactory tool from an interface
(and ease of use) point of view but the performance are suboptimal.

------------------------------------------------------------------------------
The Matrix class represents a mathematical matrix, and provides methods for
creating special-case matrices (zero, identity, diagonal, singular, vector),
operating on them arithmetically and algebraically, and determining their
mathematical properties (trace, rank, inverse, determinant).

Note that although matrices should theoretically be rectangular, this is not
enforced by the class.

Also note that the determinant of integer matrices may be incorrectly
calculated unless you also require 'mathn'. This may be fixed in the future.

== MMeetthhoodd  CCaattaalloogguuee

To create a matrix:
* Matrix[*rows]
* Matrix.(*rows)
* Matrix.rows(rows, copy = true)
* Matrix.columns(columns)
* Matrix.diagonal(*values)
* Matrix.scalar(n, value)
* Matrix.scalar(n, value)
* Matrix.identity(n)
* Matrix.unit(n)
* Matrix.I(n)
* Matrix.zero(n)
* Matrix.row_vector(row)
* Matrix.column_vector(column)

To access Matrix elements/columns/rows/submatrices/properties:
* (i, j)
* #row_size
* #column_size
* #row(i)
* #column(j)
* #collect
* #map
* #minor(*param)

Properties of a matrix:
* #regular?
* #singular?
* #square?

Matrix arithmetic:
* *(m)
* +(m)
* -(m)
* #/(m)
* #inverse
* #inv
* **

Matrix functions:
* #determinant
* #det
* #rank
* #trace
* #tr
* #transpose
* #t

Conversion to other data types:
* #coerce(other)
* #row_vectors
* #column_vectors
* #to_a

String representations:
* #to_s
* #inspect
------------------------------------------------------------------------------
= CCllaassss  mmeetthhooddss::

  I
  
  column_vector
  columns
  diagonal
  identity
  new
  row_vector
  rows
  scalar
  unit
  zero

= IInnssttaannccee  mmeetthhooddss::

  *
  **
  +
  -
  /
  ==
  
  clone
  coerce
  collect
  column
  column_size
  column_vectors
  compare_by_row_vectors
  det
  determinant
  eql?
  hash
  init_rows
  inspect
  inv
  inverse
  inverse_from
  map
  minor
  rank
  regular?
  row
  row_size
  row_vectors
  singular?
  square?
  t
  to_a
  to_s
  tr
  trace
  transpose

Sometime ago, there was a Google Summer of Code project to port NArray to OpenCL

There is also this project http://ruby-opencl.rubyforge.org/, if you
want to try multicore acceleration
(as a means to speed up your code) with OpenCL. It should work with
multicore cpus as well as GPUs

saji

···

On Sun, Sep 9, 2012 at 1:06 AM, Olivier Saut <osaut@airpost.net> wrote:

Hi all,

For pedagogic purposes, I am trying to solve simple partial differential
equations (say a diffusion equation on a regular mesh in 2D) with Ruby.
Using the NArray gem, I have built a satisfactory tool from an interface
(and ease of use) point of view but the performance are suboptimal.

I am now wondering what is the right way to improve my code
performance-wise. I am doing a lot of matrix-vector and vector-vector
products.

--

Saji N Hameed,
ARC-ENV, Center for Advanced Information Science and Technology,
University of Aizu, Tsuruga, Ikki-machi,
Aizuwakamatsu-shi, Fukushima 965-8580,
Japan

Tel: +81242 37-2736
Fax:+81242 37-2760
email: saji@u-aizu.ac.jp
url: http://www.u-aizu.ac.jp
bib: Web of Science

Hello,

Hi all,

For pedagogic purposes, I am trying to solve simple partial differential
equations (say a diffusion equation on a regular mesh in 2D) with Ruby.
Using the NArray gem, I have built a satisfactory tool from an interface
(and ease of use) point of view but the performance are suboptimal.

Is the code available on a public repo?

Not yet, but I plan to share it as soon as I am convinced it is usable for my students.

I am now wondering what is the right way to improve my code
performance-wise. I am doing a lot of matrix-vector and vector-vector
products.

From 2 2D NArrays describing two scalar fields, dot-product is implemented as :

def dot_product(vec_a, vec_b)
      dot_product=(vec_a*vec_b">vec_a*vec_b).sum
end

The definition above is wrong, the right ones

def dot_product(vec_a, vec_b)
  (vec_a*vec_b).sum
end

and as I am working with sparse matrices, (for the time being) a matrix
is an Array of Hashes. Each key of the hash contains the index of the
non-vanishing coefficients (the value of this coefficient is the value
of the Hash) of the matrix. For the identity matrix it gives

def identity(sizeX, sizeY)
      mat=
      (0..sizeX*sizeY">sizeX*sizeY).each { |ind|
          mat << {ind=>1.0}
      }
      mat
end

Matrix vector product is then defined as

def matrix_vector_product(mat, vector)
      ff=NArray.float(100,100)
      (0..100*100).each { |ind|
          matrix[ind].each do |key,value|
              ff[[ind]]+=value*vector[[key]][0]
          end
      }
      ff
end

I am wondering what is the best way to tackle this performance problem :
1. Improve the ruby code (and how? :slight_smile: Should I avoid using hashes?
2. Write an extension to perform these operations in C. BTW is there a
way to access directly NArray data (without copy) from a C extension?
3. Use a wrapper like Ruby-lapack
(
https://rubyforge.org/projects/ruby-lapack/
).

What do you think?

Thanks for your help !

Best regards,
                                       - Olivier

···

Le 8 sept. 2012 à 19:39, Panagiotis Atmatzidis <ml@convalesco.org> a écrit :

On 8 Σεπ 2012, at 18:06 , Olivier Saut <osaut@airpost.net> wrote:

Thanks for your answer !
I also really like Ruby and would prefer to avoid switching to Python.

I'll have a look at octave-ruby. I have also found a project http://sciruby.com that seems to be interesting. I am not sure how far it has improved the situation for ruby in scientific computing though.

Best regards,

···

Le 8 sept. 2012 à 20:26, Admin Tensor <lists@ruby-forum.com> a écrit :

Olivier Saut wrote in post #1075138:

Hi all,

For pedagogic purposes, I am trying to solve simple partial differential
equations (say a diffusion equation on a regular mesh in 2D) with Ruby.
Using the NArray gem, I have built a satisfactory tool from an interface
(and ease of use) point of view but the performance are suboptimal.

.......

I am wondering what is the best way to tackle this performance problem :
1. Improve the ruby code (and how? :slight_smile: Should I avoid using hashes?
2. Write an extension to perform these operations in C. BTW is there a
way to access directly NArray data (without copy) from a C extension?
3. Use a wrapper like Ruby-lapack
(
https://rubyforge.org/projects/ruby-lapack/
).

What do you think?

Thanks for your help !

Hi,

Because it seems that you emphasize on performance, I think the best way
is to use GNU Octave for dealing with the sparse matrices. There is a
Ruby gem (octave-ruby) to bridge between Ruby and Octave objects.

I really like Ruby, but for scientific computing I think for now Python
has better libraries.

Regards,

Bill

--
Posted via http://www.ruby-forum.com/\.

                                       - Olivier

Hi all,

For pedagogic purposes, I am trying to solve simple partial differential
equations (say a diffusion equation on a regular mesh in 2D) with Ruby.
Using the NArray gem, I have built a satisfactory tool from an interface
(and ease of use) point of view but the performance are suboptimal.

Have you taken a look at std lib's matrix.rb?

No, I'll check it. In particular there is a LU decomposition method implemented which could help me a lot.

Thanks,

= MMaattrriixx  <<  OObbjjeecctt

(from ruby core)
------------------------------------------------------------------------------
The Matrix class represents a mathematical matrix, and provides methods for
creating special-case matrices (zero, identity, diagonal, singular, vector),
operating on them arithmetically and algebraically, and determining their
mathematical properties (trace, rank, inverse, determinant).

Note that although matrices should theoretically be rectangular, this is not
enforced by the class.

Also note that the determinant of integer matrices may be incorrectly
calculated unless you also require 'mathn'. This may be fixed in the future.

== MMeetthhoodd  CCaattaalloogguuee

To create a matrix:
* Matrix[*rows]
* Matrix.(*rows)
* Matrix.rows(rows, copy = true)
* Matrix.columns(columns)
* Matrix.diagonal(*values)
* Matrix.scalar(n, value)
* Matrix.scalar(n, value)
* Matrix.identity(n)
* Matrix.unit(n)
* Matrix.I(n)
* Matrix.zero(n)
* Matrix.row_vector(row)
* Matrix.column_vector(column)

To access Matrix elements/columns/rows/submatrices/properties:
* (i, j)
* #row_size
* #column_size
* #row(i)
* #column(j)
* #collect
* #map
* #minor(*param)

Properties of a matrix:
* #regular?
* #singular?
* #square?

Matrix arithmetic:
* *(m)
* +(m)
* -(m)
* #/(m)
* #inverse
* #inv
* **

Matrix functions:
* #determinant
* #det
* #rank
* #trace
* #tr
* #transpose
* #t

Conversion to other data types:
* #coerce(other)
* #row_vectors
* #column_vectors
* #to_a

String representations:
* #to_s
* #inspect
------------------------------------------------------------------------------
= CCllaassss  mmeetthhooddss::

I

column_vector
columns
diagonal
identity
new
row_vector
rows
scalar
unit
zero

= IInnssttaannccee  mmeetthhooddss::

*
**
+
-
/


clone
coerce
collect
column
column_size
column_vectors
compare_by_row_vectors
det
determinant
eql?
hash
init_rows
inspect
inv
inverse
inverse_from
map
minor
rank
regular?
row
row_size
row_vectors
singular?
square?
t
to_a
to_s
tr
trace
transpose

                                       - Olivier

···

Le 8 sept. 2012 à 23:31, Ryan Davis <ryand-ruby@zenspider.com> a écrit :

On Sep 8, 2012, at 09:06 , Olivier Saut <osaut@airpost.net> wrote:

Hi,

I had not thought of using Open CL. I'll check it. The last commits to the project dates back to two years ago.

Thanks !

···

Le 9 sept. 2012 à 08:06, Saji Hameed <saji@u-aizu.ac.jp> a écrit :

On Sun, Sep 9, 2012 at 1:06 AM, Olivier Saut <osaut@airpost.net> wrote:

Hi all,

For pedagogic purposes, I am trying to solve simple partial differential
equations (say a diffusion equation on a regular mesh in 2D) with Ruby.
Using the NArray gem, I have built a satisfactory tool from an interface
(and ease of use) point of view but the performance are suboptimal.

I am now wondering what is the right way to improve my code
performance-wise. I am doing a lot of matrix-vector and vector-vector
products.

Sometime ago, there was a Google Summer of Code project to port NArray to OpenCL
第5回SCDN - Ruby Summer of Code: NArray on OpenCL | PPT
GitHub - kazuyukitanimura/narray: Ruby/NArray : N-dimensional Numerical Array for Ruby

There is also this project http://ruby-opencl.rubyforge.org/, if you
want to try multicore acceleration
(as a means to speed up your code) with OpenCL. It should work with
multicore cpus as well as GPUs

saji
--

Saji N Hameed,
ARC-ENV, Center for Advanced Information Science and Technology,
University of Aizu, Tsuruga, Ikki-machi,
Aizuwakamatsu-shi, Fukushima 965-8580,
Japan

Tel: +81242 37-2736
Fax:+81242 37-2760
email: saji@u-aizu.ac.jp
url: http://www.u-aizu.ac.jp
bib: Web of Science

                                       - Olivier

Olivier Saut wrote in post #1075180:

Thanks for your answer !
I also really like Ruby and would prefer to avoid switching to Python.

I'll have a look at octave-ruby. I have also found a project
http://sciruby.com that seems to be interesting. I am not sure how far
it has improved the situation for ruby in scientific computing though.

Hi,

Thanks for your pointer to sciruby. I think it will take them some time
to make it usable for serious scientific computation (especially sparse
matrices) and even longer to make it comparable to Python's NumPy.

I also tried it once by writing RTensor on Windows
(http://tensor.heliohost.org/rtensor/\) but it takes too much work and
time. I think using Octave is the current practical solution, and I
think if we want to contribute to Ruby community, it is by finding a way
to easily integrate Octave and Ruby (beyond octave-ruby).

Regards,

Bill

···

--
Posted via http://www.ruby-forum.com/\.