【问题标题】:for loop optimize in CC语言中的for循环优化
【发布时间】:2017-06-08 16:36:13
【问题描述】:

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

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。

【问题讨论】:

  • 我猜你想优化速度......好吧,一件事是通过将计算带入外循环并将值分配给内循环每次都停止计算 i*dim将在内部循环中使用的变量。
  • 你知道dim最常见的值是什么吗?

标签: c for-loop optimization


【解决方案1】:

我的速度比原始代码快了 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];
          }
        }

}

【讨论】:

    【解决方案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 个语句的序列上。对这些语句重新排序可能会为选定的架构带来额外的改进,而对其他架构的运行速度会更慢。

    【讨论】:

    • 你的代码比上面的代码快2.3倍。我们可以做些什么来加快速度?缓存阻塞?
    • @SevkiBekir:你知道dim最常见的值是什么吗?如果代码主要用于固定值dim,则特殊大小写此值将允许编译器展开循环并删除大多数乘法。
    • 最常见的值为 8。
    • @SevkiBekir:我用一些额外的想法更新了答案,试试看你是否能提高性能。
    • 感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 2018-12-23
    • 1970-01-01
    • 2014-09-28
    • 1970-01-01
    • 2017-09-01
    • 2020-08-28
    • 1970-01-01
    • 2019-01-02
    相关资源
    最近更新 更多