Re: GSoC 2012 Proposal: Continued Work on a D Linear Algebra library (SciD - std.linalg)

2012-04-24 Thread Jens Mueller
Cristi Cobzarenco wrote:
 Unfortunately, my proposal was not picked up this year. I might try to work
 on these ideas this summer anyway so I would still be very much interested
 in ideas and feedback, but I will probably have much less time if I'll be
 working somewhere else.

I'm less familiar with your SciD code base but I have used Eigen
regularly. Maybe you can answer my questions right away:
1. How are expression evaluated? Eigen uses no BLAS backend. All
   code is generated by themselves.
   Do you plan for such an option?
2. What is your goal for SciD? Do you want to have an Eigen in D? Are
   there places where a D solution may improved over the Eigen?
3. I'm not so sure about the array() stuff. I never liked in Eigen.
   Being able to call std.algorithm on the raw memory may be sufficient
   for the time being.
4. How about a sparse storage backend for sparse matrices? I'm missing
   sparse matrices in Eigen even though the situation is improving but
   they're not fully integrated yet.

I'd like to support your efforts for including your work in Phobos. How
about you clone Phobos and gradually move your work into a work in
progress branch? Really little steps. This allows me to follow you
closely. To familiarize myself with the code and I would then fill in
unittest, documentation and benchmarking code where missing as we go.

Jens

PS
It's great to hear that you plan for including your work in Phobos.


Re: GSoC 2012 Proposal: Continued Work on a D Linear Algebra library (SciD - std.linalg)

2012-04-24 Thread Cristi Cobzarenco
On 24 April 2012 08:32, Jens Mueller jens.k.muel...@gmx.de wrote:

 Cristi Cobzarenco wrote:
  Unfortunately, my proposal was not picked up this year. I might try to
 work
  on these ideas this summer anyway so I would still be very much
 interested
  in ideas and feedback, but I will probably have much less time if I'll be
  working somewhere else.

 I'm less familiar with your SciD code base but I have used Eigen
 regularly. Maybe you can answer my questions right away:
 1. How are expression evaluated? Eigen uses no BLAS backend. All
   code is generated by themselves.
   Do you plan for such an option?


The expressions are built in a similar way to how they are in Eigen (any
many other linear algebra libraries), using expression templates that
build, essentially, abstract syntax trees which get evaluated on assignment
(or with the eval() function). The back-end for evaluation can be specified
using a version flag. Specifying version=nodeps results in code being
generated by the library with no external dependencies - this is much
slower, as it doesn't use SIMD operations or anything of the sort.

In the current state of the library, this is done by essentially providing
naive implementations of the BLAS functions. In the revamped version, I
plan this to be done in slightly different way (more similar to the way
Eigen works) which removes the need for temporaries in some cases where
using BLAS/LAPACK makes temporary allocation inevitable. In the immediate
future I do not plan to include SIMD operations for the version=nodeps
version and the library will be the most efficient when using BLAS  LAPACK.


 2. What is your goal for SciD? Do you want to have an Eigen in D? Are
   there places where a D solution may improved over the Eigen?


These are really two questions:
 2.1. What is your goal for SciD? Do you want to have an Eigen in D?

Short anwer: no. We already have a working library, it's mostly the
interface that's getting a face-lift. Some of the design decisions we made
early on (such as support for views) and compiler bugs (such as a clash
between templated opAssign and postblit constructor) forced us to make some
unfortunate interface decisions. In the long run it became obvious that
views are pretty much useless and a lot of the compiler bugs that were
hindering progress were fixed - so I thought I would improve the library's
interface.

The more I worked on it, the more obvious it became I was converging onto
Eigen's interface, with bits from MATLAB.

 2.2. Are there places where a D solution may improved over the Eigen?

I'm not entirely sure. There's the obvious stuff like more natural slicing
syntax which D allows us to do.  Easily swappable backends is another thing
- I'm writing everything to allow custom backends for the matrices (the
backend will be a template parameter in the new version). This would in
theory, allow GPU matrices to be easily written if anyone
wanted (particularly if someone wrapped something like CUBLAS).

I am actually very interested in hearing from other people if they think
there's stuff which we could do better thanks to D.


 3. I'm not so sure about the array() stuff. I never liked in Eigen.
   Being able to call std.algorithm on the raw memory may be sufficient
   for the time being.


I am starting to lean against array myself. I wanted mostly to allow for
arbitrary typed, higher-dimensional matrices with element-wise operations.
But having worked a bit on the changes already, I realised that it's very
easy to disallow certain matrix operations on types which do not support
multiplication for example. Also I think I found an elegant way of
supporting higher-dimensional matrices using the same type, but I have to
do a bit more research into that.

In terms of running std.algorihtm on raw memory, that is and will be
possible. Matrices provide two properties .data and .cdata, which provide a
pointer to the raw memory (.cdata provides a constant one which may point
to memory shared by multiple matrices, while .data makes sure the memory is
unique).


 4. How about a sparse storage backend for sparse matrices? I'm missing
   sparse matrices in Eigen even though the situation is improving but
   they're not fully integrated yet.


Definitely. Sparse storage is a long term goal for the library, but not in
the first iteration.



 I'd like to support your efforts for including your work in Phobos. How
 about you clone Phobos and gradually move your work into a work in
 progress branch? Really little steps. This allows me to follow you
 closely. To familiarize myself with the code and I would then fill in
 unittest, documentation and benchmarking code where missing as we go.


That is actually a better idea than what I had in mind. I will do that. I
am really glad you're interested in the project, but unfortunately I won't
be able to start work on the library until the beginning of June. Also the
proposal for the project was meant as my full-time job this summer, 

Re: GSoC 2012 Proposal: Continued Work on a D Linear Algebra library (SciD - std.linalg)

2012-04-24 Thread Jens Mueller
Cristi Cobzarenco wrote:
 On 24 April 2012 08:32, Jens Mueller jens.k.muel...@gmx.de wrote:
 
  Cristi Cobzarenco wrote:
   Unfortunately, my proposal was not picked up this year. I might try to
  work
   on these ideas this summer anyway so I would still be very much
  interested
   in ideas and feedback, but I will probably have much less time if I'll be
   working somewhere else.
 
  I'm less familiar with your SciD code base but I have used Eigen
  regularly. Maybe you can answer my questions right away:
  1. How are expression evaluated? Eigen uses no BLAS backend. All
