gpt4 book ai didi

c++ - 使用 dgemm/dgemv 的矩阵 vector 积

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:09:33 28 4
gpt4 key购买 nike

在 C++ 中使用 Lapack 让我有点头疼。我发现为 fortran 定义的函数有点古怪,所以我尝试在 C++ 上创建一些函数,以便我更容易阅读正在发生的事情。

无论如何,我没有让矩阵 vector 乘积如我所愿地工作。这是该程序的一个小示例。

smallmatlib.cpp:

#include <cstdio>
#include <stdlib.h>


extern "C"{
// product C= alphaA.B + betaC
void dgemm_(char* TRANSA, char* TRANSB, const int* M,
const int* N, const int* K, double* alpha, double* A,
const int* LDA, double* B, const int* LDB, double* beta,
double* C, const int* LDC);
// product Y= alphaA.X + betaY
void dgemv_(char* TRANS, const int* M, const int* N,
double* alpha, double* A, const int* LDA, double* X,
const int* INCX, double* beta, double* C, const int* INCY);
}

void initvec(double* v, int N){
for(int i= 0; i<N; ++i){
v[i]= 0.0;
}
}

void matvecprod(double* A, double* v, double* u, int N){
double alpha= 1.0, beta= 0.0;
char no= 'N', tr= 'T';
int m= N, n= N, lda= N, incx= N, incy= N;
double* tmp= new double[N];
initvec(tmp, N);
dgemv_(&no,&m,&n,&alpha,A,&lda,v,&incx,&beta,tmp,&incy);
for(int i= 0; i<N; ++i){
u[i]= tmp[i];
}
delete [] tmp;
}

void vecmatprod(double* v, double* A, double* u, int N){
double alpha= 1.0, beta= 0.0;
char no= 'N', tr= 'T';
int m= N, n= 1, k= N, lda= N, ldb= N, ldc= N;
double* tmp= new double[N];
initvec(tmp, N);
dgemm_(&no,&no,&m,&n,&k,&alpha,A,&lda,v,&ldb,&beta,tmp,&ldc);
for(int i= 0; i<N; ++i){
u[i]= tmp[i];
}
delete [] tmp;
}

smallmatlib.h:

#ifndef SMALLMATLIB_H
#define SMALLMATLIB_H

void initvec(double* v, int N);

void matvecprod(double* A, double* v, double* u, int N);

void vecmatprod(double* v, double* A, double* u, int N);

#endif

smallmatlab.cpp:

#include "smallmatlib.h"
#include <cstdio>
#include <stdlib.h>
#define SIZE 2

int main(){
double A[SIZE*SIZE]=
{ 1,2,
3,4 };
double v[SIZE]= {2,5.2};
double u[SIZE]= {0,0};
matvecprod(A,v,u,SIZE);
printf("%f %f\n",u[0],u[1]);
vecmatprod(v,A,u,SIZE);
printf("%f %f\n",u[0],u[1]);
return 0;
}

编译:
g++ -c smallmatlib.cpp
g++ smallmatlab.cpp smallmatlib.o -L/usr/local/lib -lclapack -lcblas

现在函数 matvecprod 是问题所在。使用示例矩阵 A 和示例 vector v,它应该产生如下输出

12.4..    26.8..

而是打印出来

2.00..    0.00..

我试图用 dgemm 和 dgemv 产生正确的结果,但没能成功。我有一种预感,我的变量 incx 和 incy 没有正确的值,但很难找到我能理解的解释。

一个较小的问题是目前我不能像这样使用它们 vecmatprod(v,A,v,SIZE)- 也就是说,我总是必须定义 vector u,它将单独保存结果,并调用 vecmatprod(v,A,u,SIZE)。任何帮助将不胜感激。

顺便说一下,我也是 C++ 的初学者,所以我很感激您对我的代码提出的任何批评/建议。

最佳答案

你是对的,问题出在 incx 值上——它应该是 1,看看 reference .

INCX is INTEGER
On entry, INCX specifies the increment for the elements of
X. INCX must not be zero.

因此,当 vector x 的值不是一个一个地放置时(例如,当您只想使用实部的复数 vector 时),应该使用该值。

此外,您不能将 vecmatprod(v,A,v,SIZE)v 同时用作 xy。这是因为矩阵 vector 乘法的工作原理(参见 wikipedia 例如)。您始终需要原始 x 的值才能产生正确的结果。小例子:

y = A * x 

在哪里

y = [ y1 y2 ]
A = [ [a11 a12] [a21 a22] ]
x = [ x1 x2 ]

然后我们像这样计算y

y1 = a11 * x1 + a12 * x2
y2 = a21 * x1 + a22 * x2

你可以看到,当我们计算 y2 时,我们需要 x1x2,但是如果你使用 x = A * x(没有临时 vector )你将用 y1 替换 x1 从而产生错误的答案。

关于c++ - 使用 dgemm/dgemv 的矩阵 vector 积,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28654438/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com