我必须在C ++程序中对矩阵进行矩阵布尔乘法,我想优化它。 矩阵是对称的,所以我认为要逐行进行乘法以减少缓存未命中。 我以这种方式为矩阵分配了空间:
matrix=new bool*[dimension];
for (i=0; i<dimension; i++) {
matrix[i]=new bool[dimension];
}
乘法如下:
for (m=0; m<dimension; m++) {
for (n=0; n<dimension; n++) {
for (k=0; k<dimension; k++) {
temp=mat[m][k] && mat[n][k];
B[m][n]= B[m][n] || temp;
...
我对这个版本进行了一些计算时间的测试,并且通过列乘法对另一个版本进行了测试,如下所示
for (m=0; m<dimension; m++) {
for (n=0; n<dimension; n++) {
for (k=0; k<dimension; k++) {
temp=mat[m][k] && mat[k][n];
B[m][n]= B[m][n] || temp;
...
我在1000x1000矩阵上进行了测试结果显示第二个版本(逐列)比前一个版本更快。 你能告诉我为什么吗?不应该在第一个算法中的失误较少吗?
答案 0 :(得分:1)
加快建议。在内循环中:
Bmn = false;
for (k=0; k<dimension; k++) {
if ((Bmn = mat[m][k] && mat[k][n])) {
k = dimension; // exit for-k loop
}
}
B[m][n]= Bmn
答案 1 :(得分:1)
在第一种乘法方法中,布尔矩阵的行连续存储在存储器中,并且还连续访问,以便预取能够完美地工作。在第二种方法中,访问元素(n,0)时获取的高速缓存行在访问(n + 1,0)时已经可以被逐出。这是否实际发生取决于您运行代码的体系结构及其缓存层次结构属性。在我的机器上,对于足够大的矩阵,第一种方法确实更快。
至于加速计算:不要使用逻辑运算符,因为它们被评估为惰性,因此可能发生分支错误预测。一旦B [m] [n]变为真,内循环就可以提前退出。你可能不想使用布尔值,而是考虑使用整数。这样,您可以同时在内部循环中组合32或64个元素,并可能使用矢量化。如果您的矩阵相当稀疏,那么您可能需要考虑切换到稀疏矩阵数据结构。同样改变循环的顺序也有助于引入阻塞。但是,任何性能优化都特定于体系结构和输入矩阵类。