code is generated by themselves.
Do you plan for such an option?
 
 
 The expressions are built in a similar way to how they are in Eigen (any
 many other linear algebra libraries), using expression templates that
 build, essentially, abstract syntax trees which get evaluated on assignment
 (or with the eval() function). The back-end for evaluation can be specified
 using a version flag. Specifying version=nodeps results in code being
 generated by the library with no external dependencies - this is much
 slower, as it doesn't use SIMD operations or anything of the sort.
 
 In the current state of the library, this is done by essentially providing
 naive implementations of the BLAS functions. In the revamped version, I
 plan this to be done in slightly different way (more similar to the way
 Eigen works) which removes the need for temporaries in some cases where
 using BLAS/LAPACK makes temporary allocation inevitable. In the immediate
 future I do not plan to include SIMD operations for the version=nodeps
 version and the library will be the most efficient when using BLAS  LAPACK.

I see. That means you have already an expression evaluator. I still
wonder why a[] = b[] + c[] shouldn't be handled completely by the
compiler. I thought that this is sufficient for the compiler for
vectorization.

snip

  2.2. Are there places where a D solution may improved over the Eigen?
 
 I'm not entirely sure. There's the obvious stuff like more natural slicing
 syntax which D allows us to do.  Easily swappable backends is another thing
 - I'm writing everything to allow custom backends for the matrices (the
 backend will be a template parameter in the new version). This would in
 theory, allow GPU matrices to be easily written if anyone
 wanted (particularly if someone wrapped something like CUBLAS).

Sounds interesting.

 I am actually very interested in hearing from other people if they think
 there's stuff which we could do better thanks to D.
 
 
  3. I'm not so sure about the array() stuff. I never liked in Eigen.
Being able to call std.algorithm on the raw memory may be sufficient
for the time being.
 
 
 I am starting to lean against array myself. I wanted mostly to allow for
 arbitrary typed, higher-dimensional matrices with element-wise operations.
 But having worked a bit on the changes already, I realised that it's very
 easy to disallow certain matrix operations on types which do not support
 multiplication for example. Also I think I found an elegant way of
 supporting higher-dimensional matrices using the same type, but I have to
 do a bit more research into that.

Nice.

  4. How about a sparse storage backend for sparse matrices? I'm missing
sparse matrices in Eigen even though the situation is improving but
they're not fully integrated yet.
 
 
 Definitely. Sparse storage is a long term goal for the library, but not in
 the first iteration.

Don't want it in the first iteration. Just want to make sure that
current design allows a straightforward extension in that direction.

  I'd like to support your efforts for including your work in Phobos. How
  about you clone Phobos and gradually move your work into a work in
  progress branch? Really little steps. This allows me to follow you
  closely. To familiarize myself with the code and I would then fill in
  unittest, documentation and benchmarking code where missing as we go.
 
 
 That is actually a better idea than what I had in mind. I will do that. I
 am really glad you're interested in the project, but unfortunately I won't
 be able to start work on the library until the beginning of June. Also the
 proposal for the project was meant as my full-time job this summer, but
 since I'll probably be working somewhere else now you should take into
 account that I probably won't be able to stick to the schedule I gave in
 the proposal.

Take your time. I need to familiarize myself with the code anyway.

Jens


Re: GSoC 2012 Proposal: Continued Work on a D Linear Algebra library (SciD - std.linalg)

2012-04-23 Thread Cristi Cobzarenco
Unfortunately, my proposal was not picked up this year. I might try to work
on these ideas this summer anyway so I would still be very much interested
in ideas and feedback, but I will probably have much less time if I'll be
working somewhere else.

---
Cristi Cobzarenco
BSc in Artificial Intelligence and Computer Science
University of Edinburgh
Profile: http://www.google.com/profiles/cristi.cobzarenco



On 10 April 2012 12:31, Cristi Cobzarenco cristi.cobzare...@gmail.comwrote:

 Timon is, of course, right. I got a bit confused when trying to simplify
 in a hurry. What I meant was actually something like this:

 ops.d:
 import std.stdio;

 int sum( T )( T mat ){
  writeln(ops.sum);
 // return reduce!a+b( 0, mat );
  return 1;
 }

 int numelems( T )( T mat ) {
 // return mat.rows * mat.columns;
  return 1;
 }

 int mean( T )( T mat ) {
 return sum( mat ) / numelems( mat );
 }

 diagonal.d:
 import ops;
 import std.stdio;

 struct DiagonalMatrix {
  }

 int sum( T : DiagonalMatrix )( T mat ) {
 writeln( diagonal.sum );
 // return reduce!a+b( 0, mat.diagonal() );
  return 1;
 }

 main.d:
 import ops;
 import diagonal;

 void main() {
  DiagonalMatrix mat;
 sum( mat );   // this will not compile, but if removed mean
  mean( mat ); // will use ops.sum, not diagonal.sum anyway
 }

 The first problem could, in theory, be fixed using a member flag,
 something like enum specializedSum = true; and ops.sum could be redefined
 as: int sum( T )( T mat ) if( !T.specializedSum ) {}. But in this case
 mean() would still try to use  ops.sum which will fail. All of this can be
 easily fixed by providing member functions, and having the free functions
 call the member ones when they exist.

 ---
 Cristi Cobzarenco
 BSc in Artificial Intelligence and Computer Science
 University of Edinburgh
 Profile: http://www.google.com/profiles/cristi.cobzarenco



 On 10 April 2012 10:35, Timon Gehr timon.g...@gmx.ch wrote:

 On 04/10/2012 03:24 AM, Cristi Cobzarenco wrote:

 Thanks for the suggestions!

 I don't think UFCS would help us. Our problem is that we can't do this:
 triangular.d:
   struct TriangularMatrix {

   }

   void sum( T )( T x ) if( is( T : TriangularMatrix ) ) {

   }

 diagonal.d:
   struct DiagonalMatrix {

   }

   void sum( T )( T x ) if( is( T : DiagonalMatrix ) ) {
   }

 main.d:
 import diagonal;
 import triangular;

 void bar() {
TriangularMatrix a;
Diagonal b;
sum( a );  // this does not compile because sum() is ambiguous
sum( b );  // nor does this
 }


 There are no ambiguities in that example, and if ambiguities occur, they
 can always be fixed manually.


 This, AFAIK, is deliberate to avoid name hijacking - ADL in C++ had its
 share of criticism. I doubt we will ever get this behaviour in D and
 that is perhaps a good thing. I may have misunderstood UFCS though - or
 what you meant by making non-member function calls look nicer - please
 correct me if that's the case.

 Don't worry about long names, t() is already the way transposition is
 defined SciD. Moreover, it's a property so you can actually do a.t * a
 - convenience galore. I'm also considering of creating a submodule like
 std.linalg.short which defines aliases with short names for types and
 free functions - this will allow particularly numerics-heavy functions
 to be written more compactly. I'm not entirely sure it would be a good
 idea though as it may sacrifice readability where it's most needed.

 ---
 Cristi Cobzarenco
 BSc in Artificial Intelligence and Computer Science
 University of Edinburgh
 Profile: 
 http://www.google.com/**profiles/cristi.cobzarencohttp://www.google.com/profiles/cristi.cobzarenco


 If you change 'Diagonal' to 'DiagonalMatrix', this compiles fine.





