10

特定のループをアンロールするようにclangに指示する方法はありますか?


答えをグーグルで検索すると、単一のループではなく、コンパイル全体に影響するコマンドラインオプションが得られます。


GCC についても同様の質問があります --- gcc に具体的にループをアンロールするように指示します--- しかし、そこで提供された回答は clang では機能しません。

そこに提案されたオプション1:

#pragma GCC optimize ("unroll-loops")

黙って無視されているようです。実際には

#pragma GCC akjhdfkjahsdkjfhskdfhd

も黙って無視されます。

オプション 2:

__attribute__((optimize("unroll-loops")))

警告が表示されます:

warning: unknown attribute 'optimize' ignored [-Wattributes]

アップデート

joshuanapoli は、ループを作成せずにテンプレート メタプログラミングと C++11 を介して反復する方法を提供しています。コンストラクトはコンパイル時に解決され、繰り返しインライン化された本体になります。質問に対する正確な答えではありませんが、本質的に同じことを達成します。

それが私が答えを受け入れる理由です。forただし、標準の C ループ ( , )を使用して強制的に展開する方法を知っている場合はwhile、その知識を私たちと共有してください!

4

3 に答える 3

9

C++ プログラムの場合、言語内でループを展開できます。コンパイラ固有のオプションを理解する必要はありません。例えば、

#include <cstddef>
#include <iostream>

template<std::size_t N, typename FunctionType, std::size_t I>
class repeat_t
{
public:
  repeat_t(FunctionType function) : function_(function) {}
  FunctionType operator()()
  {
    function_(I);
    return repeat_t<N,FunctionType,I+1>(function_)();
  }
private:
  FunctionType function_;
};

template<std::size_t N, typename FunctionType>
class repeat_t<N,FunctionType,N>
{
public:
  repeat_t(FunctionType function) : function_(function) {}
  FunctionType operator()() { return function_; }
private:
  FunctionType function_;
};

template<std::size_t N, typename FunctionType>
repeat_t<N,FunctionType,0> repeat(FunctionType function)
{
  return repeat_t<N,FunctionType,0>(function);
}

void loop_function(std::size_t index)
{
  std::cout << index << std::endl;
}

int main(int argc, char** argv)
{
  repeat<10>(loop_function)();
  return 0;
}

ループ機能が複雑な例

template<typename T, T V1>
struct sum_t
{
  sum_t(T v2) : v2_(v2) {}
  void operator()(std::size_t) { v2_ += V1; }
  T result() const { return v2_; }
private:
  T v2_;
};

int main(int argc, char* argv[])
{
  typedef sum_t<int,2> add_two;
  std::cout << repeat<4>(add_two(3))().result() << std::endl;
  return 0;
}
// output is 11 (3+2+2+2+2)

明示的な関数オブジェクトの代わりにクロージャーを使用する

int main(int argc, char* argv[])
{
  int accumulator{3};
  repeat<4>( [&](std::size_t)
  {
    accumulator += 2;
  })();
  std::cout << accumulator << std::endl;
}
于 2013-03-07T15:54:28.087 に答える
2

ひどいかもしれませんが、上記のforループを独自のファイルに分離して、個別にコンパイルすることができます(独自のコマンドラインフラグを使用)。

関連するが、現在未回答の clang-developers の質問

于 2013-03-07T16:30:03.780 に答える