我有一个嵌套的循环,如下所示-
for(int i=0; i<limit1; i++)
{
for(int j=0; j<limit2; j++){
/*
Code with Custom function calls, branching etc etc.
*/
}
}内循环迭代和外循环迭代是相互独立的。由于这个循环不能简单地向量化,所以我想将它折叠到一个巨大的迭代空间中,这样它就可以更有效地展开,在这个意义上,不是只展开内部循环,而是可以展开组合的迭代空间。
我不想将其并行化。据我所知,我不认为openmp提供了像- #pragma omp collapse(2)这样的独立折叠编译指示,而是将折叠子句与simd或for等其他编译指示结合使用。
可以通过OpenMP,也可以通过其他方法来实现。
PS -我不确定这种方法的优缺点,是否会获得显着的性能提升等。如果有人解释如何从理论上(即在基准测试之前)确定这一点,那就太好了。
提亚
发布于 2021-11-06 17:30:56
首先,OpenMP是“一种可以跨不同供应商的架构移植的并行编程模型”(来源:OpenMP 5.1 specification)。因此,如果您不想并行化循环,那么它可能不是正确的工具。
但是,请注意,OpenMP提供了指令unroll来完全或部分展开循环嵌套的最外层循环。完全展开循环的full子句要求迭代计数(例如limit1)是编译时常量(否则在理论上是不可能的)。partial子句可以由整数参数化,以控制展开多少次迭代。到目前为止,无论是GCC,国际商会还是Clang都不支持这两个条款。
还有tile指令,它可以对两个嵌套循环的迭代进行重新排序,从而获得2D固定大小的块。它没有指定编译器应该展开循环。然而,积极优化的编译器很可能会展开固定大小的块循环嵌套,如果它不包含许多分支或函数调用(因为这通常对性能不利)。此指令不能与unroll一起使用(因为平铺循环没有规范的循环嵌套形式)。
请注意,如果迭代计数不是编译时常量,则折叠(使用工具手动或自动)两个嵌套循环肯定不会对编译器有所帮助,如果limit2不是2的幂,则通常也不会。事实上,在这种情况下,通过变量使用慢模数或相当慢的分支较少的条件移动肯定是必需的。对于编译器来说,展开这样的循环是非常困难的(如果可能的话)。
https://stackoverflow.com/questions/69865466
复制相似问题