【问题标题】:Why is my C++ app faster than my C app (using the same library) on a Core i7为什么我的 C++ 应用程序比 Core i7 上的 C 应用程序(使用相同的库)更快
【发布时间】:2011-01-04 11:57:21
【问题描述】:

我有一个用 C 编写的库,我有 2 个用 C++ 和 C 编写的应用程序。这个库是一个通信库,因此其中一个 API 调用如下所示:

int source_send( source_t* source, const char* data );

在 C 应用程序中,代码执行如下操作:

source_t* source = source_create();
for( int i = 0; i < count; ++i )
    source_send( source, "test" );

C++ 应用程序在哪里执行此操作:

struct Source
{
    Source()
    {
        _source = source_create();
    }

    bool send( const std::string& data )
    {
        source_send( _source, data.c_str() );
    }

    source_t* _source;
};

int main()
{
    Source* source = new Source();
    for( int i = 0; i < count; ++i )
        source->send( "test" );
}

在 Intel Core i7 上,C++ 代码每秒产生的消息几乎正好多出 50%。 而在 Intel Core 2 Duo 上,它每秒产生几乎完全相同数量的消息。 (核心 i7 有 4 个核心,每个核心有 2 个处理线程)

我很好奇硬件执行了什么样的魔法来实现这一目标。我有一些理论,但我想我会得到一个真正的答案:)

编辑:来自 cmets 的其他信息

编译器是visual C++,所以这是一个windows box(两者都是)

通信库的实现创建了一个新线程来发送消息。 source_create 是创建此线程的原因。

【问题讨论】:

  • 编译器?编译器设置?运行?比较发出的目标代码?
  • 你也在编译C库吗?或者它已经为你编译了? source_send() 是内联定义的吗?
  • 我很难把它放在编译器上。我正在使用 Visual Studio,因此它应该生成适用于所有 Windows 机器的代码,无论内核如何。现在,如果我使用 gcc -mtune=native 进行编译,我们可能会有一些东西,但事实并非如此
  • @Emile:函数不是内联的,我也编译库。

标签: c++ c hardware cpu cpu-architecture


【解决方案1】:

仅通过检查您的源代码,我看不出 C++ 代码应该更快的任何原因。

接下来我要做的是检查正在生成的汇编代码。如果您使用的是 GNU 工具链,则有几种方法可以做到这一点。

您可以通过-S 命令行参数让 gcc 和 g++ 输出汇编代码。确保除了添加该参数之外,您使用与常规编译完全相同的命令行参数。

第二种选择是使用 gdb 加载您的程序并使用 disas 命令。

祝你好运。

更新

您可以使用 Microsoft 工具链做同样的事情。

要让编译器输出程序集,您可以使用/FA or /FAs。第一个应该只输出程序集,而第二个将混合程序集和源代码(这应该更容易理解)。

至于使用调试器,在 Visual Studio 中启动调试器后,导航到“调试 | Windows | 反汇编”(在 Visual Studio 2005 上验证,其他版本可能会有所不同)。

【讨论】:

  • 很遗憾该项目还没有准备好在linux上编译,但是非常好的想法+1
  • /FA 有点整洁,我做个比较看看能不能发现什么
【解决方案2】:

没有看到完整的代码或程序集,我最好的猜测是 c++ 编译器正在为您内联。 c++ 编译器的优点之一是内联几乎任何东西以提高速度的能力,而众所周知,微软的编译器无偿内联几乎到了不合理地膨胀最终可执行文件的地步。

【讨论】:

    【解决方案3】:

    我建议做的第一件事是分析两个版本,看看是否有任何明显的差异。

    C 版本是否不必要地复制了某些内容(可能是微妙的优化,也可能不是那么微妙的优化,如返回值优化)。

    这应该会出现在一个好的分析器中,如果你有更高端的 VS SKU,那么基于采样的分析器就很好,如果你正在寻找一个好的免费分析器,Windows 性能分析器对于 Vista 及更高版本来说非常强大@ 987654321@

    我自己可能会做的第一件事是闯入调试器并检查每个的反汇编,看看它们是否有明显的不同。请注意,有一个编译器选项可以将 asm 吐出到文本文件中。

    如果没有明显的东西(比如额外的副本),我会用个人资料跟进。

    还有一件事,如果您担心超线程会妨碍您,请将进程硬关联到非 HT 核心。您可以通过 GUI 中的任务管理器或通过 SetThreadAffinityMask 执行此操作。

    -瑞克

    【讨论】:

      【解决方案4】:

      Core i7 是超线程的 - 您是否启用了 HT?

      也许 C++ 代码以某种方式被编译以利用 HT,而 C 代码却没有。运行代码时任务管理器是什么样的?将负载均匀分布在多少个核心上,或者几个核心最大化?

      【讨论】:

      • 没有线程,除非隐藏在source_send的实现中,这个特性不会是编译器代码生成问题。
      • 进程资源管理器中有 8 个内核可见,并且在处理两个应用程序时有 4 个窗口显示活动。如果我必须衡量水平,我会说 C++ 应用程序使用更多 % cpu,但总的来说,它们看起来都参与了。
      【解决方案5】:

      只是一个疯狂的猜测:如果您正在编译库源代码以及您的应用程序,并且 C API 函数没有声明为 extern "C",那么可能 C++ 版本使用了不同的并且以某种方式更快的调用约定? ?

      另外,如果您将库源代码与您的应用程序一起编译,那么 C++ 编译器可能会将您的库源代码编译为 C++,并且在优化方面比您的 C 编译器更好?

      【讨论】:

      • 我已确保 Visual Studio 将 C 代码编译为 C 代码。使用 extern "C" 并在编译器上设置 /TC 选项
      猜你喜欢
      • 2011-12-25
      • 1970-01-01
      • 1970-01-01
      • 2015-07-17
      • 1970-01-01
      • 2018-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多