Einfache und schnelle Matrix-Vektor-Multiplikation in C / C++

Einfache und schnelle Matrix-Vektor-Multiplikation in C / C++


Ich brauche häufig matrix_vector_mult() die Matrix mit Vektor multipliziert, und unten ist ihre Implementierung.


Frage:Gibt es eine einfache Möglichkeit, es deutlich, mindestens zweimal, schneller zu machen?


Bemerkungen:1) Die Größe der Matrix beträgt etwa 300x50. Sie ändert sich während des
Laufs nicht. 2) Es muss sowohl unter Windows als auch unter Linux funktionieren.


double vectors_dot_prod(const double *x, const double *y, int n)
{
double res = 0.0;
int i;
for (i = 0; i < n; i++)
{
res += x[i] * y[i];
}
return res;
}
void matrix_vector_mult(const double **mat, const double *vec, double *result, int rows, int cols)
{ // in matrix form: result = mat * vec;
int i;
for (i = 0; i < rows; i++)
{
result[i] = vectors_dot_prod(mat[i], vec, cols);
}
}

Antworten:


Dies ist etwas, das ein guter Compiler theoretisch selbst tun sollte, aber ich habe es mit meinem System (g++ 4.6.3) versucht und bei einer 300x50-Matrix etwa die doppelte Geschwindigkeit erreicht, indem ich 4 Multiplikationen von Hand entrollte (etwa 18 us pro Matrix statt 34us pro Matrix):


double vectors_dot_prod2(const double *x, const double *y, int n)
{
double res = 0.0;
int i = 0;
for (; i <= n-4; i+=4)
{
res += (x[i] * y[i] +
x[i+1] * y[i+1] +
x[i+2] * y[i+2] +
x[i+3] * y[i+3]);
}
for (; i < n; i++)
{
res += x[i] * y[i];
}
return res;
}

Ich gehe jedoch davon aus, dass die Ergebnisse dieser Mikrooptimierung zwischen den Systemen stark variieren werden.


Einige Code-Antworten


double vectors_dot_prod(const double *x, const double *y, int n) {
double res = 0.0;
int i;
for (i = 0;
i <
n;
i++)
{
res += x[i] * y[i];
}
return res;
} void matrix_vector_mult(const double **mat, const double *vec, double *result, int rows, int cols) { // in matrix form: result = mat * vec;
int i;
for (i = 0;
i <
rows;
i++)
{
result[i] = vectors_dot_prod(mat[i], vec, cols);
} }
double vectors_dot_prod2(const double *x, const double *y, int n) {
double res = 0.0;
int i = 0;
for (;
i <= n-4;
i+=4)
{
res += (x[i] * y[i] +
x[i+1] * y[i+1] +
x[i+2] * y[i+2] +
x[i+3] * y[i+3]);
}
for (;
i <
n;
i++)
{
res += x[i] * y[i];
}
return res;
}