1

我正在创建一个物理模拟,这意味着它是真实的,我让它正常工作,但帧率下降得很快。

我正在遍历每个对象,然后再遍历每个对象。

我不确定为什么会这样,因为每帧中的操作数保持不变。我唯一能想到的是线程是问题所在。我将迭代分为四个部分,并且我有四分之一的列表是在 4 个单独的线程上计算的,但是当我检查任务管理器时,我实际上只使用了一个内核。

以下是相关代码:

private void Update(GameTime gameTime)
{
    for (int i = 0; i < Bodies.Count; i++)
    {
        Bodies[i].Update(gameTime);
    }

    ThreadPool.QueueUserWorkItem(new WaitCallback(CalculatePhysics0));
    ThreadPool.QueueUserWorkItem(new WaitCallback(CalculatePhysics1));
    ThreadPool.QueueUserWorkItem(new WaitCallback(CalculatePhysics2));
    ThreadPool.QueueUserWorkItem(new WaitCallback(CalculatePhysics3));
}

private void CalculatePhysics0(object o)
{
    for (int i = 0; i < Bodies.Count/4; i++)
    {
        Body body = Bodies[i];
        g.ApplyTo(ref body, Bodies);
    }
}

// 3 other methods exactly the same, but iterating their portion of the list

我对多线程不是很有经验。不过,我可以处理因使用它而产生的问题。我可以看到问题可能是这ThreadPool不是实现我想要的效果的好方法,即在线程之间同时遍历列表。

4

2 回答 2

1

您可以使用Task Parallel Library,这有助于使大部分工作变得更容易。这应该在 XNA 4.0+ 中可用

Task.Factory.StartNew(()=>CalculatePhysics0);

我相信默认行为应该有效,但您可以指定TaskCreationOption

如果这不起作用,那么您可以使用TaskScheduler

var scheduler = new TaskScheduler{MaximumConcurrencyLevel=4};
Task.Factory.StartNew(()=>CalculatePhysics0, null, TaskCreationOptions.None, scheduler);
于 2012-11-20T05:09:06.477 回答
0

关于您在另一个答案上留下的评论:更多线程!=性能提升。您可能会惊讶有多少事情实际上在串行而不是并行中表现得更好。当然,这并不意味着您的代码不能从不同内核上的多个线程中受益,只是您不应该假设添加更多线程会神奇地导致您的处理吞吐量增加。

很难说什么可以帮助您的代码更好地执行,而无法查看更多内容。首先,了解一点 .NET 中的线程模型会很有帮助。我建议你阅读它,因为我不能在这里详细介绍。.NET 中的线程不一定是本机线程。也就是说,当您将第三个物理方法排入队列时,第一个物理方法ThreadPool可能已经完成,因此它只会使用已经创建的线程。当然,有时您会在另一个任务完成之前将一个任务排队,并且必须创建一个额外的(昂贵的)本机线程。在这种情况下,更少的线程可能会更好。

当您查看任务并行库时,抽象的想法会更进一步,其中每个任务可能看起来像一个线程,但实际上离它更远。许多任务最终可以在同一个线程上运行。你可以通过暗示TaskFactory这是一个长时间运行的任务来解决这个问题,即Task.Factory.StartNew(() => DoWork(), TaskCreationOptions.LongRunning),这会导致调度程序在一个新线程上启动这个任务(同样,这可能并不比让运行时为你安排它更好)。

话虽如此,如果你的工作需要足够的时间来处理,如果你用ThreadPool. 但是,如果工作进行得足够快,则似乎只使用了一个线程或一个内核。

  • 是什么让你得出你只使用一个核心的结论?
  • 它只是您从任务管理器中看到的吗?这几乎不是一个决定性的结果。
  • 您是否尝试在线程的任务管理器详细信息选项卡中添加一列,并实际检查您的代码是否产生了额外的线程?
  • 我还看到您正在迭代数组Bodies两次,是否有任何特殊原因您不能同时更新主体GameTime(可能是 XNA 中的一些限制)?

不过,以上所有这些都只是在黑暗中拍摄。如果你真的,我的意思是真的想知道任何性能问题出在哪里,你会用一个像样的分析器来分析你的代码,比如RedGate 的 AntsJetBrains 的 dotTrace,或者如果你有 Visual Studio 的高级版或更高版本,分析仪内置在您的 IDE 中。

我不确定您的问题是否在您认为的位置,根据我的经验,它很少出现。我希望我上面的一些脑筋急转弯可以对你有所帮助。

于 2012-11-20T07:01:46.753 回答