20

我需要经常使用matrix_vector_mult()which 将矩阵与向量相乘,下面是它的实现。

问题:有没有一种简单的方法可以显着加快速度,至少快两倍?

备注:1)矩阵大小约为300x50。它在运行期间不会改变。2) 它必须在 Windows 和 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);
    }
}
4

3 回答 3

24

这是理论上一个好的编译器应该自己做的事情,但是我尝试使用我的系统(g ++ 4.6.3)并通过手动展开 4 个乘法(每个矩阵大约 18us 而不是每个矩阵 34us):

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

但是,我希望这种级别的微优化的结果在系统之间会有很大差异。

于 2012-09-05T20:48:45.223 回答
5

正如甄亚所说,只需使用一个好的 BLAS 或矩阵数学库。

如果由于某种原因您不能这样做,请查看您的编译器是否可以展开和/或矢量化您的循环;假设您发布的函数可用于内联,确保rowscols在调用站点都是常量可能会有所帮助

如果您仍然无法获得所需的加速,您正在考虑手动展开,并使用扩展或内联汇编器进行矢量化。

于 2012-09-05T20:49:38.467 回答
0

如果大小是恒定的并且事先已知,则将其作为预编译器变量传递,这将允许编译器进行更充分的优化。

于 2012-09-05T20:54:18.193 回答