为什么单个线程比多线程更快,即使它们基本上具有相同的开销?

lul*_*loo 5 c++ windows cpu multithreading metrics

我在8核处理器上运行64位Windows 7.我运行了以下内容:

    #include "stdafx.h"
    #include <iostream>
    #include <Windows.h>
    #include <process.h>
    #include <ctime>

    using namespace std;

    int count = 0;
    int t = time(NULL);

    //poop() loops incrementing count until it is 300 million.
    void poop(void* params) {
        while(count < 300000000) {
            count++;
        }


        cout<< time(NULL) - t <<" \n";
    }

    int _tmain(int argc, _TCHAR* argv[])
    {
        //_beginthread(poop, 0, NULL);      
        //_beginthread(poop, 0, NULL);
        poop(NULL);

        cout<<"done"<<endl;

        while(1);

        return 0;
    }
Run Code Online (Sandbox Code Playgroud)

我将结果与取消注释beginThread的结果进行了比较.事实证明,单线程版本以最快的速度实现了这一目标!实际上,添加更多线程会使该过程花费更长时间.计算3亿这个过程需要花费8+秒,我认为这足以排除函数调用beginThread +其他小的开销.

我做了一些研究,并且多线程进程变慢的一般结论是开销.但在这种情况下,无论我运行多个线程还是单个线程,访问变量计数(存在于数据段中,因为它是预先分配的变量afaik)的次数是相等的.所以基本上,开销(如果它是一个开销问题)并不是因为访问全局变量而不是局部变量花费更多.

查看我的任务管理器,使用单个线程的进程使用13%cpu(大约1/8核心),并且添加线程会以1/8左右的增量增加cpu使用率.因此就cpu功率而言,假设任务管理器准确地描述了这一点,添加线程使用更多的cpu.这进一步让我感到困惑..我是如何使用更多整体cpu,使用单独的内核,但总体上需要更长的时间来完成任务?

TLDR:为什么会发生这种情况

SLa*_*aks 5

您的代码本质上是错误的.

count++是一个三步操作,读取值,递增值,然后将其存储回变量.
如果两个线程同时count++在同一个变量上运行,则其中一个线程将覆盖另一个线程的更改.

因此,多线程版本最终将完成额外的工作,因为每个线程都会破坏其他线程的进度.

如果你创建count一个局部变量,时间应该看起来更正常.

或者,您可以使用互锁增量,这是线程安全的,但是有跨线程同步的额外开销.

  • @lululoo:不,因为只有一个线程会立即更新`count`.这就是同步的全部意义所在.递增整数需要加载,增量和存储.它不是原子操作.这不是多线程解决方案的理想选择.您应该考虑一个更现实的世界问题,即可以分解为离散和单独任务的任务. (4认同)