Re: GSoC 2012 Proposal: Continued Work on a D Linear Algebra library (SciD - std.linalg)

2012-04-10 Thread Timon Gehr

On 04/10/2012 03:24 AM, Cristi Cobzarenco wrote:

Thanks for the suggestions!

I don't think UFCS would help us. Our problem is that we can't do this:
triangular.d:
   struct TriangularMatrix {

   }

   void sum( T )( T x ) if( is( T : TriangularMatrix ) ) {

   }

diagonal.d:
   struct DiagonalMatrix {

   }

   void sum( T )( T x ) if( is( T : DiagonalMatrix ) ) {
   }

main.d:
import diagonal;
import triangular;

void bar() {
TriangularMatrix a;
Diagonal b;
sum( a );  // this does not compile because sum() is ambiguous
sum( b );  // nor does this
}


There are no ambiguities in that example, and if ambiguities occur, they 
can always be fixed manually.




This, AFAIK, is deliberate to avoid name hijacking - ADL in C++ had its
share of criticism. I doubt we will ever get this behaviour in D and
that is perhaps a good thing. I may have misunderstood UFCS though - or
what you meant by making non-member function calls look nicer - please
correct me if that's the case.

Don't worry about long names, t() is already the way transposition is
defined SciD. Moreover, it's a property so you can actually do a.t * a
- convenience galore. I'm also considering of creating a submodule like
std.linalg.short which defines aliases with short names for types and
free functions - this will allow particularly numerics-heavy functions
to be written more compactly. I'm not entirely sure it would be a good
idea though as it may sacrifice readability where it's most needed.

---
Cristi Cobzarenco
BSc in Artificial Intelligence and Computer Science
University of Edinburgh
Profile: http://www.google.com/profiles/cristi.cobzarenco



If you change 'Diagonal' to 'DiagonalMatrix', this compiles fine.



Re: GSoC 2012 Proposal: Continued Work on a D Linear Algebra library (SciD - std.linalg)

2012-04-10 Thread Cristi Cobzarenco
Timon is, of course, right. I got a bit confused when trying to simplify in
a hurry. What I meant was actually something like this:

ops.d:
import std.stdio;

int sum( T )( T mat ){
 writeln(ops.sum);
// return reduce!a+b( 0, mat );
 return 1;
}

int numelems( T )( T mat ) {
// return mat.rows * mat.columns;
 return 1;
}

int mean( T )( T mat ) {
return sum( mat ) / numelems( mat );
}

diagonal.d:
import ops;
import std.stdio;

struct DiagonalMatrix {
 }

int sum( T : DiagonalMatrix )( T mat ) {
writeln( diagonal.sum );
// return reduce!a+b( 0, mat.diagonal() );
 return 1;
}

main.d:
import ops;
import diagonal;

void main() {
 DiagonalMatrix mat;
sum( mat );   // this will not compile, but if removed mean
 mean( mat ); // will use ops.sum, not diagonal.sum anyway
}

The first problem could, in theory, be fixed using a member flag, something
like enum specializedSum = true; and ops.sum could be redefined as: int
sum( T )( T mat ) if( !T.specializedSum ) {}. But in this case mean() would
still try to use  ops.sum which will fail. All of this can be easily fixed
by providing member functions, and having the free functions call the
member ones when they exist.

---
Cristi Cobzarenco
BSc in Artificial Intelligence and Computer Science
University of Edinburgh
Profile: http://www.google.com/profiles/cristi.cobzarenco



On 10 April 2012 10:35, Timon Gehr timon.g...@gmx.ch wrote:

 On 04/10/2012 03:24 AM, Cristi Cobzarenco wrote:

 Thanks for the suggestions!

 I don't think UFCS would help us. Our problem is that we can't do this:
 triangular.d:
   struct TriangularMatrix {

   }

   void sum( T )( T x ) if( is( T : TriangularMatrix ) ) {

   }

 diagonal.d:
   struct DiagonalMatrix {

   }

   void sum( T )( T x ) if( is( T : DiagonalMatrix ) ) {
   }

 main.d:
 import diagonal;
 import triangular;

 void bar() {
TriangularMatrix a;
Diagonal b;
sum( a );  // this does not compile because sum() is ambiguous
sum( b );  // nor does this
 }


 There are no ambiguities in that example, and if ambiguities occur, they
 can always be fixed manually.


 This, AFAIK, is deliberate to avoid name hijacking - ADL in C++ had its
 share of criticism. I doubt we will ever get this behaviour in D and
 that is perhaps a good thing. I may have misunderstood UFCS though - or
 what you meant by making non-member function calls look nicer - please
 correct me if that's the case.

 Don't worry about long names, t() is already the way transposition is
 defined SciD. Moreover, it's a property so you can actually do a.t * a
 - convenience galore. I'm also considering of creating a submodule like
 std.linalg.short which defines aliases with short names for types and
 free functions - this will allow particularly numerics-heavy functions
 to be written more compactly. I'm not entirely sure it would be a good
 idea though as it may sacrifice readability where it's most needed.

 ---
 Cristi Cobzarenco
 BSc in Artificial Intelligence and Computer Science
 University of Edinburgh
 Profile: 
 http://www.google.com/**profiles/cristi.cobzarencohttp://www.google.com/profiles/cristi.cobzarenco


 If you change 'Diagonal' to 'DiagonalMatrix', this compiles fine.




Re: GSoC 2012 Proposal: Continued Work on a D Linear Algebra library (SciD - std.linalg)

