此外,假设循环中的所有操作完全独立于其他迭代,编译器如何确定展开循环的程度。
2 回答
对于 MSVC,只有一个向量独立提示:http: //msdn.microsoft.com/en-us/library/hh923901.aspx
#pragma loop( ivdep )
对于许多其他编译器,例如Intel / ibm,有一些用于优化循环的 pragma 提示:
#pragma unroll
#pragma loop count N
#pragma ivdep
MSVC++ 人员有一个关于展开启发式的线程:http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/d0b225c2-f5b0-4bb9-ac6a-4d4f61f7cb17/
VC 试图平衡执行速度和代码大小。您可以通过使用标志 /O1 或 /O2 来更改平衡,但即使优化速度 VC 也会尝试节省代码大小。
基本上,展开会增加代码大小,因此可能会在 Os 和 O1 模式下受到限制(模式表)
PS: Pragma 看起来像预处理器指令,但它不是。它是编译器的指令,它被预处理器忽略(保留)。
对于英特尔编译器:
#pragma loop count N帮助编译器使用最佳策略来向量化循环。它节省了时间所以,我们可以说它有助于推动循环展开。例子:
#pragma loop_count min(n),max(n),avg(n)
#pragma unroll (n)仅在与 -O3 标志一起使用时有效,您可以使用以下策略根据目标处理器展开循环。
除了循环展开生成的代码增加之外,它可能值得,因为编译器将为标量操作和向量操作生成循环版本。
在展开影响性能的情况下,例如:循环 20 次迭代,向量长度为 16,导致 1 个循环一次执行 16 个操作,而余数循环依次执行 4 个操作。为了避免编译器生成的剩余循环,我们可以在循环之前使用:
#pragma vector novecremainder //or -mP2OPT_hpo_vec_peel = F to disable peel and remainder loops (compiler internal option)
或者
#pragma nounroll //where unrolling is not worth at all
只是为了澄清#pragma ivdep:
- 它提供了修改编译器启发式有关依赖项的具体提示,并且只有在我们知道假定的依赖项可以安全忽略时才必须使用。
- 最重要的是,它会覆盖潜在的依赖关系,但编译器仍会执行依赖关系分析,尝试 #pragma simd 进行矢量化,而不考虑任何分析。
希望这可以帮助。