Nir*_*Nir 15 c compiler-construction optimization
我的代码中的瓶颈部分存在性能问题.基本上它是一个简单的嵌套循环.
对问题进行概要分析表明,该程序花费了大量时间来增加循环计数器(++)和终止测试(i/j <8).
观察汇编输出我发现两个计数器都没有得到寄存器,访问它们需要花费很多周期.使用"register"关键字并不能说服编译器将它们实际放入寄存器中.是否可以采取一些措施来优化计数器的访问时间?
这是装配输出.C源只是一个带有i/j计数器的简单嵌套循环.
2738 0.2479 2459 0.1707 : 1e6c: jne 1dd1 <process_hooks+0x121>
1041 0.0942 1120 0.0778 : 1e72: addl $0x1,0xffffffd4(%ebp)
2130 0.1928 2102 0.1459 : 1e76: cmpl $0x8,0xffffffd4(%ebp)
2654 0.2403 2337 0.1622 : 1e7a: jne 1da0 <process_hooks+0xf0>
809 0.0732 814 0.0565 : 1e80: jmp 1ce2 <process_hooks+0x32>
Run Code Online (Sandbox Code Playgroud)
根据要求,这里也是C代码.编译器是gcc btw:
for (byte_index=0; byte_index < MASK_SIZE / NBBY; byte_index++)
{
if (check_byte(mask,byte_index))
{
for (bit_index=0; bit_index < NBBY; bit_index++)
{
condition_index = byte_index*NBBY + bit_index;
if (check_bit(condition_mask,condition_index))
{
.
.
.
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
谢谢
Pau*_*gar 13
有两个可能的原因它没有放入寄存器:
如果您正在获取变量的地址或声明它变化,则不会将其保存在寄存器中.它看起来不像你那样做,但它可能会发生在该...部分.
这很有可能.gcc似乎有一个糟糕的分配器(基于其开发人员的评论).此外,注册分配是变化无常且难以推理的.您可能可以使用寄存器分配器优化来调整它以获得一些好处.如果您愿意,可以仅为该功能设置它们.
gcc 4.4有一个新的寄存器分配器,应该更好,但也允许你选择分配算法.这将提供额外的调整内容.
您也可以尝试使用hot属性告诉gcc更加努力.
最后,您还可以使用gcc的--param标志来调整内容.它们暴露了内部编译器设置,所以这可能不应该轻易开始.
使用intel编译器时得到的最佳结果(速度方面).
你是对的,'register'关键字只是作为编译器的提示(就像内联一样).
如果你真的认为这个循环是一个主要的瓶颈,那就输入原始组件.我知道它几乎不便携,但是再次,通常这并不重要,如果它应该是便携的......它只在一个特定的地方.
您甚至可以使用原始C代码#ifdef整个位以保持可移植性
for (bit_index=0; bit_index < NBBY; bit_index++)
{
condition_index = byte_index*NBBY + bit_index;
if (check_bit(condition_mask,condition_index))
{
.
.
.
}
}
Run Code Online (Sandbox Code Playgroud)
可能很容易;
condition_index = byte_index * NBBY;
for (bit_index=0; bit_index < NBBY; bit_index++, condition_index++)
{
if (check_bit(condition_mask,condition_index))
{
.
.
.
}
}
Run Code Online (Sandbox Code Playgroud)
我喜欢将计算保持在正确的范围内.你在外部循环中拥有了这个的所有信息,但是选择在内部循环中进行.新循环稍微有点乱,但这可以避免,现在你的编译器更有可能正确地做事.(它可能以前做过,但是如果不检查组件就不能确定.)
说到正确的范围,没有理由在循环之外声明循环计数器.这种C风格已经过时多年了,虽然它可能不是特别的性能劣势,但是将事物限制在最小的逻辑范围内会导致更清晰,更易于维护的代码.
对于8位,您可能会展开,但根据您的硬件,它可能无法正常工作.还有很多其他方法可以做到这一点,我可能错过了一些看着它.在硬件中,我在循环中使用条件通常对性能有害,但我没有看到任何明显的方法来避免它.我当然会考虑在外部循环中迭代位而不是字节,以避免在常见情况下的乘法.只是建议这个...我想在这种情况下不会有明显的优势.