通过设置关联性在单核上运行多线程程序的性能?

Nat*_*Dre 4 multithreading mutex affinity allegro5 physics-engine

简而言之:

在什么情况下可以在单个核心上运行多线程应用程序破坏性能?

如何将多线程应用程序的亲和力设置为仅使用一个核心?

长期:

我正试图在它自己的线程上运行2D引擎的物理特性.它起作用,并且起初表现似乎正常,但我决定告诉游戏尝试以10K FPS运行并且物理速度为120FPS,进入任务管理器并将亲和力设置为程序只能使用一个核心.

在将亲和力设定为一个核心之前,FPS在~1700,然后达到~70FPS.我没想到那种减少.我告诉游戏尝试以300 FPS和60FPS的物理速度运行.

同样的事发生了.

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

这是关于渲染/物理运行的方式......

循环开始

收集输入直到(1.0/FPS)过去.

致电更新.

锁定物理线程互斥体,因为游戏中的东西将使用物理数据,我不希望引擎更新任何内容,直到此更新调用中的所有内容都完成.

更新游戏中的所有内容,可以将渲染功能对象(包含绘制内容,绘制位置,如何绘制)发送到渲染队列.

解锁互斥锁.

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

更新屏幕.

重复循环.

物理线程循环:

    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();

    }
Run Code Online (Sandbox Code Playgroud)

//注意:Auto mutex只是我创建的一个非常简单的对象,用于在构造函数中锁定互斥锁并在析构函数中解锁它.我正在使用Allegro 5的线程功能.

jal*_*alf 7

在什么情况下可以在单个核心上运行多线程应用程序破坏性能?

如何将多线程应用程序的亲和力设置为仅使用一个核心?

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

当在多个内核上运行时,两个需要交互的线程都可能同时运行,因此操作系统不需要为您的代码执行上下文切换.

实际上,需要大量线程间同步的代码在单个内核上运行速度较慢.

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

如果你只是做一些"当条件不满足时,保持循环"忙循环,你保持线程运行,即使它没有任何关系.它将继续循环*,直到操作系统决定其时间结束,并安排另一个线程.(如果线程没有被某些东西阻挡,它通常会被允许一次运行超过10毫秒.)

在一般的多线程编程中,*尤其是在单核上运行的多线程代码,你需要玩得很好,而不是超过必要的CPU核心.如果您没有任何明智的做法,请允许其他线程运行.

并猜猜你的代码在做什么.

你认为这些线的影响是什么?

   if (!(al_get_timer_count(timer) > prevCount))
        continue;
Run Code Online (Sandbox Code Playgroud)

跑圈!我准备好跑吗?没有?然后再开环.我现在准备好了吗?仍然没有?再次循环......

换句话说,"我现在拥有CPU,而且我永远不会转移!如果有人想要CPU,他们就必须从我死的身体中取出它!"

如果您没有使用CPU,那么请放弃它,特别是如果您有另一个准备运行的线程.

使用互斥锁或其他同步原语,或者如果您对基于时间的睡眠周期更加近似,请致电Sleep().

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