-
Notifications
You must be signed in to change notification settings - Fork 181
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add solve based on OpenBLAS #710
Conversation
#:set CMPLX_KINDS_TYPES_GESV = list(zip(BLAS_CMPLX_KINDS, CMPLX_TYPES, BLAS_CMPLX_GESV)) | ||
#:set RC_KINDS_TYPES_GESV = REAL_KINDS_TYPES_GESV + CMPLX_KINDS_TYPES_GESV | ||
#:for k1, t1, g1 in RC_KINDS_TYPES_GESV | ||
module function solve_${t1[0]}$${k1}$(a, b) result(x) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer a subroutine-style interface, e.g.
subroutine solve(X, A, B)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with the above. It makes more sense to use a subroutine, so that the code stays performant when large matrices are involved.
Also, would it make sense to call the procedure something like linsolve
, instead of just solve
, anticipating that in the future a nonlinear solver will be added as well?
@@ -133,6 +133,7 @@ Important options are | |||
Compiling with maximum rank 15 can be resource intensive and requires at least 16 GB of memory to allow parallel compilation or 4 GB memory for sequential compilation. | |||
- `-DBUILD_SHARED_LIBS` set to `on` in case you want link your application dynamically against the standard library (default: `off`). | |||
- `-DBUILD_TESTING` set to `off` in case you want to disable the stdlib tests (default: `on`). | |||
- `-DBUILD_OPENBLAS` set to `on` in case you want to use routines based on OpenBLAS (default: `off`). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BUILD_WITH_OPENBLAS
may be better
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you. I think it will be an important step for stdlib. My main concern is about the API. Should it be a simple wrapper, or something more complete (similar to @awvwgk BLAS interfaces).
See also #450 for some discussions.
@@ -133,6 +133,7 @@ Important options are | |||
Compiling with maximum rank 15 can be resource intensive and requires at least 16 GB of memory to allow parallel compilation or 4 GB memory for sequential compilation. | |||
- `-DBUILD_SHARED_LIBS` set to `on` in case you want link your application dynamically against the standard library (default: `off`). | |||
- `-DBUILD_TESTING` set to `off` in case you want to disable the stdlib tests (default: `on`). | |||
- `-DBUILD_OPENBLAS` set to `on` in case you want to use routines based on OpenBLAS (default: `off`). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fpm
should be also able to compile the project.
efficient low level implementations of standard linear algebra algorithms. | ||
|
||
If possible, highly optimized libraries that take advantage of specialized processor functionality are preferred. | ||
Examples of such libraries are [OpenBLAS][1], [oneAPI MKL(TM)][2]. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Examples of such libraries are [OpenBLAS][1], [oneAPI MKL(TM)][2]. | |
Examples of such libraries are [OpenBLAS][1], [Intel oneAPI MKL(TM)][2]. |
@@ -425,3 +436,43 @@ Specifically, upper Hessenberg matrices satisfy `a_ij = 0` when `j < i-1`, and l | |||
```fortran | |||
{!example/linalg/example_is_hessenberg.f90!} | |||
``` | |||
|
|||
## `solve` - Solve a-linear-matrix-equation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
## `solve` - Solve a-linear-matrix-equation | |
## `solve` - Solve a linear matrix equation |
|
||
Solve a linear matrix equation, or system of linear scalar equations. | ||
|
||
Note: `solve` supports only single and double precision floating point types. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This "note" will be implicitely mentioned through the description of the arguments. Therefore, it could be removed
|
||
### Class | ||
|
||
Impure function. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For such procedures, I would prefera subroutine over a function, especially for efficienct with large vectors/matrices.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Subroutines are usually faster than functions, functions are usually easier to use but may cause performance degradation. If you need high performance, you should use subroutines. If you need simpler code, you should use a function.
Intuitively, solving a system of AX = B
linear equations, the normal form X = solve(A, B)
will naturally be understood by the average user and will be surprised by call solve(A, B)
. My personal recommendation is to think of solve
as a function dedicated to solving systems of linear equations, rather than for performance, which can be done with _gesv
routines.
- (Not recommended) Perhaps we could provide a
solve_
subroutine that implements the in-place version ofsolve
, like this:
subroutine solve_(a, b)
real, intent(inout) :: a(:, :), b(:, :)
integer :: ipiv(size(a, 1)), info
call sgesv(size(a, 1), size(b, 2), a, size(a, 1), ipiv, b, size(b, 1), info)
end subroutine solve_
- (Recommended) Or for performance-sensitive users, it is recommended to just use the low-level interface
_gesv
for programming by borrowing the implementation ofsolve
?
|
||
### Synatx | ||
|
||
`x = [[stdlib_linalg(module):solve(interface)]](a,b)` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could b
be a vector too?
|
||
Experimental | ||
|
||
### Description |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be good to add somewhere to which BLAS procedure it is linked with
@jvdp1 I'm not worried about this, and it shouldn't be too complicated to switch if the full BLAS interfaces library is available later. |
This PR should be reviewed considering latest developments of @perazz on BLAS/LAPACK |
Closed in favour of #806 . |
pkg-config
to findopenblas
and defineUSE_OPENBLAS
;BUILD_OPENBLAS
is off by default because stdlib has few BLAS-based functions yet.BLAS_common.fypp
to set the BLAS related common variables;solve
function tostdlib_linalg
, and test it;_gesv
return valueinfo
.This PR is an attempt to irrationally generate enthusiasm for BLAS integration into stdlib. Close #709 .
Syntax
x = [[stdlib_linalg(module):solve(interface)]](a,b)