在 MSVC C++ 中强制展开循环
Forcing loop unrolling in MSVC C++
想象以下代码:
for (int i = 0; i < 8; ++i) {
// ... some code
}
我希望在 MSVC 中展开此循环。在 CLang 中,我可以在循环之前添加 #pragma unroll
。但是如何在 MSVC 中做同样的事情?
我知道编译器通常会为我展开这个循环,即使没有任何编译指示。但我真的想确定这一点,我想一直展开它。
当然,强制展开的一种方法是使用带有传入仿函数的模板化展开函数的递归调用,如以下代码所示:
template <int N, int I = 0, typename F>
inline void Unroll(F const & f) {
if constexpr(I < N) {
f.template operator() <I> ();
Unroll<N, I + 1>(f);
}
}
void f_maybe_not_unrolled() {
int volatile x = 0;
for (int i = 0; i < 8; ++i)
x = x + i;
}
void f_forced_unrolled() {
int volatile x = 0;
Unroll<8>([&]<int I>{ x = x + I; });
}
但是如果没有像上面这样更难的代码,是否可以在 MSVC 中强制展开?
另外CLang有没有可能真的强制展开,我想#pragma unroll
只是给CLang一个提示(或者我不对),也许有类似#pragma force_unroll
,有吗?
另外我只想展开这个循环,我不需要像传递命令行参数这样的解决方案来强制展开所有可能的循环。
注意: 对我来说,在所有 100% 的情况下真正强制展开代码并不重要。在大多数情况下,我只需要它发生。基本上,我只想找出与 CLang 的 #pragma unroll
一样的 MSVC,与不使用 pragma 相比,它平均使编译器更有可能展开循环。
你不能直接。最接近的 #pragma
是 #pragma loop(...)
,它没有展开选项。这里的大锤是 Profile Guided Optimization - 分析你的程序,MSVC 将知道这个循环运行的频率。
想象以下代码:
for (int i = 0; i < 8; ++i) {
// ... some code
}
我希望在 MSVC 中展开此循环。在 CLang 中,我可以在循环之前添加 #pragma unroll
。但是如何在 MSVC 中做同样的事情?
我知道编译器通常会为我展开这个循环,即使没有任何编译指示。但我真的想确定这一点,我想一直展开它。
当然,强制展开的一种方法是使用带有传入仿函数的模板化展开函数的递归调用,如以下代码所示:
template <int N, int I = 0, typename F>
inline void Unroll(F const & f) {
if constexpr(I < N) {
f.template operator() <I> ();
Unroll<N, I + 1>(f);
}
}
void f_maybe_not_unrolled() {
int volatile x = 0;
for (int i = 0; i < 8; ++i)
x = x + i;
}
void f_forced_unrolled() {
int volatile x = 0;
Unroll<8>([&]<int I>{ x = x + I; });
}
但是如果没有像上面这样更难的代码,是否可以在 MSVC 中强制展开?
另外CLang有没有可能真的强制展开,我想#pragma unroll
只是给CLang一个提示(或者我不对),也许有类似#pragma force_unroll
,有吗?
另外我只想展开这个循环,我不需要像传递命令行参数这样的解决方案来强制展开所有可能的循环。
注意: 对我来说,在所有 100% 的情况下真正强制展开代码并不重要。在大多数情况下,我只需要它发生。基本上,我只想找出与 CLang 的 #pragma unroll
一样的 MSVC,与不使用 pragma 相比,它平均使编译器更有可能展开循环。
你不能直接。最接近的 #pragma
是 #pragma loop(...)
,它没有展开选项。这里的大锤是 Profile Guided Optimization - 分析你的程序,MSVC 将知道这个循环运行的频率。