克++,基于对和量化范围(g++ , range based for and vectorizati

2019-10-18 04:04发布

考虑以下基于范围在C ++ 11环

for ( T k : j )
{
  ...
}

还有g++clang++优化参数,可以加快编译的代码?

我不是在谈论任何for循环,我只考虑这个新的C ++ 11的构建。

Answer 1:

优化的循环是很少有关优化的实际循环迭代的代码( for ( T k : j )在这种情况下),但非常关注优化什么是循环。

现在,由于这是...在这种情况下,这是不可能的说,如果,例如,展开循环会帮助或声明的内部函数[或简单地移动它们,这样编译器可以看到他们,并把他们在线],使用自动向量化,或者使用循环中完全不同的算法。

在更详细一点上段的实施例:

  1. 展开循环 - 主要做几个循环迭代,而不必返回到循环的开始。 这是最有用的,当环含量非常小。 有自动展开,在编译器中展开,也可以手动展开的代码,通过简单地在每个循环迭代做,也就是说,四个项目,然后踩着四个项目向前在每个循环变量更新或更新迭代多次循环本身[但当然这意味着不使用for循环的基于范围的]。
  2. 内联函数 - 编译器会采取(通常很小)的功能,并将它们放到循环本身,而不是通话。 这样可以节省花费处理器叫唤在另一地点的代码,并返回的时间。 大多数编译器只能这样做对于那些在编译过程中“看得见”的编译器功能 - 所以源,必须为在同一个源文件,或者是包含被编译源文件中的头文件。
  3. 自动向量化-使用SSE,MMX或AVX指令处理在一个指令(例如,一个SSE指令可以添加四个多个数据项float值以另外四个float在一个指令)。 这比一次对单个数据项运行速度更快(大部分时间,有时是因为尝试不同的数据项合并,然后整理出云当计算完成,其中额外的复杂性没有好处)。
  4. 选择不同的算法 - 经常有几种方法来解决特定的问题。 根据您所想要达到的目的,一个for循环[什么样的]可能无法在第一时间正确的解决方案,或代码内循环或许可以用更聪明的方式来计算/重新安排/什么,它-does达到你需要的结果。

但是...实在太含糊地说,如果有的话,上述解决方案将努力提高你的代码。



Answer 2:

GCC 关于自动矢量文件没有提及的基于任何范围内for循环。 此外,它的代码归结为:

{
    auto && __range = range_expression ;
    for (auto __begin = begin_expr,
                __end = end_expr;
            __begin != __end; ++__begin) {
        range_declaration = *__begin;
        loop_statement
    }
}

所以,从技术上讲,任何标志帮助自动矢量化在这种常规的结构for基于相似范围应自动向量化for循环。 我真正做到这一点的编译器只能翻译基于范围的for循环定期for循环,然后让自动矢量做的工作对这些老循环。 这意味着,没有必要为一个标志,告诉编译器自动向量化的范围内,基于for在任何情况下循环。


由于GCC的实施情况,问,这里是在源代码中描述什么是真正的做了相关的注释范围为基础for循环(您可以检查实现文件parser.c如果你想看看代码):

/* Converts a range-based for-statement into a normal
   for-statement, as per the definition.

      for (RANGE_DECL : RANGE_EXPR)
    BLOCK

   should be equivalent to:

      {
    auto &&__range = RANGE_EXPR;
    for (auto __begin = BEGIN_EXPR, end = END_EXPR;
          __begin != __end;
          ++__begin)
      {
          RANGE_DECL = *__begin;
          BLOCK
      }
      }

   If RANGE_EXPR is an array:
    BEGIN_EXPR = __range
    END_EXPR = __range + ARRAY_SIZE(__range)
   Else if RANGE_EXPR has a member 'begin' or 'end':
    BEGIN_EXPR = __range.begin()
    END_EXPR = __range.end()
   Else:
    BEGIN_EXPR = begin(__range)
    END_EXPR = end(__range);

   If __range has a member 'begin' but not 'end', or vice versa, we must
   still use the second alternative (it will surely fail, however).
   When calling begin()/end() in the third alternative we must use
   argument dependent lookup, but always considering 'std' as an associated
   namespace.  */

正如你所看到的,他们这样做无非是什么标准实际上是描述多。



文章来源: g++ , range based for and vectorization