Multiplicación matriz-vector sencilla y rápida en C / C++

Multiplicación matriz-vector sencilla y rápida en C / C++


Necesito un uso frecuente de matrix_vector_mult() que multiplica matriz por vector, y debajo está su implementación.


Pregunta:¿Existe una forma sencilla de hacerlo significativamente, al menos dos veces, más rápido?


Observaciones:1) El tamaño de la matriz es de unos 300x50. No cambia durante la ejecución
. 2) Debe funcionar tanto en Windows como en Linux.


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);
}
}

Respuestas:


Esto es algo que, en teoría, un buen compilador debería hacer solo, sin embargo, probé con mi sistema (g ++ 4.6.3) y obtuve aproximadamente el doble de velocidad en una matriz de 300x50 desenrollando a mano 4 multiplicaciones (alrededor de 18us por matriz en lugar de 34us por matriz):


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;
}

Sin embargo, espero que los resultados de este nivel de microoptimización varíen enormemente entre sistemas.


Algunas respuestas de código


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;
}