关于 GCC 单向旋转算法的一项发现
A discovery about GCC's unidirectional rotation algorithm

原始链接: https://devblogs.microsoft.com/oldnewthing/20260603-00/?p=112378

本摘要旨在探讨 `gcc libstdc++` 中针对随机访问迭代器(random-access iterators)与前向迭代器(forward iterators)所采用的旋转算法。虽然最初预期两者会有所不同,但分析显示,尽管呈现视角不同,这两种算法在功能上是完全一致的。 通过对这两种方法进行旋转采样追踪可以发现,它们执行了相同的交换操作并最终达到相同的状态,只是内部逻辑有所区别。主要差异在于 `libstdc++` 版本具有对称性,如果右侧区块较大,它允许从右向左处理交换;而前向迭代器算法则始终从左向右操作。归根结底,这再次证明了看似不同的技术方案往往共享相同的底层机制。本系列后续将继续分析 `clang` 所使用的循环分解法。

这篇 Hacker News 讨论聚焦于微软《旧事新说》(The Old New Thing)博客中关于 GCC 单向旋转算法的文章。 技术探讨部分强调了“三次反转”法(先反转两个子块,再反转整个向量),这被认为是优于循环分解的经典且对缓存友好的替代方案,在乔恩·本特利的《编程珠玑》中已有著名记载。 讨论帖中很大一部分内容围绕用户对作者语气的反应展开;几位评论者起初批评文章使用了夸张的语言,后来才意识到作者是有意采用枯燥的反讽和自我修正手法。讨论还扩展到了关于 GCC 等现代编译器复杂性与简单轻量级工具链吸引力之间的更广泛辩论,一些参与者表达了对摆脱历史“糟粕”的 C 语言风格编程语言的渴望。
相关文章

原文

Last time, we looked at the rotation algorithm used by gcc libstdc++ for random-access iterators, and I concluded by noting that we’re going to make a shocking discovery.

As with all shocking discoveries, this one will shock disappoint you.

The discovery is that the gcc libstdc++ algorithm is the same as the forward-iterator algorithm!

Let’s run both algorithms on a problem where the two blocks are A1, A2, A3, B1, B2, B3, B4, B5. I’ll put the old forward iterator algorithm on top and the new gcc libstdc++ algorithm below.

first   mid       last
           
A1 A2 A3 B1 B2 B3 B4 B5
           
first   mid       last

We swap at first and mid, then advance both pointers. The two algorithms agree until first reaches the end of the original A block.

      first   mid   last
           
B1 B2 B3 A1 A2 A3 B4 B5
           
      first   mid   last

The old algorithm recurses in order to exchange A1, A2, A3 with B4, B4. This happens by exchanging A1 with B4 and A2 with B5.

The new algorithm just keeps swapping first with mid, which also exchanges A1 with B4 and A2 with B5.

          first   mid
last
             
B1 B2 B3 B4 B5 A3 A1 A2
             
          first   last
mid

The old algorithm now recurses to swap the A3 block with the A1+A2 block. And that’s what the new algorithm does, too.

So it’s the same algorithm, just with a different point of view. It’s another case of the geeky thrill of discovering that two things are really the same thing, just with different labels.

Now, the two algorithms are not identical. The new algorithm is symmetric and performs its swaps from right to left if the larger block is on the right. The old algorithm always operates from left to right.

But the similarity is striking.

Next time, we’ll look at how clang performs rotation by decomposing into cycles.

联系我们 contact @ memedata.com