MFC多线程程序可以并行方式运行吗?

时间:2017-12-26 09:20:56

标签: c++ multithreading mfc

我想在MFC中使用多线程。我做了一个小实验,看看程序是否以并行方式运行。我写了两个这样的线程函数:

UINT CMFCApplication2Dlg::thread01(LPVOID pParam)
{
    clock_t t1, t2;
    t1 = clock();
    for (int i = 0; i < 300000; i++)
        cout << "thread01111111111" << endl;

    t2 = clock();
    cout << "clock is " << t2 - t1 << endl;
    return 0;
}

UINT CMFCApplication2Dlg::thread02(LPVOID pParam)
{
    clock_t t1, t2;
    t1 = clock();

    for (int i = 0; i < 300000; i++)
        cout << "thread02222222222" << endl;


    t2 = clock();
    cout << "clock is " << t2 - t1 << endl;
    return 0;
}

并调用它们并输出到控制台窗口:

AllocConsole();                     

    freopen("CONOUT$", "w+t", stdout);

    freopen("CONIN$", "r+t", stdin);  

    printf("Hello World!\n");         

    CWinThread *pThread01;
    CWinThread *pThread02;
    pThread01 = AfxBeginThread(thread01, this, 0, 0, 0, NULL);
    pThread02 = AfxBeginThread(thread02, this, 0, 0, 0, NULL);

一起运行两个线程时,计数为118020;运行单线程时,计数为60315;当以串行方式将两个循环放在同一个线程中时,我得到102795。

我曾经认为编译器可以优化多线程自动并行执行,但看起来像单核多线程并发。它不会减少运行时间。我使用的CPU有4个核心。我应该怎么做才能在不同的核心并行运行线程以实现高性能?

2 个答案:

答案 0 :(得分:3)

两个线程都在尝试同时使用共享资源(std::cout)。系统必须在一个点上序列化输出,因此大多数时候其中一个线程将等待另一个线程完成写入。这称为同步。当您使用线程进行性能改进时,您希望尽可能减少同步所花费的时间,因为在此期间线程无法完成有用的工作。

尝试通过冗长的计算替换内部循环中的cout,并且仅在末尾使用cout来打印最终结果,因此编译器无法优化计算(没有{{1它可以,因为计算没有可观察到的影响。)

此外,cout缺乏分析的精确度。我建议使用std::chrono::high_resolution_clock代替,这通常是在Windows平台上使用std::clock实现的。这是Windows上最好的。

试试这个:

QueryPerformanceCounter()

确保计算不是太简单,因为优化器非常聪明,可能会将您的O(n)算法转换为O(1)。它甚至可以在编译时执行整个计算,并且仅在运行时分配常量。 为避免这种情况,您可以从INT CMFCApplication2Dlg::thread01(LPVOID pParam) { using myclock = std::chrono::high_resolution_clock; auto t1 = myclock::now(); std::int64_t first = 0, second = 1, result = 0; for( std::int64_t i = 0; i < 10000000; ++i ) { result = first + second; first = second; second = result; } auto t2 = myclock::now(); std::chrono::duration<double> td = t2 - t1; // duration in seconds std::cout << "result is " << result << '\n' << "clock is " << std::fixed << std::setprecision( 6 ) << td.count() << " s" << std::endl; return 0; } 读取循环迭代次数。虽然在MSVC 2017上测试上述代码时即使完全优化也不需要这样做。

答案 1 :(得分:-1)

阅读并发运行时。它可以帮助你摆脱困境:https://msdn.microsoft.com/en-us/library/dd504870.aspx