关于c ++:哪种算法带来最佳性能?

Which algorithm brings the best performance?

本问题已经有最佳答案,请猛点这里访问。

我有一段代码非常脏。

我想优化一下。当我采取以下结构中的一个,或者它们与C++中的性能相同时,这有什么区别吗?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
for(unsigned int i = 1; i < entity.size(); ++i) begin
if
 if ... else ...
for end

for(unsigned int i = 1; i < entity.size(); ++i) begin
if
 if ... else ...
for end

for(unsigned int i = 1; i < entity.size(); ++i) begin
if
 if ... else ...
for end
....

1
2
3
4
5
6
7
8
9
for(unsigned int i = 1; i < entity.size(); ++i) begin
if
 if ... else ...
if
 if ... else ...
if
 if ... else ...
....
for end

事先谢谢!


第一个循环可能花费较少的时间递增/测试i和条件分支(假设编译器的优化程序不会将其减少到第二个循环的等效值),但如果循环展开,则与循环内花费的时间相比,i循环所花费的时间可能无关紧要。

与此相反,选择单独的循环和组合的循环很容易影响缓存命中率,这可能会显著影响任何一个版本:它实际上取决于代码。例如,如果三条if/else语句中的每一条都在索引i处访问不同的数组,那么它们将竞争CPU缓存,并可能降低彼此的速度。另一方面,如果他们访问索引i上的同一个数组,在某些计算中执行不同的步骤,那么在这些内存页仍在缓存中的情况下,最好执行这三个步骤。

除了缓存之外,还存在其他潜在影响-从影响到寄存器分配、I/O设备的速度(例如,如果每个循环在不同物理驱动器上不同文件的行/记录上运行,则在循环中处理每个文件的某些部分可能会非常快,而不是按顺序处理每个文件)等。

如果您愿意,可以使用具有代表性的数据对实际应用程序进行基准测试。


两者都是O(n)。因为我们不知道各种for循环的本质,所以不可能说出来。

顺便说一下,马克是伪代码而不是C++


仅仅从循环的结构来看,不可能确定哪种方法更快。从算法上讲,两者具有相同的复杂性o(n)。但是,根据对元素执行的操作类型和容器的大小,这两者的性能数字可能不同。

容器的大小可能会影响位置,从而影响性能。因此,一般来说,一旦将数据放入缓存中,就希望尽可能多地咀嚼数据。所以我更喜欢第二种方法。为了得到一个清晰的画面,你应该实际测量你的方法的性能。


我希望第二种方法在大多数情况下至少更为优化,因为它可以利用参考区域访问entity集合/集合的元素。注意,在第一种方法中,每个for循环都需要从一开始就开始访问元素;根据缓存的大小、列表的大小以及编译器可以推断和优化的程度,当新的for循环尝试读取元素时,这可能会导致缓存未命中,即使该元素会已经被前面的循环读取。


第二个比第一个效率稍高。你保存:

  • 循环索引的初始化
  • 呼叫size()
  • 将循环索引与size()进行比较`
  • 增加循环索引
  • 这些是非常小的优化。如果它不影响可读性,那么就做它。