2012-04-09 Thread Michael Chen
Hi, Cristi,
From change log of D 2.059. I saw that uniform function call syntax
was implemented. I hope you can leverage this feature to make non
member function calls look nicer. Another suggestion, please use
shorter function name for example M.t() instead of M.transpose() so
that long expression is easy to read.

Best,
Mo

On Mon, Apr 9, 2012 at 6:52 AM, Cristi Cobzarenco
cristi.cobzare...@gmail.com wrote:
 On 8 April 2012 18:59, Caligo iteronve...@gmail.com wrote:

 On Tue, Apr 3, 2012 at 6:20 AM, Cristi Cobzarenco
 cristi.cobzare...@gmail.com wrote:
 
  The point of these is to have light-weight element wise operation
  support.
  It's true that in theory the built-in arrays do this. However, this
  library
  is built on top BLAS/LAPACK, which means operations on large matrices
  will
  be faster than on D arrays.
 

 I can't agree with building it on top of LAPACK or any other BLAS
 implementation, but perhaps I shouldn't complain because I'm not the
 one who's going to be implementing it.  I like the approach Eigen has
 taken where it offers its own BLAS implementation and, iirc, other
 BLAS libraries can be used as optional back-ends.


 Yes, I agree with you. I already built naive implementations for BLAS 
 LAPACK functions as part of my last year project, using external libraries
 is optional (building with version=nodeps ensures absolutely no dependencies
 are needed). The argument still stands, though. If you _do_ use external
 BLAS libraries then using value arrays will _still_ be faster.



  Also, as far as I know, D doesn't support
  allocating dynamic 2-D arrays (as in not arrays of arrays), not to
  mention
  2-D slicing (keeping track of leading dimension).
 

 I fail to see why there is any need for 2D arrays.  We need to make
 sure multidimensional arrays (matrices) have data in very good
 arrangements.  This is called tiling and it requires 1D arrays:  2D
 arrays are stored as 1D arrays together with an indexing mechanism.


 That is precisely what I meant. We need wrappers around D arrays, because
 they, by themselves, do not support 2-D indexing. By providing a wrapper we
 allow the nice syntax of matrix[ a, b ]. This kind of wrapping is already in
 SciD by CowMatrix. I meant we shouldn't use D built-in arrays directly, not
 not at all. Also, as mentioned before, we can't use new for allocation,
 because we want the library to be GC-independent.


  Also I'm not sure how a case like this will be compiled, it may or may
  not
  allocate a temporary:
 
  a[] = b[] * c[] + d[] * 2.0;
 
  The expression templates in SciD mean there will be no temporary
  allocation
  in this call.
 

 Why are expression templates used?


 As H. S. Teoh rightfully pointed out, it is important not to allocate
 temporaries in matrix operations. You want to evaluate A = B * 3.0 + D * 2.0
 (where .* is element-wise multiplication) as (in BLAS terms):
   copy( B, A );
   scal( 3.0, A );
   axpy( D, 2.0, A );

 Or with naive expression template evaluation:
   for( i = 0 ; i  n ; ++ i ) {
      A[ i ] = B[ i ] * 3.0 + D * 2.0;
   }

 The D compiler would instead evaluate this as:
   // allocate temporaries
   allocate( tmp1, A.length );
   allocate( tmp2, A.length );
   allocate( tmp3, A.length );

   // compute tmp1 = B * 3.0
   copy( B, tmp1 );
   scal( 3.0, tmp1 );

   // compute tmp2 = D * 2.0;
   copy( D, tmp2 );
   scal( 2.0, tmp2 );

   // compute tmp3 = tmp1 + tmp2;
   copy( tmp1, tmp3 );
   axpy( tmp2, 1.0, tmp1 );

   // copy tmp3 into A
   copy( tmp3, A );

 Plenty of useless computation. Note this is not a fault of the compiler, it
 has no way of knowing which temporaries can be optimised away for user types
 (i.e. our matrices).

 Are you pretty much rewriting Eigen in D?

 No. It is just the interface - and even that only to a certain extent - that
 will mimic Eigen. The core the library would be very similar to what I
 implemented for SciD last year, which, you will find, is very D-like and not
 at all like Eigen.




Re: GSoC 2012 Proposal: Continued Work on a D Linear Algebra library (SciD - std.linalg)

2012-04-09 Thread Cristi Cobzarenco
Thanks for the suggestions!

I don't think UFCS would help us. Our problem is that we can't do this:
triangular.d:
  struct TriangularMatrix {

  }

  void sum( T )( T x ) if( is( T : TriangularMatrix ) ) {

  }

diagonal.d:
  struct DiagonalMatrix {

  }

  void sum( T )( T x ) if( is( T : DiagonalMatrix ) ) {

  }

main.d:
import diagonal;
import triangular;

void bar() {
   TriangularMatrix a;
   Diagonal b;
   sum( a );  // this does not compile because sum() is ambiguous
   sum( b );  // nor does this
}

This, AFAIK, is deliberate to avoid name hijacking - ADL in C++ had its
share of criticism. I doubt we will ever get this behaviour in D and that
is perhaps a good thing. I may have misunderstood UFCS though - or what you
meant by making non-member function calls look nicer - please correct me if
that's the case.

Don't worry about long names, t() is already the way transposition is
defined SciD. Moreover, it's a property so you can actually do a.t * a -
convenience galore. I'm also considering of creating a submodule like
std.linalg.short which defines aliases with short names for types and free
functions - this will allow particularly numerics-heavy functions to be
written more compactly. I'm not entirely sure it would be a good idea
though as it may sacrifice readability where it's most needed.

---
Cristi Cobzarenco
BSc in Artificial Intelligence and Computer Science
University of Edinburgh
Profile: http://www.google.com/profiles/cristi.cobzarenco



