ruby-numo / numo-narray

Ruby/Numo::NArray - New NArray class library
http://ruby-numo.github.io/narray/
BSD 3-Clause "New" or "Revised" License
418 stars 42 forks source link

# Dot product between two 2d NArray matrices, one single-row and one single-column, is not correct. A strange warning is printed though no Error is raised. #86

Closed giuse closed 6 years ago

giuse commented 6 years ago

Dot product between two 2d NArray matrices, one single-row and one single-column, is not correct. A strange warning is printed though no Error is raised.

a = Numo::DFloat.new(1,3).seq # => Numo::DFloat#shape=[1,3]  [[0, 1, 2]]
b = Numo::DFloat.new(3,1).seq # => Numo::DFloat#shape=[3,1]  [[0], [1], [2]]
a.dot(b)
# => ** On entry to DGEMM  parameter number 13 had an illegal value
# => Numo::DFloat#shape=[1,1]  [[0]]
# Expected: Numo::DFloat#shape=[1,1] [[5]]
Try2Code commented 6 years ago

the built-in tests cover "dot". do you get the same error running them?

masa16 commented 6 years ago

If numo-linalg is loaded, NArray#dot uses Linalg.dot method. Otherwise it uses NArray#mulsum method. This seems a bug in Blas.dgemm.

Try2Code commented 6 years ago

I dont get the error on my system (archlinux, ruby-2.5, numo-narray (226e3ee), numo-linalg (c0ac1ad)

giuse commented 6 years ago

I conferm numo-linalg is loaded. Did not consider that, apologies. Here's an updated example tested on a clean console:

require 'numo/narray'
# => true
a = Numo::DFloat.new(1,3).seq
# => Numo::DFloat#shape=[1,3]  [[0, 1, 2]]
b = Numo::DFloat.new(3,1).seq
# => Numo::DFloat#shape=[3,1]  [[0], [1], [2]]
a.dot(b)
# => Numo::DFloat#shape=[1,1]  [[5]]
require 'numo/linalg'
# => true
a.dot(b)
# ** On entry to DGEMM  parameter number 13 had an illegal value
# => Numo::DFloat#shape=[1,1]  [[0]]

EDIT Here's my configuration:

giuse@free:~$ gem list numo*
numo-linalg (0.1.1)
numo-narray (0.9.1.1)
giuse@free:~$ uname -a
Linux free 4.13.0-37-generic #42~16.04.1-Ubuntu SMP Wed Mar 7 16:03:28 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
giuse@free:~$ rvm list
=* ruby-2.4.2 [ x86_64 ]
Try2Code commented 6 years ago

I get a load error

Numo::DFloat#shape=[1,1]
[[5]]
Traceback (most recent call last):
    5: from testDot.rb:9:in `<main>'
    4: from /usr/lib/ruby/site_ruby/2.5.0/rubygems/core_ext/kernel_require.rb:39:in `require'
    3: from /usr/lib/ruby/site_ruby/2.5.0/rubygems/core_ext/kernel_require.rb:135:in `rescue in require'
    2: from /usr/lib/ruby/site_ruby/2.5.0/rubygems/core_ext/kernel_require.rb:135:in `require'
    1: from /home/ram/.gem/ruby/2.5.0/gems/numo-linalg-0.1.1/lib/numo/linalg.rb:3:in `<top (required)>'
/home/ram/.gem/ruby/2.5.0/gems/numo-linalg-0.1.1/lib/numo/linalg/loader.rb:176:in `load_library': cannot find backend library for Numo::Linalg (RuntimeError)

when running

require 'numo/narray'

a = Numo::DFloat.new(1,3).seq

b = Numo::DFloat.new(3,1).seq

pp a.dot(b)

require 'numo/linalg'

pp a.dot(b)

ruby 2.5.0p0 (2017-12-25 revision 61468)

the numo-narray tests run (rake test)

Try2Code commented 6 years ago

I fixed that - I had installed a blas library, but linalg needs lapack. With C-interface to lapack, I get the message @giuse reported.

giuse commented 6 years ago

If numo-linalg is loaded, NArray#dot uses Linalg.dot method. Otherwise it uses NArray#mulsum method. This seems a bug in Blas.dgemm.

A Google search for Blad.dgemm yielded multiple correspondences. Where can we correctly direct/file the issue? Also, would switching library avoid this? I am currently on OpenBLAS.

In the meanwhile I did this (UPDATE: this is wrong, see below):

class Numo::DFloat
  alias dot mulsum
end

Which is clearly not optimal since #dot is defined on Numo::NArray while #mulsum is defined on its typed subclasses (hence my reference to Numo::DFloat). Any advice?

giuse commented 6 years ago

Update: the alias above is clearly not correct.

require 'numo/narray'
# => true
a = Numo::DFloat.new(1,3).seq
# => Numo::DFloat#shape=[1,3]  [[0, 1, 2]]
b = Numo::DFloat.new(3,1).seq
# => Numo::DFloat#shape=[3,1]  [[0], [1], [2]]
a.dot(b)
# => Numo::DFloat#shape=[1,1]  [[5]]
a.mulsum(b)
# => 9.0

Can the original Numo::NArray#dot method be accessed after require 'numo/linalg'? I guess I will alias it out before loading Linalg and setting it back after for now.

masa16 commented 6 years ago

I have identified the reason of dgemm bug and it will be fixed.

NArray#dot is defined as: https://github.com/ruby-numo/numo-narray/blob/master/lib/numo/narray/extra.rb#L1081-L1116

NArray#mulsum is inferior to BLAS implementation, so it should be replaced if BLAS is available.

giuse commented 6 years ago

Oh thank you so much Tanaka-san! You are right, I am indeed looking forward for the fix. Also, I see now why I was having so much trouble with aliasing :) I will work around it by making false the if defined?(Linalg) conditional in the downloaded gem.

masa16 commented 6 years ago

Fixed a bug in numo-narray and released ver. 0.9.1.2.

giuse commented 6 years ago

I confirm this is now fixed in 0.9.1.2

require 'numo/narray'
# => true
a = Numo::DFloat.new(1,3).seq
# => Numo::DFloat#shape=[1,3]  [[0, 1, 2]]
b = Numo::DFloat.new(3,1).seq
# => Numo::DFloat#shape=[3,1]  [[0], [1], [2]]
a.dot(b)
# => Numo::DFloat#shape=[1,1]  [[5]]
require 'numo/linalg'
# => true
a.dot(b)
# => Numo::DFloat#shape=[1,1]  [[5]]
Numo::Linalg.dot(a,b)
# => Numo::DFloat#shape=[1,1]  [[5]]

Thanks a lot!