C++语言的未来

null

你好,世界!  今天,我(斯蒂芬T。Lavavej,library dev)想提出一个问题和一个Orcas错误修复。

首先,问题是:C++的未来是什么?  或者,粗略地说,C++有未来吗?  随着程序员在新的应用领域中使用它,并找到更有效地使用它的方法,它会增长和发展吗?  或者它会停滞不前,程序员在越来越少的应用领域中使用它,直到没有新的东西被发明出来,它永远进入“维护模式”?  在过去三年里,C++的爆炸式增长之后,接下来会发生什么?

这个问题的范围是有限的。  语言不可能是永恒的,对吧?  (尽管C确实很成功。)  我不希望C++在2107,甚至2057的时候充满活力。  在计算机行业,50年是一个几乎无法理解的时间跨度;晶体管本身今年就要60岁了。  所以当我问“C++的未来是什么”时,我真的在问下10, 20年和30年。

我是这么看的。  首先,考虑C++的过去。  碰巧,Bjarne Stroustrup最近发布了一篇优秀论文,内容涵盖了C++的近期历史,“在现实世界中为真实世界和进化语言提供了一个C++: http://research.att.com/~bs/hopl-almost-final.pdf .  还有一个精彩的1995年采访亚历山大斯特帕诺夫在 http://stepanovpapers.com/drdobbs-interview.html 这说明了C++的机器模型。