On 10 April 2012 01:36, Michael Chen sth4...@gmail.com wrote:

 Hi, Cristi,
 From change log of D 2.059. I saw that uniform function call syntax
 was implemented. I hope you can leverage this feature to make non
 member function calls look nicer. Another suggestion, please use
 shorter function name for example M.t() instead of M.transpose() so
 that long expression is easy to read.

 Best,
 Mo

 On Mon, Apr 9, 2012 at 6:52 AM, Cristi Cobzarenco
 cristi.cobzare...@gmail.com wrote:
  On 8 April 2012 18:59, Caligo iteronve...@gmail.com wrote:
 
  On Tue, Apr 3, 2012 at 6:20 AM, Cristi Cobzarenco
  cristi.cobzare...@gmail.com wrote:
  
   The point of these is to have light-weight element wise operation
   support.
   It's true that in theory the built-in arrays do this. However, this
   library
   is built on top BLAS/LAPACK, which means operations on large matrices
   will
   be faster than on D arrays.
  
 
  I can't agree with building it on top of LAPACK or any other BLAS
  implementation, but perhaps I shouldn't complain because I'm not the
  one who's going to be implementing it.  I like the approach Eigen has
  taken where it offers its own BLAS implementation and, iirc, other
  BLAS libraries can be used as optional back-ends.
 
 
  Yes, I agree with you. I already built naive implementations for BLAS 
  LAPACK functions as part of my last year project, using external
 libraries
  is optional (building with version=nodeps ensures absolutely no
 dependencies
  are needed). The argument still stands, though. If you _do_ use external
  BLAS libraries then using value arrays will _still_ be faster.
 
 
 
   Also, as far as I know, D doesn't support
   allocating dynamic 2-D arrays (as in not arrays of arrays), not to
   mention
   2-D slicing (keeping track of leading dimension).
  
 
  I fail to see why there is any need for 2D arrays.  We need to make
  sure multidimensional arrays (matrices) have data in very good
  arrangements.  This is called tiling and it requires 1D arrays:  2D
  arrays are stored as 1D arrays together with an indexing mechanism.
 
 
  That is precisely what I meant. We need wrappers around D arrays, because
  they, by themselves, do not support 2-D indexing. By providing a wrapper
 we
  allow the nice syntax of matrix[ a, b ]. This kind of wrapping is
 already in
  SciD by CowMatrix. I meant we shouldn't use D built-in arrays directly,
 not
  not at all. Also, as mentioned before, we can't use new for allocation,
  because we want the library to be GC-independent.
 
 
   Also I'm not sure how a case like this will be compiled, it may or may
   not
   allocate a temporary:
  
   a[] = b[] * c[] + d[] * 2.0;
  
   The expression templates in SciD mean there will be no temporary
   allocation
   in this call.
  
 
  Why are expression templates used?
 
 
  As H. S. Teoh rightfully pointed out, it is important not to allocate
  temporaries in matrix operations. You want to evaluate A = B * 3.0 + D *
 2.0
  (where .* is element-wise multiplication) as (in BLAS terms):
copy( B, A );
scal( 3.0, A );
axpy( D, 2.0, A );
 
  Or with naive expression template evaluation:
for( i = 0 ; i  n ; ++ i ) {
   A[ i ] = B[ i ] * 3.0 + D * 2.0;
}
 
  The D compiler would instead evaluate this as:
// allocate temporaries
allocate( tmp1, A.length );
allocate( tmp2, A.length );
allocate( tmp3, A.length );
 
// compute tmp1 = B * 3.0
copy( B, tmp1 );
scal( 3.0, tmp1 );
 
// compute tmp2 = D * 

Re: GSoC 2012 Proposal: Continued Work on a D Linear Algebra library (SciD - std.linalg)

2012-04-08 Thread Caligo
On Tue, Apr 3, 2012 at 6:20 AM, Cristi Cobzarenco
cristi.cobzare...@gmail.com wrote:

 The point of these is to have light-weight element wise operation support.
 It's true that in theory the built-in arrays do this. However, this library
 is built on top BLAS/LAPACK, which means operations on large matrices will
 be faster than on D arrays.


I can't agree with building it on top of LAPACK or any other BLAS
implementation, but perhaps I shouldn't complain because I'm not the
one who's going to be implementing it.  I like the approach Eigen has
taken where it offers its own BLAS implementation and, iirc, other
BLAS libraries can be used as optional back-ends.

 Also, as far as I know, D doesn't support
 allocating dynamic 2-D arrays (as in not arrays of arrays), not to mention
 2-D slicing (keeping track of leading dimension).


I fail to see why there is any need for 2D arrays.  We need to make
sure multidimensional arrays (matrices) have data in very good
arrangements.  This is called tiling and it requires 1D arrays:  2D
arrays are stored as 1D arrays together with an indexing mechanism.

 Also I'm not sure how a case like this will be compiled, it may or may not
 allocate a temporary:

 a[] = b[] * c[] + d[] * 2.0;

 The expression templates in SciD mean there will be no temporary allocation
 in this call.


Why are expression templates used?  Are you pretty much rewriting
Eigen in D ?  I don't see why expression templates would be needed
with D.


Re: GSoC 2012 Proposal: Continued Work on a D Linear Algebra library (SciD - std.linalg)

2012-04-08 Thread H. S. Teoh
On Sun, Apr 08, 2012 at 12:59:08PM -0500, Caligo wrote:
 On Tue, Apr 3, 2012 at 6:20 AM, Cristi Cobzarenco
 cristi.cobzare...@gmail.com wrote:
[...]
  Also I'm not sure how a case like this will be compiled, it may or
  may not allocate a temporary:
 
  a[] = b[] * c[] + d[] * 2.0;
 
  The expression templates in SciD mean there will be no temporary
  allocation in this call.
 
 
 Why are expression templates used?  Are you pretty much rewriting
 Eigen in D ?  I don't see why expression templates would be needed
 with D.

Expression templates are necessary to eliminate temporaries and optimize
loops. The reason libraries like BLAS are so efficient is because they
directly implement common operations like A = k*B + C. Without
expression templates, a D implementation would create a temporary for
k*B and then k*B + C and then assign the result, whereas expression
templates allow you to directly compute the elements of A in a single
loop over the matrix elements.


T

-- 
Change is inevitable, except from a vending machine.


Re: GSoC 2012 Proposal: Continued Work on a D Linear Algebra library (SciD - std.linalg)

2012-04-08 Thread Cristi Cobzarenco
On 8 April 2012 18:59, Caligo iteronve...@gmail.com wrote:

 On Tue, Apr 3, 2012 at 6:20 AM, Cristi Cobzarenco
 cristi.cobzare...@gmail.com wrote:
 
  The point of these is to have light-weight element wise operation
 support.
  It's true that in theory the built-in arrays do this. However, this
 library
  is built on top BLAS/LAPACK, which means operations on large matrices
 will
  be faster than on D arrays.
 

 I can't agree with building it on top of LAPACK or any other BLAS
 implementation, but perhaps I shouldn't complain because I'm not the
 one who's going to be implementing it.  I like the approach Eigen has
 taken where it offers its own BLAS implementation and, iirc, other
 BLAS libraries can be used as optional back-ends.


