在C中进行循环优化

时间:2017-01-24 01:46:27

标签: c for-loop optimization

我必须在下面针对循环代码进行优化。我能怎么做?有什么建议吗?我试图展开循环,但它没有改变任何东西。 感谢。

G是图的矩阵(有向或无向图) 代码如下:

void col_convert(int dim, int *G)
{
    int i, j;
    for (i = 0; i < dim; i++)
        for (j = 0; j < dim; j++)
            G[j*dim+i] = G[j*dim+i] || G[i*dim+j];
}

修改 最常见的维度是8。

2 个答案:

答案 0 :(得分:2)

通过注意操作是对称的,可以将迭代次数减半:

void naive_col_convert(int dim, int *G) {
    for (int i = 0; i < dim; i++) {
        G[i * dim + i] = G[i * dim + i] != 0;
        for (int j = i + 1; j < dim; j++) {
            G[i * dim + j] = G[j * dim + i] = G[j * dim + i] || G[i * dim + j];
        }
    }
}

编辑:如果最常见的值为8,请使用-O3尝试以下代码。编译器应该能够从相同的源代码为特殊情况生成有效的代码。

void naive_col_convert(int dim, int *G) {
    if (dim == 8) {
    #define dim 8
        for (int i = 0; i < dim; i++) {
            G[i * dim + i] = G[i * dim + i] != 0;
            for (int j = i + 1; j < dim; j++) {
                G[i * dim + j] = G[j * dim + i] = G[j * dim + i] || G[i * dim + j];
            }
        }
    #undef dim
    } else {
        for (int i = 0; i < dim; i++) {
            G[i * dim + i] = G[i * dim + i] != 0;
            for (int j = i + 1; j < dim; j++) {
                G[i * dim + j] = G[j * dim + i] = G[j * dim + i] || G[i * dim + j];
            }
        }
    }
}

如果性能改进不显着,您可以手动将循环展开到36个语句的序列上。对这些语句进行重新排序可能会对选定的体系结构产生额外的改进,而对其他语句的操作则会更慢。

答案 1 :(得分:0)

我比原始代码加速了5.4倍。谢谢大家。

这就是答案:

void col_convert(int dim, int *G)
{

      int i, j,dimj,dimi,nj,ni;

      for (i = 0; i <= dim-8; i +=8){
          ni = dim * i;
          for (j = 0; j < dim; j++)
          {
              nj = j * dim ;
              dimj = nj + i;
              dimi = ni + j;
              G[dimj] |= G[dimi];

              dimj += 1;
              dimi += dim;
              G[dimj] |= G[dimi];

              dimj += 1;
              dimi += dim;
              G[dimj] |= G[dimi];

              dimj += 1;
              dimi += dim;
              G[dimj] |= G[dimi];

              dimj += 1;
              dimi += dim;
              G[dimj] |= G[dimi];

              dimj += 1;
              dimi += dim;
              G[dimj] |= G[dimi];

              dimj += 1;
              dimi += dim;
              G[dimj] |= G[dimi];

              dimj += 1;
              dimi += dim;
              G[dimj] |= G[dimi];
          }
      }

      // Use the normal loop for any remaining elements
      for (; i < dim; i++){
        ni = i * dim;

          for (j = 0; j < dim; j++){
            nj = j * dim;
            dimj = nj + i;
            dimi = ni + j;
            G[dimj] |= G[dimi];
          }
        }

}