While using BLAS DGEMM matrix-multiply function, I noticed that for an uninitialized result matrix C, I get NaNs in the resultwhen I call it like so:
DGEMM('N', 'N', M, N, K, 1.0, A, LDA, B, LDB, 0.0, C, LDC)
However, if I declare ALPHA and BETA before-hand:
REAL*8 ALPHA, BETA
PARAMETER (ALPHA=1.0)
PARAMETER (BETA=0.0)
DGEMM('N', 'N', M, N, K, ALPHA, A, LDA, B, LDB, BETA, C, LDC)
then the multiplication works okay. Does anyone have any ideas as to why declaring the arguments works?
Note that I'm using the Intel Fortran compiler along with it's MKL library.
It would work if you passed alpha and beta as double precision numerical constants (eg, 1.d0), but you're passing it single precision constants, and Fortran 77 has no way of knowing dgemm's argument list and promoting the reals to double precision. (It might work with the single precision constants if you used MKL's Fortran 95 interface, but I'm not sure).
Because you're only passing pointers 4-byte arguments and the library subroutine is looking up 8-byte values, the rest of the calculation gets messed up.
Related
I have a function that takes floats, I'm doing some computation with them, and I'd like to keep as much accuracy as possible in the returned result. I read that when you multiply two floats, you double the number of significant digits.
So when two floats get multiplied, for example float e, f; and I do double g = e * f, when do the bits get truncated?
In my example function below, do I need casting, and if yes, where? This is in a tight inner loop, if I put static_cast<double>(x) around each variable a b c d where it's used, I get 5-10% slowdown. But I suspect I don't need to cast each variable separately, and only in some locations, if at all? Or does returning a double here do not give me any gain anyway and I can as well just return a float?
double func(float a, float b, float c, float d) {
return (a - b) * c + (a - c) * b;
}
When you multiply two floats without casting, the result is calculated with float precision (i.e. truncated) and then converted to double.
To calculate the result in double, you need to cast at least one operand to double first. Then the entire calculation will be done in double (and all float values will be converted). However, that will create the same slowdown. The slowdown is likely because converting a number from float to double is not entirely trivial (different bit size and range of exponent and mantisa).
If I'd be doing that and have control over the function definition, I'd pass all the arguments as double (I generally use double everywhere, on modern computers the speed difference between calculating in float vs double is negligible, only issues could be memory throughput and cache performance when operating on large arrays of values).
Btw. the case important for precision actually isn't the multiplication, but the addition/subtraction - that is where the precision can make a big difference. Consider adding/subtracting 1e+6 and 1e-3.
Meaning is more important than 5-10% slowdown. What I'd do:
double func_impl(double a, double b, double c, double d) {
return (a - b) * c + (a - c) * b;
}
double func(float a, float b, float c, float d) {
return func_impl(a, b, c, d);
}
I'd choose this even if it's a bit slower, because it expresses the idea that you want double precision in your calculations well and just need the floats on the interface; while it keeps the body of your function separate from the casting (the latter being done in one step).
I would like to call a C api function from Fortran. The C function accepts an array of bytes:
void image(const void *bitmap, int w, int h);
where three successive bytes in *bitmap represent an RGB colour tripple and are interpreted as unsigned char in C. I want to initialize the bitmap in Fortran and take care of drawing inside C. Current definition in Fortran uses
integer*1 rgbImage(6,2)
to initialize an image of 2x2 for example, but compiler won't accept assignment
rgbImage(1,1) = 255
to get red colour. I've seen hints of using BYTE, UNSIGNED*1, LOGICAL*1 for unsigned single bytes, but gfortran (MacPort's gcc 4.4 or 4.6 under Mac OS X) isn't really happy with either of them. I could probably get away by cheating and assigning value -1 instead of 255, but that is very uncomfortable to use. The compiler flag -fno-range-check helped compile the code, but might not be available in other Fortran compilers and I consider it an ugly solution (I would still want to catch other warning). The values 'FF'X or '11111111'B are also recognized as 32-bit integers.
It is highly desirable for the code to be portable across different Fortran compilers.
My suggestion would be to use CHARACTER variables, and use ACHAR to set values (and ICHAR to convert back to integers as necessary). That should get you what you want and be completely portable. eg,
character, dimension(6,2) :: rgbImage
rgbImage(1,1) = achar(255)
Updated to add: if you're going to use the Fortran 2003 iso_c_binding stuff to interface to the C routines (highly recommended!) then you might as well make that rgbImage array characters of kind c_char, eg
character(kind=c_char), dimension(6,2) :: rgbImage
integer(kind=c_int) :: w, h
...
rgbImage(1,1) = achar(255)
...
call image(rgbImage, w, h)
where you've defined the interface for the routine
interface
subroutine image(img, w, h) bind(C)
use, intrinsic :: iso_c_binding
implicit none
integer(kind=c_int), intent(in), value :: w, h
character(kind=c_char) :: img(:,:)
end subroutine image
end interface
An alternative strategy that may be suitable for some circumstances is to pass the 1 byte c int array to an Integer(1) array, say, iVal(:), then create another Int array such as Integer(2) iVal2(:), then:
Where(iVal(:) < 0)
iVal2(:) = -iVal(:)+127
ElseWhere
iVal2(:) = iVal(:)
End Where
... this can be a bit more efficient/cleaner compared to converting to/fro chars (sometimes) and requires less coding (sometimes).
If you do a lot of this type of thing (interfacing various types of usigned's etc to Fortran), a few utility routines relying on Fortran's bit intrinsics may be a worthwhile investment (e.g. BTest(), iBSet() etc).
I'm stucked with a heap corruption problem in Visual Studio 2008 with Intel Fortran Compiler 11. I'm working on Windows 7 64-bit.
This is a call to a (F77) lapack subroutine in my F90 program:
call dgetrs('N', nbParams, one, a, nbParams, ipv, x, nbParams, err)
Before this call the debugger shows expected values for all parameters. a and x stand for two "allocatable" variables with size (nbParams,nbParams) and (nbParams) respectively.
However, after running this line the execution stops with an Access violation reading location 0x0000000000000001. Since I have compiled lapack in debug mode I'm able to go inside the call, and I see that everything but 'TRANS' gets corrupted just in the first statement of DGETRS.
SUBROUTINE DGETRS( TRANS, N, NRHS, A, LDA, IPIV, B, LDB, INFO )
...
CHARACTER TRANS
INTEGER INFO, LDA, LDB, N, NRHS
...
INTEGER IPIV( * )
DOUBLE PRECISION A( LDA, * ), B( LDB, * )
......
INFO = 0 **--> Now all input vars but TRANS are corrupted or dereferenced!**
I'm tried everything and I'm unable to locate the problem. Could anybody help me locating the problem?
Thanks for your help!
This kind of problems usually appear when using assumed shape arrays without an interface. Try declaring an interface such as:
INTERFACE
SUBROUTINE DGETRS( TRANS, N, NRHS, A, LDA, IPIV, B, LDB, INFO )
CHARACTER TRANS
INTEGER INFO, LDA, LDB, N, NRHS
INTEGER IPIV( * )
DOUBLE PRECISION A( LDA, * ), B( LDB, * )
END SUBROUTINE
END INTERFACE
Does anybody know of a sparse SVD solver for c++? My problem involves some badly conditioned matrices that might have zeroed columns/rows. My data is stored in a uBLAS matrix which is the Harwell-Boeing sparse format.
I am having some trouble finding:
The SVD solver
The SVD solver that can operate on sparse matrices. Lapack doesn't seem to be able to do this? I want to have sparse matrices passed to the function and sparse matrices output.
A way to recombine the results... So that I can read off the xs from x=b(A^-1). I would expect this to be x=(b)(v.(d^-1).(u^t))
I am hoping to recreate the following two steps from GSL
gsl_linalg_SV_decomp_jacobi (gsl_matrix * A, gsl_matrix * V, gsl_vector * S)
gsl_linalg_SV_solve (const gsl_matrix * U, const gsl_matrix * V, const gsl_vector * S, const gsl_vector * b, gsl_vector * x)
I also have no clue how to wrap a FORTRAN library in c++.
Where/Are there any PROPACK c/c++ bindings?
Edit 1:
I'm having some trouble with PROPACK. Does PROPACK output sparse matrices? It seems to output V as "V(LDV,KMAX): DOUBLE PRECISION array." which would imply that it doesn't?
SVDLIBC is a C library with partial support for the Harwell-Boeing format. I am not familiar with the library, but on the surface it seems to match your requirements.
You mentioned PROPACK. Fortran is C-compatible, you just have to know how the calling convention works. I'm not certain, but I think that the function you want to call in PROPACK is dlansvd (assuming double-precision), which is documented as follows:
subroutine dlansvd(jobu,jobv,m,n,k,kmax,aprod,U,ldu,Sigma,bnd,
c V,ldv,tolin,work,lwork,iwork,liwork,doption,ioption,info,
c dparm,iparm)
c DLANSVD: Compute the leading singular triplets of a large and
c sparse matrix by Lanczos bidiagonalization with partial
c reorthogonalization.
c
c Parameters:
c
c JOBU: CHARACTER*1. If JOBU.EQ.'Y' then compute the left singular vectors.
c JOBV: CHARACTER*1. If JOBV.EQ.'Y' then compute the right singular
c vectors.
c M: INTEGER. Number of rows of A.
c N: INTEGER. Number of columns of A.
c K: INTEGER. Number of desired singular triplets. K <= MIN(KMAX,M,N)
c KMAX: INTEGER. Maximal number of iterations = maximal dimension of
c the generated Krylov subspace.
c APROD: Subroutine defining the linear operator A.
c APROD should be of the form:
c
c SUBROUTINE DAPROD(TRANSA,M,N,X,Y,DPARM,IPARM)
c CHARACTER*1 TRANSA
c INTEGER M,N,IPARM(*)
c DOUBLE PRECISION X(*),Y(*),DPARM(*)
c
c If TRANSA.EQ.'N' then the function should compute the matrix-vector
c product Y = A * X.
c If TRANSA.EQ.'T' then the function should compute the matrix-vector
c product Y = A^T * X.
c The arrays IPARM and DPARM are a means to pass user supplied
c data to APROD without the use of common blocks.
c U(LDU,KMAX+1): DOUBLE PRECISION array. On return the first K columns of U
c will contain approximations to the left singular vectors
c corresponding to the K largest singular values of A.
c On entry the first column of U contains the starting vector
c for the Lanczos bidiagonalization. A random starting vector
c is used if U is zero.
c LDU: INTEGER. Leading dimension of the array U. LDU >= M.
c SIGMA(K): DOUBLE PRECISION array. On return Sigma contains approximation
c to the K largest singular values of A.
c BND(K) : DOUBLE PRECISION array. Error estimates on the computed
c singular values. The computed SIGMA(I) is within BND(I)
c of a singular value of A.
c V(LDV,KMAX): DOUBLE PRECISION array. On return the first K columns of V
c will contain approximations to the right singular vectors
c corresponding to the K largest singular values of A.
c LDV: INTEGER. Leading dimension of the array V. LDV >= N.
c TOLIN: DOUBLE PRECISION. Desired relative accuracy of computed singular
c values. The error of SIGMA(I) is approximately
c MAX( 16*EPS*SIGMA(1), TOLIN*SIGMA(I) )
c WORK(LWORK): DOUBLE PRECISION array. Workspace of dimension LWORK.
c LWORK: INTEGER. Dimension of WORK.
c If JOBU.EQ.'N' and JOBV.EQ.'N' then LWORK should be at least
c M + N + 9*KMAX + 2*KMAX**2 + 4 + MAX(M+N,4*KMAX+4).
c If JOBU.EQ.'Y' or JOBV.EQ.'Y' then LWORK should be at least
c M + N + 9*KMAX + 5*KMAX**2 + 4 +
c MAX(3*KMAX**2+4*KMAX+4, NB*MAX(M,N)), where NB>1 is a block
c size, which determines how large a fraction of the work in
c setting up the singular vectors is done using fast BLAS-3
c operation.
c IWORK: INTEGER array. Integer workspace of dimension LIWORK.
c LIWORK: INTEGER. Dimension of IWORK. Should be at least 8*KMAX if
c JOBU.EQ.'Y' or JOBV.EQ.'Y' and at least 2*KMAX+1 otherwise.
c DOPTION: DOUBLE PRECISION array. Parameters for LANBPRO.
c doption(1) = delta. Level of orthogonality to maintain among
c Lanczos vectors.
c doption(2) = eta. During reorthogonalization, all vectors with
c with components larger than eta along the latest Lanczos vector
c will be purged.
c doption(3) = anorm. Estimate of || A ||.
c IOPTION: INTEGER array. Parameters for LANBPRO.
c ioption(1) = CGS. If CGS.EQ.1 then reorthogonalization is done
c using iterated classical GRAM-SCHMIDT. IF CGS.EQ.0 then
c reorthogonalization is done using iterated modified Gram-Schmidt.
c ioption(2) = ELR. If ELR.EQ.1 then extended local orthogonality is
c enforced among u_{k}, u_{k+1} and v_{k} and v_{k+1} respectively.
c INFO: INTEGER.
c INFO = 0 : The K largest singular triplets were computed succesfully
c INFO = J>0, J<K: An invariant subspace of dimension J was found.
c INFO = -1 : K singular triplets did not converge within KMAX
c iterations.
c DPARM: DOUBLE PRECISION array. Array used for passing data to the APROD
c function.
c IPARM: INTEGER array. Array used for passing data to the APROD
c function.
c
c (C) Rasmus Munk Larsen, Stanford, 1999, 2004
c
In Fortran, the important things to remember is that all parameters are passed by reference, and non-sparse arrays are stored in column-major format. So, the proper declaration of this function in C++ should be as follows (untested):
extern "C"
void dlansvd(const char *jobu,
const char *jobv,
int *m,
int *n,
int *k,
int *kmax,
void (*aprod)(const char *transa,
int *m,
int *n,
int *iparm,
double *x,
double *y,
double *dparm),
double *U,
int *ldu,
double *Sigma,
double *bnd,
double *V,
int *ldv,
double *tolin,
double *work,
int *lwork,
int *iwork,
int *liwork,
double *doption,
int *ioption,
int *info,
double *dparm,
int *iparm);
It's quite a beast. Good luck!
It might be worthwhile checking out Tim Davis's sparse linear algebra software: http://www.cise.ufl.edu/~davis/
Generally speaking I've found his software to be really useful, typically very efficient and robust.
It seems that he's been working on a sparse SVD package with a student, but I'm not sure what stage the project is at.
Hope this helps.
I'm translating some Fortran to our C# app and I'm trying to figure out what a bit of Fortran means at the top of a function.
DOUBLE PRECISION INF, DMIN, D12
DATA INF/1.D+300/
What would the value of INF be?
The D means "× 10???", or commonly known as the e in 1.e+300 in C#, but it's for double precision.
The DOUBLE PRECISION statement just defines 3 variables to be of type double.
The DATA statement
DATA X/Y/
translates to
X = Y;
in C#. Hence you get
double INF = 1.e+300, DMIN, D12;
Since INF is so large I believe it means "Infinity", in that case it's better to use the real IEEE infinity (double INF = double.PositiveInfinity, ...).
The code is declaring a constant called INF (i.e. infinity) with the value 10^300. You would want to substitute double.PositiveInfinity or double.MaxValue.
The code is in the style of FORTRAN IV or FORTRAN 77 rather than Fortran 90/95/2003.
Double Precision declares the variables to be double the precision of a regular real. I'm not sure that the FORTRAN standards of that era were extremely precise about what that meant, since there was a greater variety of numeric hardware then. Today, it will virtually always obtain an 8-byte real. The Data statement initializes the variable INF. The use of "D" in the constant "1.D+300", instead of E, is old FORTRAN to specify that the constant is double precision.
The Fortran (>=90) way of obtaining the largest positive double is:
INF = huge (1.0D+0)
The value would be 1.0e300, but I'm sure that what is intended is that it be set to the largest double value that can be expressed on the current CPU. so in C# that would be double.PositiveInfinity rather than some hard-coded value.