首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >通过设置亲和性在单核上运行多线程程序的性能?

通过设置亲和性在单核上运行多线程程序的性能?
EN

Stack Overflow用户
提问于 2011-09-24 02:37:49
回答 2查看 3.5K关注 0票数 4

简而言之:

在什么情况下,在单核上运行多线程应用会破坏性能?

如果将多线程应用程序的亲和性设置为只使用一个内核呢?

在long中:

我试着在2D引擎自己的线程上运行它的物理特性。它可以工作,一开始性能似乎很正常,但我决定告诉游戏尝试以10K FPS运行,物理运行在120FPS,进入任务管理器并设置亲和力,程序只能使用一个内核。

在设置到一个核心的亲和力之前,FPS为~1700,之后为~70FPS。我没想到会有这样的下降。我告诉游戏运行速度为300fps,物理速度为60FPS。

同样的事情也发生了。

我没有考虑太多,所以我只是继续修改引擎。在修改了一些绘图代码后,我再次测试了它,300fps,60FPS的物理。在允许所有内核的情况下,它可以很好地管理300FPS,与单核FPS的亲和力下降到4。现在我知道在单核上运行多线程应用程序不可能那么糟糕,或者我不知道当您将亲和力设置为单核时会发生什么。

这是关于渲染/物理如何运行的。

循环开始

收集输入,直到(1.0 / FPS)通过。

调用update。

锁定物理线程互斥,因为游戏中的东西将使用物理数据,我不想让引擎更新任何东西,直到这个update调用中的所有东西都完成。

更新游戏中可能发送绘制函数对象(保存绘制内容,绘制位置,如何绘制)到渲染队列的所有内容。

解锁互斥锁。

渲染器在每个函数对象上调用operator(),并将它们从队列中删除。

更新屏幕。

重复循环。

物理线程循环:

代码语言:javascript
复制
    ALLEGRO_TIMER* timer(al_create_timer(1.0f / 60.0f));
    double prevCount(0);

    al_start_timer(timer);
    while(true)
    {
        auto_mutex lock(m_mutex);

        if(m_shutdown)
            break;
        if (!m_allowedToStep)
            continue;
                    // Don't run too fast. This isn't final, just simple test code.
        if (!(al_get_timer_count(timer) > prevCount))
            continue;

        prevCount = al_get_timer_count(timer);

        m_world->Step(1.0f / 60.0f, 10, 10); 
        m_world->ClearForces();

    }

//注意:自动互斥锁只是我创建的一个非常简单的对象,用于在构造函数中锁定互斥锁,并在析构函数中解锁。我使用的是Allegro 5的线程函数。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-09-24 04:48:02

在什么情况下,在单核上运行多线程应用会破坏性能?

如果将多线程应用程序的亲和性设置为只使用一个内核呢?

在这两种情况下,答案基本相同。如果你的程序在一个内核上运行,那么一次只有一个线程运行。这意味着,每当一个线程必须等待另一个线程时,您需要操作系统执行上下文切换,这是一个相当昂贵的操作。

当在多核上运行时,需要交互的两个线程很有可能同时运行,因此操作系统不需要执行上下文切换即可继续执行代码。

因此,实际上,需要大量线程间同步的代码在单核上的运行速度会更慢。

但你可以让事情变得更糟。自旋锁或任何类型的忙碌等待循环都会完全破坏性能。原因应该是显而易见的。您一次只能运行一个线程,因此如果您需要一个线程等待某个事件,您应该告诉操作系统立即将其置于休眠状态,以便另一个线程可以运行。

如果你只是做了一些“虽然条件不满足,保持循环”的繁忙循环,你保持线程运行,即使它没有做任何事情。它将继续循环*,直到操作系统决定它的时间到了,并且它调度另一个线程。(如果线程没有被某些东西阻塞,它通常会被允许一次运行10毫秒以上。)

在一般的多线程编程中,尤其是在单核上运行的多线程代码中,你需要表现得很好,而不是在必要的情况下占用CPU核心。如果你没有什么可做的,允许另一个线程运行。

猜猜你的代码在做什么。

你认为这些线条的效果是什么?

代码语言:javascript
复制
   if (!(al_get_timer_count(timer) > prevCount))
        continue;

运行循环!我准备好跑了吗?不是吗?然后再次运行循环。我现在可以跑了吗?还是没有?再次运行循环.....

换句话说,“我现在有了CPU,我永远不会投降!如果其他人想要CPU,他们就必须从我冰冷的身体上拿走它!”

如果你没有什么可以使用的CPU,那就放弃它,如果你有另一个准备运行的线程,尤其是

使用互斥或其他一些同步原语,或者如果您可以使用更近似的基于时间的休眠周期,则调用Sleep()

但是,如果你想要任何一种不错的性能,如果你在等待另一个线程来做一些处理,不要无限期地占用CPU。

票数 8
EN

Stack Overflow用户

发布于 2011-09-24 02:54:46

当你看处理器的时候,不要把它看作一个计算一件事情接着一件事情的块。把它看作是一个计算器,你必须为它预留一个时间

Windows (和所有操作系统)确保为所有正在运行的应用程序保留此时间。当你运行一个程序时,计算机并不只是做新程序想要的所有计算,windows会给程序分配一段特定的时间。当该时间结束时,下一个程序将获得一些时间。windows为您完成了所有这些工作,因此只有当您想要了解它时,它才是相关的。

这确实会影响你看待多线程的方式,因为当windows环顾四周,看到一个多线程的应用程序时,它会说“我将把它作为两个独立的程序来处理”,所以它会为这两个程序分配时间。因此,其中一个不会完全阻止另一个进行计算。

所以,多线程运行不会降低程序的性能,但会使周围的其他程序变得更慢。并产生少量的开销。但是,如果您正在进行大型计算,并且这会导致您的程序挂起,那么可以自由地使用多线程。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7533415

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档