Yes, I agree with you. I already built naive implementations for BLAS 
LAPACK functions as part of my last year project, using external libraries
is optional (building with version=nodeps ensures absolutely no
dependencies are needed). The argument still stands, though. If you _do_
use external BLAS libraries then using value arrays will _still_ be faster.



  Also, as far as I know, D doesn't support
  allocating dynamic 2-D arrays (as in not arrays of arrays), not to
 mention
  2-D slicing (keeping track of leading dimension).
 

 I fail to see why there is any need for 2D arrays.  We need to make
 sure multidimensional arrays (matrices) have data in very good
 arrangements.  This is called tiling and it requires 1D arrays:  2D
 arrays are stored as 1D arrays together with an indexing mechanism.


That is precisely what I meant. We need wrappers around D arrays, because
they, by themselves, do not support 2-D indexing. By providing a wrapper we
allow the nice syntax of matrix[ a, b ]. This kind of wrapping is already
in SciD by CowMatrix. I meant we shouldn't use D built-in arrays directly,
not not at all. Also, as mentioned before, we can't use new for allocation,
because we want the library to be GC-independent.


  Also I'm not sure how a case like this will be compiled, it may or may
 not
  allocate a temporary:
 
  a[] = b[] * c[] + d[] * 2.0;
 
  The expression templates in SciD mean there will be no temporary
 allocation
  in this call.
 

 Why are expression templates used?


As H. S. Teoh rightfully pointed out, it is important not to allocate
temporaries in matrix operations. You want to evaluate A = B * 3.0 + D *
2.0 (where .* is element-wise multiplication) as (in BLAS terms):
  copy( B, A );
  scal( 3.0, A );
  axpy( D, 2.0, A );

Or with naive expression template evaluation:
  for( i = 0 ; i  n ; ++ i ) {
 A[ i ] = B[ i ] * 3.0 + D * 2.0;
  }

The D compiler would instead evaluate this as:
  // allocate temporaries
  allocate( tmp1, A.length );
  allocate( tmp2, A.length );
  allocate( tmp3, A.length );

  // compute tmp1 = B * 3.0
  copy( B, tmp1 );
  scal( 3.0, tmp1 );

  // compute tmp2 = D * 2.0;
  copy( D, tmp2 );
  scal( 2.0, tmp2 );

  // compute tmp3 = tmp1 + tmp2;
  copy( tmp1, tmp3 );
  axpy( tmp2, 1.0, tmp1 );

  // copy tmp3 into A
  copy( tmp3, A );

Plenty of useless computation. Note this is not a fault of the compiler, it
has no way of knowing which temporaries can be optimised away for user
types (i.e. our matrices).

 Are you pretty much rewriting Eigen in D?

No. It is just the interface - and even that only to a certain extent -
that will mimic Eigen. The core the library would be very similar to what I
implemented for SciD last year, which, you will find, is very D-like and
not at all like Eigen.


Re: GSoC 2012 Proposal: Continued Work on a D Linear Algebra library (SciD - std.linalg)

2012-04-05 Thread Michael Chen
Thanks for the explanation, now I get it. In case you are interested,
there is excellent article about monad style c++ template meta
programming by Bartosz Milewski which might be helpful for compile
time optimization for evaluation order.
Really looking forward to official release of the SciD. D is really
suitable for scientific computation. It will be great to have an
efficient and easy-to-use linear algebra library.


On Thu, Apr 5, 2012 at 7:42 AM, Cristi Cobzarenco
cristi.cobzare...@gmail.com wrote:
 Thanks for the feedback!

 On 4 April 2012 10:21, Michael Chen sth4...@gmail.com wrote:

 another btw, there is also another great c++ linear algebra library
 besides Eigen: Amardillo which has very simple matlab like interface
  and performs on a par with Eigen.


 I'll look into it, thanks.


 On Wed, Apr 4, 2012 at 5:14 PM, Michael Chen sth4...@gmail.com wrote:
  Btw, I really don't like the matrix api to be member functions. It is
  hard for user to extend the library in an unified way. It is also ugly
  when you want to chain the function calls.

 
  On Wed, Apr 4, 2012 at 5:09 PM, Michael Chen sth4...@gmail.com wrote:
  For the Point 4, I really like to have high order functions like
  reduceRow and reduceCol. then the function argument is simply the
  reduceRow!foo(0,mat), here the foo is not a function operating on the
  whole column but simply a function of two elements (e.g.
  reduceRow!(a+b)(0,mat)). Or even better we could have a general
  reduce function with row and col as template parameter so that we can
  do reduce!(foo,row)(0,mat). I dont know whether we can optimize such
  reduce function for different matrix type, but such a function will be
  extremely useful from a user perspective


 Well, as I said before, there's nothing stopping us from providing the free
 functions that call the member functionsl. However there is something
 stopping us from not providing a member function alternative. D's lack of
 ADL means we would not allow easy extensibility of possible operations. Say
 Alice invents a new kind of matrix type, the DiagonalMatrix type which
 stores its elements in a 1D array (this isn't exactly how it would work with
 the design we have, she would in fact have to define a storage type, but
 bear with me). If she wants to implement sum on her matrix, she can't simply
 add a specialisation to the sum( T ) function because of the lack of ADL. If
 instead we implemented sum(T) as:

 auto sum( T )( T matrix ) {
      static if( is( typeof( T.init.sum() ) ) )
          return matrix.sum;
      else
          return reduce!a+b( 0, matrix.elements() );
 }

 then Alice could simply define a DiagonalMatrix.sum() method that wouldn't
 need to go through all the zero elements, for example. The idea of rowReduce
 and columnReduce still works - we can provide this for when a user wants to
 use her own operation for reducing. We could also have a way of
 automatically optimising rowReduce!a+b( mat ) by calling
 mat.rowwise().sum() if the operation is available - but that wouldn't be
 exactly high priority.


 .
 
  On Tue, Apr 3, 2012 at 7:20 PM, Cristi Cobzarenco
  cristi.cobzare...@gmail.com wrote:
 
 
  On 3 April 2012 02:37, Caligo iteronve...@gmail.com wrote:
 
  I've read **Proposed Changes and Additions**, and I would like to
  comment and ask a few questions if that's okay.  BTW, I've used Eigen
  a lot and I see some similarities here, but a direct rewrite may not
  be the best thing because D  C++.
 
  2.  Change the matrix  vector types, adding fixed-sized matrix
  support in the process.
 
  This is a step in the right direction I think, and by that I'm
  talking
  about the decision to remove the difference between a Vector and a
  Matrix.  Also, fixed-size matrices are also a must.  There is
  compile-time optimization that you won't be able to do for
  dynamic-size matrices.
 
 
  3. Add value arrays (or numeric arrays, we can come up with a good
  name).
 
  I really don't see the point for these.  We have the built-in arrays
  and the one in Phobos (which will get even better soon).
 
 
  The point of these is to have light-weight element wise operation
  support.
  It's true that in theory the built-in arrays do this. However, this
  library
  is built on top BLAS/LAPACK, which means operations on large matrices
  will
  be faster than on D arrays. Also, as far as I know, D doesn't support
  allocating dynamic 2-D arrays (as in not arrays of arrays), not to
  mention
  2-D slicing (keeping track of leading dimension).
  Also I'm not sure how a case like this will be compiled, it may or may
  not
  allocate a temporary:
 
  a[] = b[] * c[] + d[] * 2.0;
 
  The expression templates in SciD mean there will be no temporary
  allocation
  in this call.
 
 
 
  4. Add reductions, partial reductions, and broadcasting for matrices
  and
  arrays.
 
  This one is similar to what we have in Eigen, but I don't understand
  why the operations are member functions (even in Eigen).  I 

