I am writing a function which calls Fortran functions for complex matrix matrix multiplication. I am calling the CGEMM_ and ZGEMM_ functions for complex multiplication. Since all xGEMM_ functions are essentially the same I copied the code from SGEMM_ to CGEMM__ and ZGEMM_. The only change made were the respective data types. The SGEMM_ and DGEMM_ functions are working fine but CGEMM_ throws the error. All inputs are the same as well.
** On entry to CGEMM parameter number 13 had an illegal value
and zgemm_ throws
** On entry to ZGEMM parameter number 1 had an illegal value
I really have no idea what's going on. Is this some kind of bug in the liblapack package? I am using liblapack-dev package. I made a smaller version of my big code and i am still getting the same error with CGEMM_.
I am running a 32-bit system and was wondering if that was the problem.
Code:
#include<iostream>
using namespace std;
#include<stdlib.h>
#include<string.h>
#include<complex>
typedef complex<float> c_float;
extern "C"
{c_float cgemm_(char*,char*,int*,int*,int*,c_float*, c_float[0],int*,c_float[0],int*,c_float*,c_float[0],int*);//Single Complex Matrix Multiplication
}
c_float** allocate(int rows, int columns)
{
c_float** data;
// Allocate Space
data = new c_float*[columns]; //Allocate memory for using multidimensional arrays in column major format.
data[0] = new c_float[rows*columns];
for (int i=0; i<columns; i++)
{
data[i] = data[0] + i*rows;
}
// Randomize input
for (int i=0; i<columns; i++)
{for (int j=0; j<rows; j++)
{
data[j][i] =complex<double>(drand48()*10 +1,drand48()*10 +1); //Randomly generated matrix with values in the range [1 11)
}
}
return(data);
}
// Destructor
void dest(c_float** data)
{
delete [] data[0];
delete [] data;
}
// Multiplication
void mult(int rowsA,int columnsA, int rowsB,int columnsB)
{
c_float **matA,**matB,**matC;
char transA, transB;
int m,n,k,LDA,LDB,LDC;
c_float *A,*B,*C;
c_float alpha(1.0,0.0);
c_float beta(0.0,0.0);
matA = allocate(rowsA,columnsA);
matB = allocate(rowsB,columnsB);
matC = allocate(rowsA,columnsB);
transA = 'N';
transB = 'N';
A = matA[0];
B = matB[0];
m = rowsA;
n = columnsB;
C = matC[0];
k = columnsA;
LDA = m;
LDB = k;
LDC = m;
cout<<"Matrix A"<<endl;
for (int i=0; i<rowsA; i++)
{for (int j=0; j<columnsA; j++)
{
cout<<matA[i][j];
cout<<" ";
}cout<<endl;
}
cout<<"Matrix B"<<endl;
for (int i=0; i<rowsB; i++)
{for (int j=0; j<columnsB; j++)
{
cout<<matB[i][j];
cout<<" ";
}cout<<endl;
}
cgemm_(&transA,&transB,&m,&n,&k,&alpha,A,&LDA,B,&LDB,&beta,C,&LDC);
cout<<"Matrix A*B"<<endl;
for (int i=0; i<rowsA; i++)
{for (int j=0; j<columnsB; j++)
{
cout<<matC[i][j];
cout<<"";
}
cout<<endl;
}
dest(matA);
dest(matB);
dest(matC);
}
main()
{
mult (2,2,2,2);
}
The output and valgrind report are as follows:
-----------------------------------------
Compilation using g++ -g -o matrix Matrix_multiplication.cpp -lblas -llapack -lgfortran
./matrix gives
Matrix A
(1.00985,1) (1.91331,4.64602)
(2.76643,1.41631) (5.87217,1.92298)
Matrix B
(5.54433,6.2675) (6.6806,10.3173)
(9.31292,3.33178) (1.50832,6.56094)
** On entry to CGEMM parameter number 1 had an illegal value
Valgrind output looks like
==4710== Memcheck, a memory error detector
==4710== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==4710== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==4710== Command: ./o
==4710== Parent PID: 3337
==4710==
==4710== Conditional jump or move depends on uninitialised value(s)
==4710== at 0x46E5096: lsame_ (in /usr/lib/atlas-base/atlas/libblas.so.3.0)
==4710== by 0x46DD683: cgemm_ (in /usr/lib/atlas-base/atlas/libblas.so.3.0)
==4710== by 0x8048C7E: mult(int, int, int, int) (Matrix_multiplication.cpp:83)
==4710== by 0x8048D70: main (Matrix_multiplication.cpp:102)
==4710== Uninitialised value was created by a stack allocation
==4710== at 0x8048A18: mult(int, int, int, int) (Matrix_multiplication.cpp:43)
==4710==
==4710== Conditional jump or move depends on uninitialised value(s)
==4710== at 0x46DD686: cgemm_ (in /usr/lib/atlas-base/atlas/libblas.so.3.0)
==4710== by 0x8048C7E: mult(int, int, int, int) (Matrix_multiplication.cpp:83)
==4710== by 0x8048D70: main (Matrix_multiplication.cpp:102)
==4710== Uninitialised value was created by a stack allocation
==4710== at 0x8048A18: mult(int, int, int, int) (Matrix_multiplication.cpp:43)
==4710==
==4710== Conditional jump or move depends on uninitialised value(s)
==4710== at 0x46E5096: lsame_ (in /usr/lib/atlas-base/atlas/libblas.so.3.0)
==4710== by 0x46DD7B1: cgemm_ (in /usr/lib/atlas-base/atlas/libblas.so.3.0)
==4710== by 0x8048C7E: mult(int, int, int, int) (Matrix_multiplication.cpp:83)
==4710== by 0x8048D70: main (Matrix_multiplication.cpp:102)
==4710== Uninitialised value was created by a stack allocation
==4710== at 0x8048A18: mult(int, int, int, int) (Matrix_multiplication.cpp:43)
==4710==
==4710== Conditional jump or move depends on uninitialised value(s)
==4710== at 0x46DD7B4: cgemm_ (in /usr/lib/atlas-base/atlas/libblas.so.3.0)
==4710== by 0x8048C7E: mult(int, int, int, int) (Matrix_multiplication.cpp:83)
==4710== by 0x8048D70: main (Matrix_multiplication.cpp:102)
==4710== Uninitialised value was created by a stack allocation
==4710== at 0x8048A18: mult(int, int, int, int) (Matrix_multiplication.cpp:43)
==4710==
==4710== Conditional jump or move depends on uninitialised value(s)
==4710== at 0x46E5096: lsame_ (in /usr/lib/atlas-base/atlas/libblas.so.3.0)
==4710== by 0x46DD859: cgemm_ (in /usr/lib/atlas-base/atlas/libblas.so.3.0)
==4710== by 0x8048C7E: mult(int, int, int, int) (Matrix_multiplication.cpp:83)
==4710== by 0x8048D70: main (Matrix_multiplication.cpp:102)
==4710== Uninitialised value was created by a stack allocation
==4710== at 0x8048A18: mult(int, int, int, int) (Matrix_multiplication.cpp:43)
==4710==
==4710== Conditional jump or move depends on uninitialised value(s)
==4710== at 0x46DD85C: cgemm_ (in /usr/lib/atlas-base/atlas/libblas.so.3.0)
==4710== by 0x8048C7E: mult(int, int, int, int) (Matrix_multiplication.cpp:83)
==4710== by 0x8048D70: main (Matrix_multiplication.cpp:102)
==4710== Uninitialised value was created by a stack allocation
==4710== at 0x8048A18: mult(int, int, int, int) (Matrix_multiplication.cpp:43)
==4710==
==4710==
==4710== HEAP SUMMARY:
==4710== in use at exit: 120 bytes in 6 blocks
==4710== total heap usage: 43 allocs, 37 frees, 13,897 bytes allocated
==4710==
==4710== LEAK SUMMARY:
==4710== definitely lost: 0 bytes in 0 blocks
==4710== indirectly lost: 0 bytes in 0 blocks
==4710== possibly lost: 0 bytes in 0 blocks
==4710== still reachable: 120 bytes in 6 blocks
==4710== suppressed: 0 bytes in 0 blocks
==4710== Rerun with --leak-check=full to see details of leaked memory
==4710==
==4710== For counts of detected and suppressed errors, rerun with: -v
==4710== ERROR SUMMARY: 6 errors from 6 contexts (suppressed: 0 from 0)
EDIT: The question was modified with a code that can be run. The problem remains the same and the nature of the question has not changed.
I don't see the lengths of the
transA
ortransB
strings being passed to thexgemm_
call.Character
dummies in Fortran are accompanied by a 'hidden' length argument. The convention used by GCC 4.9.0, for example, for this is described more here:https://gcc.gnu.org/onlinedocs/gcc-4.9.0/gfortran/Argument-passing-conventions.html.
The positioning of these hidden arguments in the argument list is platform dependent. On Linux they are placed after all the explicit arguments.
Consider
s.f90
and
main.c
For running on Linux I am passing
1
as the (hidden in Fortran) third argument fors
, representing the length of my string.Compiling and running with
gfortran
gives meSo probably your
xgemm_
calls should be...,&LDC,1,1);
?