在繁重的模拟代码中,c++ 类/结构会明显慢于 c-array [关闭]

Posted

技术标签:

【中文标题】在繁重的模拟代码中,c++ 类/结构会明显慢于 c-array [关闭]【英文标题】:Would a c++ class/struct be noticeably slower than a c-array in heavy simulation codes [closed] 【发布时间】:2013-11-15 18:44:09 【问题描述】:

由于添加了“不同级别的间接”,据说创建数据类/结构比 c 数组慢,并且显然是“错误”,如发现 here。我一直在研究模拟代码一段时间,虽然我知道人们总是说不要进行预优化,但在深入了解之前了解要使用的数据结构是必不可少的。

如果我要运行 >10,000 个主循环,其中包含 1->50 个“迷你循环”,甚至可能是 1->10 个“迷你迷你循环”(即,最多可以说大约 10,000,000 个循环)总计),将我的所有数据保存在 c 代码中是否有益?还是速度上的差异微不足道,以至于我可以利用类而不是编写一个大的 c 文件?

【问题讨论】:

你能举一个你感兴趣的两个sn-ps的例子吗? 很遗憾我不能。这是我独立学习的机密工作(我是本科生)。但我可以说原始代码可以运行 10,000 个主循环,初始“能量”为 100 或 100,000,分别需要 5 分钟和 24 小时,所以我一直在尽我所能优化它。编辑 - 原始代码也是 > 10 年前编写的 据说比较慢请为这个说法提供证据。谁说的?有数据支持吗? > 10 年前,大多数编译器很难达到相同的优化水平,但今天在性能上绝对没有差异,AFAIK。 您不必输入实际代码(很少有人这样做;我们都有隐私/合同问题)。但是您始终可以发布具有代表性的 sn-ps 代码,以便我们更好地帮助您。否则我们都在猜测。 当然,根据你在这些周期中所做的事情,任何事情都可能发生,但它们对我来说听起来有点太慢了......你是否启用了编译器的优化?你用的是什么编译器? 【参考方案1】:

除非您使用虚函数或虚基类,否则生成的代码应该绝对没有区别。在 C++ 中,类和结构之间没有任何运行时差异。唯一的区别与成员可见性有关,这纯粹是编译时。

从问题中不清楚您如何将 C++ 类与 C 数组进行比较。 C 有 struct 而 C++ 有数组,一般来说,在 C 中使用数组和在 C++ 中使用数组将产生相同的结果,并且与“POD”(普通旧数据)类类似(除了上面提到的仅限 C++ 的特性。 )

您可能正在考虑 C++ std::vector 与 C 数组之间的区别。 std::vector 确实涉及间接,尽管在许多情况下优化器将能够避免它。但是,除非您在编译时知道数组的大小,否则很难使用 C 数组而不产生完全相同的间接寻址。如果您在编译时确实知道数组的大小,则可以使用 C++11 std::array,它将生成与 C 数组相同的代码。

【讨论】:

【参考方案2】:

我认为,出于许多实际目的,区分 C 和 C++ 是没有意义的。当我的同事们提出“我坚持使用 C,因为我需要更接近金属”的经典言论时,我听到的是“我将把抽象保持在最低限度”,或者在某些不幸的情况下“我知道我”我应该这么说,但我真的不知道”。

精心设计的抽象不会对性能造成任何影响。它甚至可以使您的代码更快(参见使用 C API 与算法 API 进行排序的典型示例)。 C++ 模板也意味着显着的速度提升。

话虽如此,唯一的答案是“我们不知道”,或者更好的是:“视情况而定”。之所以如此,是因为每个 sn-p 的代码都是不同的。

正如已经提到的:调用之间的间接性越多,数据局部性越少,意味着代码越慢。在 C 和 C++ 中都是如此。我再说一遍:不要将“我将抽象保持在最低限度”与“我正在用 C 编程”混淆。

【讨论】:

我不确定这如何回答数组与数据成员的问题主要区别是你不能在 C 中使用 C++ 功能,所以如果你开始用 C 编码,你就不会C 的优势,如果您从 C++ 开始,则很难移植到 C(假设使用得当) 一个数组可以是一个数据成员(我不确定你的意思)。我不明白“移植”你的程序有多“困难”。如果您的意思是“我不能在 C 中使用类”,那么您将 C++ 与面向对象编程混淆了。请记住:C++ 不是面向对象的语言,而是一种多范式 语言(其中一种范式是 OO)。您可以编写大量代码,无需任何修改即可在 C 和 C++ 中编译。【参考方案3】:

过早的优化。 :) 您需要设置性能要求、实施,然后如果不满足要求,则分析和优化瓶颈。

你所说的数据结构只是部分正确。知道要使用什么数据结构只是有点必要的,主要有两个原因(除其他外):

    一个设计良好的程序,其结构被划分为不同的、健全的、模块化的组件和清晰的契约,这意味着如果您稍后在优化期间更改了实现,那么您更改的代码将被限制在尽可能小的范围内。例如,如果您正在存储需要由某种键引用的值的集合,请不要认为“我使用哈希映射或二叉树或某种列表或......”,想想“我需要对这个集合做什么?”将其隐藏在一个 API 后面,该 API 可以保证功能,并在以后提高性能。也许您的初始实现是一个值数组,您每次都会强制执行,然后您将其更改为哈希表,但没关系,甚至提前,因为从从外部的角度来看,它只是一个按你说的做的集合,它对你在其他地方的初始设计决策没有影响。

    与上述类似,知道要使用的什么数据结构与知道要使用的实现是不同的。你犯了一个错误地思考太多细节。例如,不要认为“hash map”与“tree”,而是认为“map”。不要认为“数组”vs.“链表”vs.“双向链表”,想想“列表”。

专注于您的高级“OOP”设计。然后,当您准备好进行优化时,该过程将相对轻松。如果您的 API 合理、实用且定义明确,则您不需要需要了解实现细节。

【讨论】:

基于性能问题决定语言通常不被视为过早优化。在进行概要分析之前决定优化实施细节。 当然是过早的优化。应该编写易于理解的算法,这些算法通常使用高级语言进行充实以进行快速开发(例如 Python)。糟糕的算法在任何语言中都是糟糕的。 @GlennTeitelbaum 我没有阅读 OP 试图在两种语言之间做出决定。在大多数情况下,C++ 是完整的 C 超级集。GCC 和 G++(例如)使用相同的基本后端来生成二进制文件,无论您是在 C++ 模式还是 C 模式下运行它都没有显着 代码是 C 的区别。我将 OP 解读为在 C 风格的方法与使用 C++ 的语言特性之间做出决定,在任何一种情况下,高级设计都是相同的,只是语法表达不同(例如,C++ 使表示类更加方便)。 @JasonC 我是根据标签(C 已列出)和这个“将我的所有数据保存在 c 代码中”——代码而不是结构。但这可能只是一个错字【参考方案4】:

C++ 中有一些特性可以使开发速度更快,让您可以花更多时间进行优化 然而,C++ 确实为您提供了更多编写无用代码的机会,因此请保持简单并用 C++ 编写它

关于类与数组:

获取第 4 个 int 数据成员是

this+4*sizeof(int)

完全一样:

array+4*sizeof(int)

一旦达到机器级别 - 它们都只是偏移量的数据加载

【讨论】:

主要区别可能在于数据局部性;如果你使用 parallel 数组,如果你一起检查每个元素的属性,你的数据局部性比使用 structs 的数组更差。

以上是关于在繁重的模拟代码中,c++ 类/结构会明显慢于 c-array [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

犰狳 inplace_plus 明显慢于“正常”加操作

为什么在Hive中计数(明显)慢于group by?

使用JNDI明显慢于persistence.xml中的显式连接(Jetty 9 / Hibernate)

如何在 C++ 代码中的一些“繁重”操作之前使 QML 对象可见

gtk为何要用C语言

用于类和结构之间交互的 C++ 语法