Re: GSoC 2012 Proposal: Continued Work on a D Linear Algebra library (SciD - std.linalg)

2012-04-04 Thread Michael Chen
For the Point 4, I really like to have high order functions like
reduceRow and reduceCol. then the function argument is simply the
reduceRow!foo(0,mat), here the foo is not a function operating on the
whole column but simply a function of two elements (e.g.
reduceRow!(a+b)(0,mat)). Or even better we could have a general
reduce function with row and col as template parameter so that we can
do reduce!(foo,row)(0,mat). I dont know whether we can optimize such
reduce function for different matrix type, but such a function will be
extremely useful from a user perspective.

On Tue, Apr 3, 2012 at 7:20 PM, Cristi Cobzarenco
cristi.cobzare...@gmail.com wrote:


 On 3 April 2012 02:37, Caligo iteronve...@gmail.com wrote:

 I've read **Proposed Changes and Additions**, and I would like to
 comment and ask a few questions if that's okay.  BTW, I've used Eigen
 a lot and I see some similarities here, but a direct rewrite may not
 be the best thing because D  C++.

 2.  Change the matrix  vector types, adding fixed-sized matrix
 support in the process.

 This is a step in the right direction I think, and by that I'm talking
 about the decision to remove the difference between a Vector and a
 Matrix.  Also, fixed-size matrices are also a must.  There is
 compile-time optimization that you won't be able to do for
 dynamic-size matrices.


 3. Add value arrays (or numeric arrays, we can come up with a good name).

 I really don't see the point for these.  We have the built-in arrays
 and the one in Phobos (which will get even better soon).


 The point of these is to have light-weight element wise operation support.
 It's true that in theory the built-in arrays do this. However, this library
 is built on top BLAS/LAPACK, which means operations on large matrices will
 be faster than on D arrays. Also, as far as I know, D doesn't support
 allocating dynamic 2-D arrays (as in not arrays of arrays), not to mention
 2-D slicing (keeping track of leading dimension).
 Also I'm not sure how a case like this will be compiled, it may or may not
 allocate a temporary:

 a[] = b[] * c[] + d[] * 2.0;

 The expression templates in SciD mean there will be no temporary allocation
 in this call.



 4. Add reductions, partial reductions, and broadcasting for matrices and
 arrays.

 This one is similar to what we have in Eigen, but I don't understand
 why the operations are member functions (even in Eigen).  I much
 rather have something like this:

 rowwise!sum(mat);

 Also, that way the users can use their own custom functions with much
 ease.


 There is a problem with this design. You want each matrix type (be it
 general, triangular, sparse or even an expression node)  do be able to
 define its own implementation of sum: calling the right BLAS function and
 making whatever specific optimisations they can. Since D doesn't have
 argument dependent look-up (ADL), users can't provide specialisations for
 their own types. The same arguments apply to rowwise() and columnwise()
 which will return proxies specific to the matrix type. You could do
 something like this, in principle:

 auto sum( T )( T mat ) {
   return mat.sum();
 }

 And if we want that we can add it, but this will provide no addition in
 extensibility. By the way, you can use std.algorithm with matrices since
 they offer range functionality, but it will be much slower to use
 reduce!mySumFunction(mat) than mat.sum() which uses a BLAS backend.





 6. Add support for interoperation with D built-in arrays (or pointers).

 So I take that Matrix is not a sub-type?  why? If we have something like
 this:

 struct Matrix(Real, size_t row, size_t col) {

  Real[row*col] data;
  alias data this;
 }

 then we wouldn't need any kind of interoperation with built-in arrays,
 would we?  I think this would save us a lot of headache.

 That's just me and I could be wrong.


 Inter-operation referred more to having a matrix object wrapping a pointer
 to an already available piece of memory - maybe allocated through a region
 allocator, maybe resulting from some other library. This means we need to
 take care of different strides and different storage orders which cannot be
 handled by built-in arrays. Right now, matrices wrap ref-counted
 copy-on-write array types (ArrayData in the current code) - we decided last
 year that we don't want to use the garbage collector, because of its current
 issues. Also I would prefer not using the same Matrix type for
 pointer-wrappers and normal matrices because the former must have reference
 semantics while the latter have value semantics. I think it would be
 confusing if some matrices would copy their data and some would share
 memory.



 I've got to tell you though, I'm very excited about this project and
 I'll be watching it closely.

 cheers.

 ---
 Cristi Cobzarenco
 BSc in Artificial Intelligence and Computer Science
 University of Edinburgh
 Profile: http://www.google.com/profiles/cristi.cobzarenco



Re: GSoC 2012 Proposal: Continued Work on a D Linear Algebra library (SciD - std.linalg)

2012-04-04 Thread Cristi Cobzarenco
Thanks for the feedback!

