6

我即将编写一个非晶格扩散受限聚合 (DLA) 模拟,我想知道是使用 C 还是 C++。

出于设计原因,C++ 会很好,但我想知道 C 是否会表现得更好。当然,我了解算法性能并选择了最好的算法。所以我不是在谈论将 O(n^2) 改进为 O(log n) 或类似的东西。可以这么说,我正试图减少我的常数。

如果你不知道 DLA,它基本上归结为有一个双精度数组(大小在 10^3 和 10^6 之间),并在循环中选择随机双精度数来比较(大于/小于)数组的大部分。

因此,对此很重要的性能差异是数据访问和调用函数:

  • 数据访问:C 结构与具有公共数据成员的 C++ 类与具有私有数据成员和访问器的 C++ 类。
  • 调用函数:C 函数与 C++ 成员函数。

我是否可以得出结论,判断这一点的最终方法是查看汇编代码(例如比较移动/加载、跳转和调用的数量)?这当然取决于编译器(例如,您可以将糟糕的 C 编译器与好的 C++ 编译器进行比较)。我正在使用 Gnu 编译器(gcc 和 g++)。

我发现 gcc 和 g++ 生成的程序集在跳转次数(无)、移动/加载和调用以下两个程序方面几乎相同:

C程序

#include <stdlib.h>

typedef struct 
{
    double x;
} particle;

double square(double a)
{
    return a*a;
}

int main()
{

    particle* particles = malloc(10*sizeof(particle));
    double res;

    particles[0].x = 60.42;

    res = square(particles[0].x);

    return 0;
}

C++程序

class particle
{
    public:
        double x;

    public:
        double square()
        {
            return x*x;
        }

};

int main()
{

    particle* particles = new particle[10];
    double res;

    particles[0].x = 60.42;

    res = particles[0].square();

    return 0;
}

如果我在 C++ 程序中使用私有成员数据,当我调用particles[0].setx(60.42) 时,我当然会在程序集中得到另一个调用。

这是否意味着我可以选择 C++ 作为 C,因为它们产生几乎相同的汇编代码?我应该避免私有成员数据,因为它增加了额外的函数调用(例如,在程序集中调用很昂贵)?

4

2 回答 2

11

鉴于您概述的事物的类型,我会惊讶地看到 C 在其中任何一个方面都有显着优势。根据您所说的,我还猜想您所做的比较是基于在很少或没有启用优化的情况下进行的编译。启用完全优化后,我希望那些甚至会消失。

从长远来看,C++ 提供了更多的优化机会。一个在矩阵算术中相当常见的(尽管我不确定它是否适用于您的 DLA 模拟)是表达式模板,您可以使用它来“扁平化”计算以避免复制原本需要的数据。

底线:在更糟糕的情况下,C++ 最终将完全等同于 C(即,在最糟糕的情况下,您编写的 C++ 代码几乎与 C 代码相同,并且在性能上看不到任何差异)。充其量,C++ 的额外特性(尤其是模板)为您提供了以 C 语言不可能或完全不切实际的方式进行优化的机会。

于 2013-05-25T16:59:18.030 回答
1

malloc在您发布的情况下,您基本上是在询问和之间的性能差异new

在 C++ 中,new运算符执行附加功能,例如调用对象的构造函数或初始化变量。

对于 C 中的等效操作,您需要在调用malloc. 将您的 C 程序更改为更像 C++ 然后配置文件。

在大多数性能问题中,您需要将苹果与苹果进行比较。如果您在 C++ 中使用面向对象编程,则需要在进行比较之前在 C++ 中编写等效代码。鉴于此,在大多数情况下,两种语言之间的性能差异可以忽略不计。

还要考虑:开发时间、正确性、稳健性、安全性以及您对语言的信心或经验。与项目的这些其他属性相比,性能通常可以忽略不计。

许多性能问题不取决于语言,而是取决于设计和平台。缓存未命中、循环展开、许多比较都会影响性能,而与语言无关。

于 2013-05-25T17:17:00.347 回答