BLAS 矩阵向量乘法与向量矩阵乘法。一个作品;另一个失败
BLAS matrix-vector multiplication vs vector-matrix multiplication. One works; the other fails
在 Lapack 中使用 cgemv
BLAS lvl 2 函数时,我成功地进行了矩阵向量乘法运算,但是当我尝试转置时,我得到了一个错误的答案。你能指导我的错误吗? (我实际上使用的是 C 包装器,而不是 FORTRAN。)
我正在尝试
| 4+i 3 | | 3+2i | | 4+i 3 |^T | 3+2i |
| 14+3i 2 | * | 2 | (AND) | 14+3i 2 | * | 2 |
要清楚,第一个成功了。第二个给出了错误的输出。
/* config variables */
char normal = 'N';
char transpose = 'T';
integer m = 2;
complex alpha = {r:1,i:0};
complex beta = {r:0,i:0};
integer one = 1;
/* data buffers */
complex a[4] = {(complex){r:4, i:1},(complex){r:14, i:3},(complex){r:3, i:0},(complex){r:6, i:0}};
complex x[2] = {(complex){r:3, i:2},(complex){r:2, i:0}};
complex y[2];
/* execution */
cgemv_(&normal, &m, &m, &alpha, &a[0], &m, &x[0], &one, &beta, &y[0], &one);
cgemv_(&transpose, &m, &m, &alpha, &a[0], &m, &x[0], &one, &beta, &y[0], &one);
在第一个 cgemv_
调用之后,y
保持 16.0000+11.0000i 48.0000+37.0000i
,MATLAB 确认这是正确的。
但是在第二次 cgemv_
调用之后,y
保持 38.0000+17.0000i 21.0000+6.0000i
,而 MATLAB 表示它应该是 42.0000-1.0000i 21.0000+6.0000i
。我不知道哪里出了问题。
由于 2 向量乘以 2x2 矩阵,因此使用 pen and a piece of paper 执行运算并不太复杂。如果使用转置矩阵:
(4+i)*(3+2i)+(14+3i)*2=38+17i
好奇地:
(4-i)*(3+2i)+(14-3i)*2=42-i
所以MATLAB的输出很可能是使用complex conjugate transpose. The same output can be produced by BLAS if the TRANS
parameter of cgemv_
设置为'C'
得到的输出。
这是一个基于我们代码的示例代码,显示了 BLAS 对 TRANS
的不同值的实际计算结果。可以通过gcc main.c -o main -lblas -Wall
.
计算
#include <stdlib.h>
#include <stdio.h>
#include <complex.h>
extern int cgemv_(char* trans, int * m, int * n, float complex* alpha, float complex* A, int * lda,float complex * x, int* incx, float complex * beta, float complex * y,int* incy);
int main(void) {
/* config variables */
char normal = 'N';
char transpose = 'T';
char ctranspose = 'C';
int m = 2;
float complex alpha = 1.0+0.*I;
float complex beta = 0.0+0.*I;
int one = 1;
/* data buffers */
float complex a[4]= {4+1.*I,14+3.*I,3.+0.*I,6.+0.*I};
float complex x[2] = {3.+2.*I,2+0.*I};
float complex y[2];
/* execution */
float complex ye[2];
ye[0]=a[0]*x[0]+a[2]*x[1];
ye[1]=a[1]*x[0]+a[3]*x[1];
cgemv_(&normal, &m, &m, &alpha, &a[0], &m, &x[0], &one, &beta, &y[0], &one);
printf("N\n");
printf("y[0]=%2.6f + %2.6f I expected %6f + %6f I\n",creal(y[0]),cimag(y[0]),creal(ye[0]),cimag(ye[0]));
printf("y[1]=%2.6f + %2.6f I expected %6f + %6f I\n",creal(y[1]),cimag(y[1]),creal(ye[1]),cimag(ye[1]));
//float complex ye[2];
ye[0]=a[0]*x[0]+a[1]*x[1];
ye[1]=a[2]*x[0]+a[3]*x[1];
cgemv_(&transpose, &m, &m, &alpha, &a[0], &m, &x[0], &one, &beta, &y[0], &one);
printf("T\n");
printf("y[0]=%2.6f + %2.6f I expected %6f + %6f I\n",creal(y[0]),cimag(y[0]),creal(ye[0]),cimag(ye[0]));
printf("y[1]=%2.6f + %2.6f I expected %6f + %6f I\n",creal(y[1]),cimag(y[1]),creal(ye[1]),cimag(ye[1]));
ye[0]=conj(a[0])*x[0]+conj(a[1])*x[1];
ye[1]=conj(a[2])*x[0]+conj(a[3])*x[1];
cgemv_(&ctranspose, &m, &m, &alpha, &a[0], &m, &x[0], &one, &beta, &y[0], &one);
printf("C\n");
printf("y[0]=%2.6f + %2.6f I expected %6f + %6f I\n",creal(y[0]),cimag(y[0]),creal(ye[0]),cimag(ye[0]));
printf("y[1]=%2.6f + %2.6f I expected %6f + %6f I\n",creal(y[1]),cimag(y[1]),creal(ye[1]),cimag(ye[1]));
return 0;
}
在 Lapack 中使用 cgemv
BLAS lvl 2 函数时,我成功地进行了矩阵向量乘法运算,但是当我尝试转置时,我得到了一个错误的答案。你能指导我的错误吗? (我实际上使用的是 C 包装器,而不是 FORTRAN。)
我正在尝试
| 4+i 3 | | 3+2i | | 4+i 3 |^T | 3+2i |
| 14+3i 2 | * | 2 | (AND) | 14+3i 2 | * | 2 |
要清楚,第一个成功了。第二个给出了错误的输出。
/* config variables */
char normal = 'N';
char transpose = 'T';
integer m = 2;
complex alpha = {r:1,i:0};
complex beta = {r:0,i:0};
integer one = 1;
/* data buffers */
complex a[4] = {(complex){r:4, i:1},(complex){r:14, i:3},(complex){r:3, i:0},(complex){r:6, i:0}};
complex x[2] = {(complex){r:3, i:2},(complex){r:2, i:0}};
complex y[2];
/* execution */
cgemv_(&normal, &m, &m, &alpha, &a[0], &m, &x[0], &one, &beta, &y[0], &one);
cgemv_(&transpose, &m, &m, &alpha, &a[0], &m, &x[0], &one, &beta, &y[0], &one);
在第一个 cgemv_
调用之后,y
保持 16.0000+11.0000i 48.0000+37.0000i
,MATLAB 确认这是正确的。
但是在第二次 cgemv_
调用之后,y
保持 38.0000+17.0000i 21.0000+6.0000i
,而 MATLAB 表示它应该是 42.0000-1.0000i 21.0000+6.0000i
。我不知道哪里出了问题。
由于 2 向量乘以 2x2 矩阵,因此使用 pen and a piece of paper 执行运算并不太复杂。如果使用转置矩阵:
(4+i)*(3+2i)+(14+3i)*2=38+17i
好奇地:
(4-i)*(3+2i)+(14-3i)*2=42-i
所以MATLAB的输出很可能是使用complex conjugate transpose. The same output can be produced by BLAS if the TRANS
parameter of cgemv_
设置为'C'
得到的输出。
这是一个基于我们代码的示例代码,显示了 BLAS 对 TRANS
的不同值的实际计算结果。可以通过gcc main.c -o main -lblas -Wall
.
#include <stdlib.h>
#include <stdio.h>
#include <complex.h>
extern int cgemv_(char* trans, int * m, int * n, float complex* alpha, float complex* A, int * lda,float complex * x, int* incx, float complex * beta, float complex * y,int* incy);
int main(void) {
/* config variables */
char normal = 'N';
char transpose = 'T';
char ctranspose = 'C';
int m = 2;
float complex alpha = 1.0+0.*I;
float complex beta = 0.0+0.*I;
int one = 1;
/* data buffers */
float complex a[4]= {4+1.*I,14+3.*I,3.+0.*I,6.+0.*I};
float complex x[2] = {3.+2.*I,2+0.*I};
float complex y[2];
/* execution */
float complex ye[2];
ye[0]=a[0]*x[0]+a[2]*x[1];
ye[1]=a[1]*x[0]+a[3]*x[1];
cgemv_(&normal, &m, &m, &alpha, &a[0], &m, &x[0], &one, &beta, &y[0], &one);
printf("N\n");
printf("y[0]=%2.6f + %2.6f I expected %6f + %6f I\n",creal(y[0]),cimag(y[0]),creal(ye[0]),cimag(ye[0]));
printf("y[1]=%2.6f + %2.6f I expected %6f + %6f I\n",creal(y[1]),cimag(y[1]),creal(ye[1]),cimag(ye[1]));
//float complex ye[2];
ye[0]=a[0]*x[0]+a[1]*x[1];
ye[1]=a[2]*x[0]+a[3]*x[1];
cgemv_(&transpose, &m, &m, &alpha, &a[0], &m, &x[0], &one, &beta, &y[0], &one);
printf("T\n");
printf("y[0]=%2.6f + %2.6f I expected %6f + %6f I\n",creal(y[0]),cimag(y[0]),creal(ye[0]),cimag(ye[0]));
printf("y[1]=%2.6f + %2.6f I expected %6f + %6f I\n",creal(y[1]),cimag(y[1]),creal(ye[1]),cimag(ye[1]));
ye[0]=conj(a[0])*x[0]+conj(a[1])*x[1];
ye[1]=conj(a[2])*x[0]+conj(a[3])*x[1];
cgemv_(&ctranspose, &m, &m, &alpha, &a[0], &m, &x[0], &one, &beta, &y[0], &one);
printf("C\n");
printf("y[0]=%2.6f + %2.6f I expected %6f + %6f I\n",creal(y[0]),cimag(y[0]),creal(ye[0]),cimag(ye[0]));
printf("y[1]=%2.6f + %2.6f I expected %6f + %6f I\n",creal(y[1]),cimag(y[1]),creal(ye[1]),cimag(ye[1]));
return 0;
}