6

我有一个用 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" );
}

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

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

编辑:来自评论的附加信息

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

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

4

5 回答 5

7

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

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

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

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

祝你好运。

更新

您可以使用 Microsoft 工具链执行相同的操作。

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

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

于 2010-01-13T05:01:11.217 回答
2

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

于 2010-01-13T06:00:05.030 回答
1

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

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

这应该出现在一个好的分析器中,如果你有一个更高端的 VS SKU,那么基于采样的分析器就很好,如果你正在寻找一个好的免费分析器,Windows 性能分析器对于 Vista 来说非常强大,这里有一个演练使用 stackwalking 选项

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

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

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

-瑞克

于 2010-01-13T05:52:54.030 回答
0

Core i7 是超线程的——你启用了 HT 吗?

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

于 2010-01-13T04:51:37.007 回答
0

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

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

于 2010-01-13T05:08:39.830 回答