如果我有一个我知道需要执行的循环n次有没有办法在没有比较的情况下每次写一个while(或for)循环?如果没有,有办法进行宏观转变:
int i = 0;
for(i = 0; i < 5; i++) {
operation();
}
成:
operation();
operation();
operation();
operation();
operation();
P.S。这是迄今为止我提出的最快的循环。
int i = 5;
while(i-- >= 0) {
operation();
}
答案 0 :(得分:7)
一个足够聪明的编译器会为你做这件事。更具体地说,优化编译器可以理解循环展开。这是一个相当基本的优化,特别是在你的例子中,在编译时已知迭代次数。
简而言之:打开编译器优化并且不用担心它。
答案 1 :(得分:5)
您在源代码中编写的指令数量与编译器将生成的机器指令数量并不严格相关。
大多数编译器更智能,在第二个示例中可以生成如下代码:
operation();
operation();
operation();
operation();
operation();
自动,因为它们检测到循环将总是迭代5次。
此外,如果您进行面向性能分析的优化,并且编译器发现循环具有很小的主体和非常高的重复计数,它甚至可以使用以下代码进行通用迭代次数的展开:
while (count >= 5) {
operation();
operation();
operation();
operation();
operation();
count -= 5;
}
while (count > 0) {
operation();
count--;
}
与天真版本相比,这将使大count
大约五分之一的测试。
如果值得做或不做就是只能进行分析的东西。
如果您确定代码需要至少执行一次,那么您可以做的一件事就是写
do {
operation();
} while (--count);
而不是
while (count--) {
operation();
}
count==0
对于CPU有点烦人的可能性,因为大多数编译器生成的代码需要额外的JMP转发:
jmp test
loop:
...operation...
test:
...do the test...
jne loop
do { ... } while
版本的机器代码只是
loop:
... opertion ...
... do the test...
jne loop
答案 2 :(得分:0)
两个循环都会进行比较..
无论如何,编译器应该识别常量迭代并展开循环。
您可以使用gcc和优化标志(-O)检查它,然后查看生成的代码。
更重要的是: 除非有明显的理由,否则不要进行优化!
答案 3 :(得分:0)
编译C代码后,while和for循环将转换为机器语言的比较语句,因此无法避免与for / while循环进行某种类型的比较。您可以制作一系列避免使用比较的goto和算术语句,但结果可能效率较低。你应该看看如何使用radare2或gdb将这些循环编译成机器语言,看看它们如何在那里得到改进。
答案 4 :(得分:0)
使用模板,您可以使用以下内容展开循环(在计数中已知计数):
namespace detail
{
template <std::size_t ... Is>
void do_operation(std::index_sequence<Is...>)
{
std::initializer_list<std::size_t>{(static_cast<void>(operation()), Is)...};
}
}
template <std::size_t N>
void do_operation()
{
detail::do_operation(std::make_index_sequence<N>());
}
但是编译器可能已经对正常循环进行了那种优化。