1

現実的な物理シミュレーションを作成しており、正しく動作していますが、フレームレートがすぐに低下します。

各オブジェクトを繰り返し処理し、次にそれらのオブジェクトごとに繰り返します。

各フレームの操作数は同じままなので、なぜそうなるのかはわかりません。私が考えることができる唯一のことは、スレッドが問題であるということです。反復を 4 つの部分に分割し、リストの 4 分の 1 を 4 つの別々のスレッドで計算していますが、タスク マネージャーを確認すると、実際には 1 つのコアしか使用していません。

関連するコードは次のとおりです。

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

In regards to a comment you've left on another answer: more threads != performance increase. You may be surprised how many things actually perform better in serial rather than in parallel. Of course, that doesn't mean that your code can't benefit from multiple threads on different cores, just that you shouldn't assume adding more threads will magically cause your processing throughput to increase.

It's difficult to say what will help your code perform better, without being able to look at more of it. First, it's helpful to know a little bit about the threading model in .NET. I would recommend you read about it, since I can't go into much detail here. A thread in .NET is not necessarily a native thread. That is to say that by the time you queue the third physics method in the ThreadPool, the first might be done, and so it will just use the thread already created. Of course, then there's the time where you queue a task right before another one finishes and an additional (costly) native thread has to be created. In that case, it's possible that less threads might have been better.

The idea of abstraction goes further when you look at the Task Parallel Library, where each task may seem like a thread, but really is much further from it. Many tasks can wind up running on the same thread. You can get around this by hinting to the TaskFactory that it's a long running task, ie Task.Factory.StartNew(() => DoWork(), TaskCreationOptions.LongRunning), which causes the scheduler to start this task on a new thread (this, again, might not be better than just having the runtime schedule it for you).

All this being said, if your work takes enough time to process, it will wind up running on a separate thread if you're queuing it with the ThreadPool. If the work happens fast enough, though, it would appear that only one thread or one core is being used.

  • What led you to the conclusion that that you're only using one core?
  • Was it only what you saw from Task Manager? That's hardly a conclusive result.
  • Did you try adding a column to the Task Manager detail tab for threads, and actually check if your code is spawning additional threads or not?
  • I also see that you're iterating over the array of Bodies twice, is there any particular reason you can't update the bodies with the GameTime in parallel as well (perhaps some limitation in XNA)?

All of the above is just a shot in the dark though. If you really, and I mean really want to know where any performance issues lie, you'll profile your code with a decent profiler, like Ants by RedGate, dotTrace by JetBrains, or if you have the Premium or above edition of Visual Studio, the analyzer built right into your IDE.

I'm not sure your problem is where you think it is, and in my experience, it rarely is. I hope that some of my brain dump above can be of some help to you.

于 2012-11-20T07:01:46.753 に答える