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

问题描述 投票:1回答:2

我想在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个核心。我应该怎么做才能在不同的核心并行运行线程以实现高性能?

c++ multithreading mfc
2个回答
3
投票

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

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

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

试试这个:

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;
}

确保计算不是太简单,因为优化器非常聪明,可能会将您的O(n)算法转换为O(1)。它甚至可以在编译时执行整个计算,并且仅在运行时分配常量。为避免这种情况,您可以从cin中读取循环迭代次数。虽然在MSVC 2017上测试上述代码时没有必要这样做,即使进行了全面优化。


-1
投票

阅读并发运行时。它可以帮助你没有头痛:https://msdn.microsoft.com/en-us/library/dd504870.aspx

© www.soinside.com 2019 - 2024. All rights reserved.