【问题标题】:Loop Unrolling in C [closed]C中的循环展开[关闭]
【发布时间】:2014-07-31 19:37:26
【问题描述】:

我应该在C中优化一个循环。循环如下:

#define N_TIMES     600000
#define ARRAY_SIZE   10000

for (i = 0; i < N_TIMES; i++) {

            for (ptr = array; ptr < &array[ARRAY_SIZE]; ptr+=2) {

                    sum += *ptr;
                    sum1 += *ptr + 1;
            }

    }

sum += sum1;

我们已经了解了 3 种优化类型:循环展开、循环拆分和在循环中使用指针。我已经成功地实现了指针和拆分(现在循环的运行速度比以前快了大约 50%),但是每次我尝试展开循环时,速度都没有提高。这是我一直在尝试的:

for (i = 0; i < N_TIMES; i++) {

            for (ptr = array; ptr < &array[ARRAY_SIZE]; ptr+=4) {

                    sum += *ptr;
                    sum += *ptr + 1;
                    sum1 += *ptr + 2;
                    sum1 += *ptr + 3;
            }

    }

这似乎什么也没做。我只是完全误解了循环展开是什么,还是我应该在循环声明中继续将 ptr 增加 2 直到它起作用?感谢您提供任何和所有帮助!

另外,我知道编译器在当今世界进行大部分优化,但这是一个类的分配,我必须这样做。

【问题讨论】:

  • 你是如何编译你的代码的?如果您包含任何 -O 标志,并且在编译时已知 N_TIMES,则很有可能已经展开循环。
  • 仅供参考,您的两个循环不等效。在展开的版本中,sum 应该得到 *ptr*ptr+2sum1 应该得到 *ptr+1*ptr+3
  • 还有其他人发现明显的问题吗? :)
  • 请注意,您有一个运算符优先级问题:sum += *ptr + 1; 应该是 sum += *(ptr + 1);,对于其他偏移量也是如此。

标签: c loops optimization


【解决方案1】:

第一,您没有正确展开循环。应该是:

for (i = 0; i < N_TIMES; i++) {
    for (ptr = array; ptr < &array[ARRAY_SIZE]; ptr+=4) {
        sum += *ptr;
        sum1 += *ptr + 1;
        sum += *(ptr+2);
        sum1 += *(ptr+2) + 1;
    }
}

显然,原始循环可能不是您真正想要的。但是因为你翻译不正确,如果数组元素是双倍的(如果你告诉我们会很好),原始循环每次迭代执行 3 个浮点操作,错误展开的循环每次迭代执行 7 个浮点操作,显然是一半多次迭代,仍然多出 16.7% 的浮点运算。

【讨论】:

  • 我的错;总和确实是两倍。
  • 我认为您误解了代码的意图(可能是由于原始代码中缺少括号)-每次迭代需要对 4 个连续的位置求和。
  • 嗯,展开的循环应该做的事情和原来的循环完全一样,而不是原来的循环打算做的事情。
猜你喜欢
  • 2020-12-19
  • 2016-08-03
  • 1970-01-01
  • 2011-07-28
  • 1970-01-01
  • 2015-03-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多