我的代码如下,在主函数中,我回忆了Mat_product
次的223440
函数,在整个运行时使用179ns
,23%
。
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
来描述矩阵,这会影响计算效率吗?
答案 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指令来优化代码。