On 4 April 2012 10:21, Michael Chen sth4...@gmail.com wrote:

 another btw, there is also another great c++ linear algebra library
 besides Eigen: Amardillo which has very simple matlab like interface
  and performs on a par with Eigen.


I'll look into it, thanks.


 On Wed, Apr 4, 2012 at 5:14 PM, Michael Chen sth4...@gmail.com wrote:
  Btw, I really don't like the matrix api to be member functions. It is
  hard for user to extend the library in an unified way. It is also ugly
  when you want to chain the function calls.


  On Wed, Apr 4, 2012 at 5:09 PM, Michael Chen sth4...@gmail.com wrote:
  For the Point 4, I really like to have high order functions like
  reduceRow and reduceCol. then the function argument is simply the
  reduceRow!foo(0,mat), here the foo is not a function operating on the
  whole column but simply a function of two elements (e.g.
  reduceRow!(a+b)(0,mat)). Or even better we could have a general
  reduce function with row and col as template parameter so that we can
  do reduce!(foo,row)(0,mat). I dont know whether we can optimize such
  reduce function for different matrix type, but such a function will be
  extremely useful from a user perspective


Well, as I said before, there's nothing stopping us from providing the free
functions that call the member functionsl. However there is something
stopping us from not providing a member function alternative. D's lack of
ADL means we would not allow easy extensibility of possible operations. Say
Alice invents a new kind of matrix type, the DiagonalMatrix type which
stores its elements in a 1D array (this isn't exactly how it would work
with the design we have, she would in fact have to define a storage type,
but bear with me). If she wants to implement sum on her matrix, she can't
simply add a specialisation to the sum( T ) function because of the lack of
ADL. If instead we implemented sum(T) as:

auto sum( T )( T matrix ) {
 static if( is( typeof( T.init.sum() ) ) )
 return matrix.sum;
 else
 return reduce!a+b( 0, matrix.elements() );
}

then Alice could simply define a DiagonalMatrix.sum() method that wouldn't
need to go through all the zero elements, for example. The idea of
rowReduce and columnReduce still works - we can provide this for when a
user wants to use her own operation for reducing. We could also have a way
of automatically optimising rowReduce!a+b( mat ) by calling
mat.rowwise().sum() if the operation is available - but that wouldn't be
exactly high priority.


 .
 
  On Tue, Apr 3, 2012 at 7:20 PM, Cristi Cobzarenco
  cristi.cobzare...@gmail.com wrote:
 
 
  On 3 April 2012 02:37, Caligo iteronve...@gmail.com wrote:
 
  I've read **Proposed Changes and Additions**, and I would like to
  comment and ask a few questions if that's okay.  BTW, I've used Eigen
  a lot and I see some similarities here, but a direct rewrite may not
  be the best thing because D  C++.
 
  2.  Change the matrix  vector types, adding fixed-sized matrix
  support in the process.
 
  This is a step in the right direction I think, and by that I'm talking
  about the decision to remove the difference between a Vector and a
  Matrix.  Also, fixed-size matrices are also a must.  There is
  compile-time optimization that you won't be able to do for
  dynamic-size matrices.
 
 
  3. Add value arrays (or numeric arrays, we can come up with a good
 name).
 
  I really don't see the point for these.  We have the built-in arrays
  and the one in Phobos (which will get even better soon).
 
 
  The point of these is to have light-weight element wise operation
 support.
  It's true that in theory the built-in arrays do this. However, this
 library
  is built on top BLAS/LAPACK, which means operations on large matrices
 will
  be faster than on D arrays. Also, as far as I know, D doesn't support
  allocating dynamic 2-D arrays (as in not arrays of arrays), not to
 mention
  2-D slicing (keeping track of leading dimension).
  Also I'm not sure how a case like this will be compiled, it may or may
 not
  allocate a temporary:
 
  a[] = b[] * c[] + d[] * 2.0;
 
  The expression templates in SciD mean there will be no temporary
 allocation
  in this call.
 
 
 
  4. Add reductions, partial reductions, and broadcasting for matrices
 and
  arrays.
 
  This one is similar to what we have in Eigen, but I don't understand
  why the operations are member functions (even in Eigen).  I much
  rather have something like this:
 
  rowwise!sum(mat);
 
  Also, that way the users can use their own custom functions with much
  ease.
 
 
  There is a problem with this design. You want each matrix type (be it
  general, triangular, sparse or even an expression node)  do be able to
  define its own implementation of sum: calling the right BLAS function
 and
  making whatever specific optimisations they can. Since D doesn't have
  argument dependent look-up (ADL), users can't provide specialisations
 for
  their own types. The same 

Re: GSoC 2012 Proposal: Continued Work on a D Linear Algebra library (SciD - std.linalg)

2012-03-27 Thread Cristi Cobzarenco
Sorry for the follow-up, I just wanted to mention that I also uploaded
the proposal on Melange at
http://www.google-melange.com/gsoc/proposal/review/google/gsoc2012/cristicbz/41002#,
but I still recommend reading it on github.

Thank you,
Cristian.

---
Cristi Cobzarenco
BSc in Artificial Intelligence and Computer Science
University of Edinburgh
Profile: http://www.google.com/profiles/cristi.cobzarenco



On 27 March 2012 11:44, Cristi Cobzarenco cristi.cobzare...@gmail.com wrote:
 Hello everyone,

 My name is Cristian Cobzarenco and last year, mentored by David Simcha
 and co-mentored by Fawzi Mohamed and Andrei Alexandrescu, I worked on
 a fork of SciD as part of Google's Summer of Code. While we've got a
 lot done last summer there's still plenty to do and my proposal this
 year is to get the library into a finished state where it can be
 reviewed for inclusion in Phobos as std.linalg. The easiest place to
 read my proposal is at the library's wiki:
 https://github.com/cristicbz/scid/wiki/GSoC-2012-Proposal, I will
 convert the formatting and add it to Melange soon.

 Feedback would be most welcome, I'm interested particularly in if you
 think the priorities I set are correct or if there is something you
 would (or wouldn't) rather see in the library. Let me know if anyone
 wants me to attach the content to an e-mail (it would be a pretty long
 e-mail), to allow in-line commenting.

 Yours,
 Cristian.

 ---
 Cristi Cobzarenco
 BSc in Artificial Intelligence and Computer Science
 University of Edinburgh
 Profile: http://www.google.com/profiles/cristi.cobzarenco