有什么方法可以优化C语言中的矩阵乘法?

时间:2019-01-22 09:25:10

标签: c optimization

我的代码如下,在主函数中,我回忆了Mat_product次的223440函数,在整个运行时使用179ns23%

struct Matrix_SE3 {
    float R[3][3];
    double P[3];  //here i need use double type.
};

struct Matrix_SE3 Mat_product(struct Matrix_SE3 A, struct Matrix_SE3 B) {
    struct Matrix_SE3 result = { { { 0, 0, 0 }, { 0, 0, 0 }, { 0, 0, 0 } }, { 0,
            0, 0 } };
    for (int i = 0; i < 3; i++) {
        result.P[i] += A.P[i];
        for (int j = 0; j < 3; j++) {
            result.P[i] += A.R[i][j] * B.P[j];
            for (int k = 0; k < 3; k++)
                result.R[i][j] += A.R[i][k] * B.R[k][j];
        }
    }
    return result;
}

其中$ R $是旋转矩阵,而$ P $表示位置,该函数是在两个特殊的欧几里德组$ SE(3)$矩阵相乘并返回$ SE(3)$矩阵的情况下计算的。

也许这是Optimized matrix multiplication in C的副本,不同之处是我的代码使用struct来描述矩阵,这会影响计算效率吗?

1 个答案:

答案 0 :(得分:1)

不确定代码中的P和R参数是什么,但是绝对不要将ijk排序用于矩阵乘法。

由于行顺序较大,因此在您的内部循环中访问B.R [k] [j]时,即使使用较小的矩阵,许多访问也会导致高速缓存未命中,从而显着降低性能。

执行矩阵乘法的正确方法是按照ikj顺序进行迭代。

for (int i = 0; i < 3; i++) {
    double r;
    result.P[i] += A.P[i];
    for (int k = 0; k < 3; k++) {
        r=A.R[i][k];
        for (int j = 0; j < 3; j++) {
            result.P[i] += A.R[i][j] * B.P[j];  
            result.R[i][j] += r * B.R[k][j];
        }
    }
}

所有访问将按行主要顺序正确执行,并将受益于缓存行为。

并且不要忘记使用-O3优化。大多数编译器将使用sse / avx指令来优化代码。