由于几个原因,C++的机器模型对性能的关注是不停的。  源自C,它是“无脂肪”的,是一个原因——在性能领域,C++从来没有减肥过。 只是为了避免体重增加。  C++的添加总是以最大有效的方式实现,并且避免对不要求它们的程序员施加成本。  (作为C++性能的技术报告,现在公开 http://standards.iso.org/ittf/PubliclyAvailableStandards/c043351_ISO_IEC_TR_18015_2006(E) .zip文件 ,解释说,异常处理可以用“表”方法实现,这种方法对实际上不抛出的代码施加最小的运行时开销。  由于历史原因,VC在x86上使用“代码”方法,但在x64和IA-64上使用“表”方法。)  历史上,C++运行在非常小的和慢的机器上,无法承受任何不必要的成本。  现在,C++被用来解决性能非常关键的巨大问题,所以不必要的成本仍然是不可想象的!

除了电梯控制器和超级计算机之外,性能对普通的台式机和服务器还有影响吗?  哦,是的。  处理器终于碰壁了,正如我们的Herb Sutter在2005年的 http://gotw.ca/publications/concurrency-ddj.htm .  那些用硅做神奇事情的硬件人,遇到了工程上的限制,这些限制阻碍了消费类处理器的频率稳步上升,因为它们从一开始就一直如此。  尽管我们的处理器没有变慢,但它们也没有变得更快(至少,除非有一些令人难以置信的突破)。  不管怎样,底部已经没有足够的空间了。  我们的电路非常接近原子水平,原子并没有变小。  频率的工程极限比电路的物理极限来得早。  在可预见的未来,缓存将继续变得更大,这很好,但是拥有一个两倍大的缓存并不如以两倍的频率运行所有东西那么好。

作为程序员,我们面临着一个与我们所习惯的截然不同的未来:我们今天拥有的处理器的速度和我们将拥有的速度一样快。  当然,计算机行业经历着不断的变化,但我们更喜欢这种变化,这种变化使我们的程序每两年运行两倍于以前的速度,而我们没有额外的工作。

不屈不挠的是,硬件工程师已经开始在每个处理器中放置多个内核,这实际上很好地提高了整体性能。  (我当然希望有一台四核机器在工作!)  但并不是所有的东西都像编译那样令人尴尬地平行。  单核性能仍然很重要。  作为程序员,我们被要求解决的问题每年都在变得越来越大,就像他们一直做的那样。

因此,我认为C++是唯一的位置来应对这种性能风暴。 其他语言将继续在性能不重要或令人尴尬的并行应用程序域中找到用途。  但无论何时单个核心收缩的速度都很重要,C++将存在。  (例如,3D游戏。  当Halo无穷大在2027被释放时,是的,我完全是这样做的——我完全希望它是用C++编写的。

在C++ 0x中,最大的核心语言变化将是可变模板、概念和rValk引用。  前两个将使编写模板更加有趣。  这很好,因为模板是生成高效代码的一种强大方法。  第三个将解决C++ 03中最薄弱的区域之一——它倾向于复制值。  (有价值语义的东西是很好的——不必要的拷贝不是。)  通过“move semantics”消除不必要的拷贝,rvalue引用将使重值代码(与任何使用STL的代码一样)的速度大大加快。  未来是光明的!

我为什么要考虑绩效?  因为我的一个修正降低了标准库的性能。  在你痛苦地尖叫之前,让我解释一下…

在我的第一篇VCBlog文章中,我提到了我正在研究的东西,后来被签入了Orcas(VC9)。  我称之为交换修复。  综上所述,VisualStudio2005(VC8)引入了新的迭代器调试和迭代器检查功能。  迭代器调试,由u启用有u迭代器u调试,执行强大的正确性验证。  迭代器检查由u SECURE u SCL启用,执行最小的检查,作为最后一道安全防线。  例如,u SECUREu SCL将终止一个程序,该程序使用向量迭代器触发堆溢出。

所有这些都由MSDN文档解释。  这背后的故事很有趣。  Dinkumware提供了_HAS _ITERATOR _调试功能,这是一家允许标准库的最成功实现包含在visualstudio中的公司。  Microsoft添加了u SECURE u SCL功能,以提高在Windows上运行的程序的安全性。  为了执行它们的检查,两个都有迭代器调试和安全的SCL使迭代器包含额外的数据成员,例如指向其父容器的指针。  _有_ITERATOR_DEBUGGING,因为它在默认情况下在调试模式下启用(在发布模式下不可获得),它还构建单链接列表,允许容器引用其所有迭代器。  这在性能方面是昂贵的,但在调试模式下性能并不重要,这可以实现出色的检查。

_SECUREu SCL,因为它在默认情况下是在释放模式下启用的,所以它努力施加最小的性能损失。  因此,当它被启用时,尽管迭代器有指向其容器的指针,但容器没有指向其迭代器的指针。  (更新“迭代器列表”对于发布模式来说太耗时了。)

现在,VC8RTM/SP1在禁用迭代器调试和启用安全SCL(例如,默认的发布模式)时出现了一个错误。  当您将持久迭代器放入两个容器中,然后交换容器时,标准要求迭代器保持有效(23.1/10)。  不幸的是,u SECUREu SCL添加到迭代器的父指针被这样的交换破坏了。  (正在交换的容器无法找到指向它们的迭代器。)  Dinkumware的HAS ITERATOR调试不受此问题的影响,因为它可以遍历ITERATOR列表并更新所有父指针。  此选项对u SECUREu SCL不可用。

为了修复这个一致性错误,Orcas中的Swap fix使每个标准容器都拥有一个额外的动态分配对象,想象地称为“aux对象”。  每个容器都有一个指向其aux对象的指针,而aux对象又有一个指向容器的指针。  每个迭代器不再直接持有指向其父容器的指针,而是持有指向其父容器的辅助对象的指针。  这是真的:任何事情都可以通过一个额外的间接层次来解决。  交换容器时,它们也交换其辅助对象。  这允许容器“告诉”迭代器它们的当前位置,而不必知道它们都在哪里。  结果表明,即使在安全的SCL下,VC9也是一致的。

性能问题是,aux对象虽然不可避免(没有“pimpling”容器,这对于性能来说可能更昂贵),但它不是免费的。  每个标准容器现在都变大了,因为它必须持有指向其辅助对象的指针。  aux对象必须动态分配,占用更多的空间和时间。  当从迭代器到其父容器时, u SECURE u SCL必须执行双重间接寻址。  我已经衡量了双间接寻址的成本,这是不寻常的:在深度嵌套循环中使用迭代器的程序可能会以以前的一半速度运行。  (一般来说,只有手写循环会受到显著影响。  标准算法执行一次检查,然后“取消检查”它们的参数以提高速度。  这是避免手写循环的另一个原因!)  大多数程序不应该因为这个修正而经历明显的性能变化,一些程序员的生活将因为一致性的提高而变得更容易,但是其他程序员将不得不处理交换修正的影响。  所以我用大写字母写。

这是需要记住的:尽管性能很重要,但它并不是全部。  正确性和安全性胜过性能。  _SECUREu SCL提高了安全性,此修复对于恢复正确性是必需的。  VC8中的性能是一种错觉,因为它是以正确性为代价获得的。  Orcas的性能将反映安全SCL的真实成本。  和以前一样,程序将能够关闭u SECUREu SCL以获得最大性能。  如何正确地禁用u SECUREu SCL(并且u有u ITERATORu调试)可能是未来博客文章的一个主题–这很容易出错,我们正在考虑如何使这个过程在Orcas+1中更加健壮。

STL公司

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享