如何告诉编译器展开这个循环[重复]
Posted
技术标签:
【中文标题】如何告诉编译器展开这个循环[重复]【英文标题】:How to tell the compiler to unroll this loop [duplicate] 【发布时间】:2013-04-07 23:47:34 【问题描述】:我在 ARM 处理器上运行以下循环。
// pin here is pointer to some part of an array
for (i = 0; i < v->numelements; i++)
pe = pptr[i];
peParent = pe->parent;
SPHERE *ps = (SPHERE *)(pe->data);
pin[0] = FLOAT2FIX(ps->rad2);
pin[1] = *peParent->procs->pe_intersect == &SphpeIntersect;
fixifyVector( &pin[2], ps->center ); // Is an inline function
pin = pin + 5;
通过循环的缓慢性能,我可以判断编译器无法展开这个循环,因为当我手动展开时,它变得非常快。我认为编译器被pin
指针弄糊涂了。我们可以在这里使用restrict
关键字来帮助编译器,还是restrict
只保留给函数参数?一般来说,我们如何告诉编译器展开它而不用担心pin
指针。
【问题讨论】:
您是否测量了调试或发布版本的执行时间? 使用 -O3 优化发布构建。 您是否尝试将v->numelements
分配给本地并在 for 循环中使用它?可能是编译器无法展开循环,因为它必须假设 v->numelements
的值将在 fixifyVector
中更改。
gcc 还有 -funroll-loops 优化标志,查看 docs 它必须与 -O3 分开启用
我在该代码中看不到任何可以通过展开循环得到显着帮助的内容。您将不得不查看为这两种情况生成的目标代码,以了解发生了什么。
【参考方案1】:
要告诉 gcc 展开所有循环,您可以使用优化标志 -funroll-loops
。
仅展开您可以使用的特定循环:
__attribute__((optimize("unroll-loops")))
查看answer了解更多详情。
编辑
如果编译器在进入时无法确定循环的迭代次数,则需要使用-funroll-all-loops
。注意从documentation:"Unroll all loops, even if their number of iterations is uncertain when the loop is entered. This usually makes programs run more slowly."
【讨论】:
【参考方案2】:如果将pptr
的大小扩大一倍,则可以使用pld
指令。
__asm__ __volatile__("pld\t[%0]" :: "r" (pptr[i+1]));
或者,您可能需要预加载 next peParent
和 SPHERE *ps
。 ARM 上的循环开销非常小。展开循环不太可能带来显着的好处。没有循环变量常量。当您展开循环时,编译器的调度程序更有可能在使用高级数据之前获取这些数据。
您还没有展示所有代码来查看数据依赖关系。 预加载可能还有其他变量会受益。给出一个完整的例子可能会帮助每个人回答你的问题。
【讨论】:
这个答案更可能出现在流水线较大的 Cortex 类型 CPU 上。没有提到具体的 ARM CPU。以上是关于如何告诉编译器展开这个循环[重复]的主要内容,如果未能解决你的问题,请参考以下文章