c++ - 跨线程扩展 MSVC 2005 的运算符 << 时出现性能问题

标签 c++ performance multithreading scaling iostream

在查看我们的一些日志记录时,我在分析器中注意到我们在 operator<< 上花费了大量时间。格式化整数等。看起来有一个共享锁,每当 ostream::operator<< 时都会使用。在格式化 int (并且可能是 double )时调用。经过进一步调查,我将范围缩小到这个例子:

使用 ostringstream 的 Loop1进行格式化:

DWORD WINAPI doWork1(void* param)
{
    int nTimes = *static_cast<int*>(param);
    for (int i = 0; i < nTimes; ++i)
    {
        ostringstream out;
        out << "[0";
        for (int j = 1; j < 100; ++j)
            out << ", " << j; 
        out << "]\n";
    }
    return 0;
}

使用相同的 ostringstream 的 Loop2执行除 int 格式之外的所有操作,这是通过 itoa 完成的:

DWORD WINAPI doWork2(void* param)
{
    int nTimes = *static_cast<int*>(param);
    for (int i = 0; i < nTimes; ++i)
    {
        ostringstream out;
        char buffer[13];
        out << "[0";
        for (int j = 1; j < 100; ++j)
        {
            _itoa_s(j, buffer, 10);
            out << ", " << buffer;
        }
        out << "]\n";
    }
    return 0;
}

在我的测试中,我使用 1、2、3 和 4 个线程多次运行每个循环(我有一台 4 核机器)。试验次数是恒定的。这是输出:

doWork1: all ostringstream
n       Total
1         557
2        8092
3       15916
4       15501

doWork2: use itoa
n       Total
1         200
2         112
3         100
4         105

正如您所看到的,使用 ostringstream 时的性能非常糟糕。当添加更多线程时,情况会变得更糟 30 倍,而 itoa 的速度会快 2 倍。

一个想法是使用_configthreadlocale(_ENABLE_PER_THREAD_LOCALE)根据 M$ in this article 的推荐。这似乎对我没有帮助。 Here's another user谁似乎也有类似的问题。

我们需要能够在应用程序并行运行的多个线程中格式化整数。鉴于这个问题,我们要么需要弄清楚如何使其工作,要么找到另一种格式化解决方案。我可以编写一个简单的类,其中为整型和浮点类型重载了operator<<,然后有一个模板化版本,只在底层流上调用operator<<。有点难看,但我想我可以让它工作,尽管可能不适用于用户定义operator<<(ostream&,T)因为它不是 ostream

我还应该明确指出,这是使用 Microsoft Visual Studio 2005 构建的。我相信这个限制来自于他们对标准库的实现。

最佳答案

如果 Visual Studio 2005 的标准库实现有错误,为什么不尝试其他实现呢?喜欢:

甚至Dinkumware Visual Studio 2005 标准库所基于的标准库可能自 2005 年以来就已经解决了该问题。

编辑:您提到的另一位用户使用的是 Visual Studio 2008 SP1,这意味着 Dinkumware 可能尚未修复此问题。

关于c++ - 跨线程扩展 MSVC 2005 的运算符 << 时出现性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1363817/

相关文章:

performance - 在 Rust 中,如何将快速的始终为空且单条目的 HashMap 传递给第三方 API?

windows - 程序完成执行后的线程状态

在 Ui 线程上运行的 Android 注释

c++ - boost:如何监视互斥体的状态并在死锁时强制释放

c++ - 如何为 unsigned char 类型编译 boost::spirit ?

c++ - 在 C 的 main 中调用函数后定义和声明函数是否可移植?

c++ - Eigen:稀疏-密集积到普通 C++ 数组

python - 我应该在应用程序中还是在数据库中生成 UUID?

c - 如何编写更高效的代码

python - Flask session 变量是否跨线程维护状态?