使用.NETs ThreadPool

时间:2015-05-05 01:37:34

标签: multithreading unity3d threadpool

我之前已经问过这个问题,但没有提供代码,因为我没有这么简单的方法。然而,现在我已经在Unity开始了一个新项目,并尝试复制行为,而不会附加所有不必要的行李。

所以这是我目前的设置:

public class Main : MonoBehaviour
{
    public GameObject calculatorPrefab;
    void Start ()
    {
        for (int i = 0; i < 10000; i++)
        {
            Instantiate(calculatorPrefab);
        }
    }
}

public class Calculator : MonoBehaviour
{
    void Start ()
    {
        ThreadPool.QueueUserWorkItem(DoCalculations);
    }

    void DoCalculations(object o)
    {
            // Just doing some pointless calculations so the thread actually has something to do.
            float result = 0;
            for (int i = 0; i < 1000; i++)
            {
                    // Note that the loop count doesn't seem to matter at all, other than taking longer.
                    for (int i2 = 0; i2 < 1000; i2++)
                    {
                            result = i * i2 * Mathf.Sqrt(i * i2 + 59);
                    }
            }
    }
}

这两个脚本都附加到GameObjects。 'Main'脚本位于放置在场景中的GameObject上,并且应该在启动时创建一堆其他GameObject,然后为ThreadPool排队一些随机计算。显然,这会在启动时产生相当大的CPU峰值,但这不是问题所在。问题是主线程似乎被这个阻塞了。换句话说,它会产生可怕的fps。这是为什么 ?它不应该在后台运行吗?这背后的重点不是让主线程没有反应吗?

我真的很难弄明白我做错了什么,因为据我所知,它并没有比这简单得多。

2 个答案:

答案 0 :(得分:0)

在第一帧上,您实例化10000个预制件。这对于单帧来说是相当大的负担。在第二帧上初始化10000个线程池。这是很多线程,我相信你会遇到一些前期初始化成本。

后台任务并不复杂。我使用后台任务进行长时间运行。例如Web调用和长时间运行的计算。我不认为你的任务真的适合。换句话说,前期成本超出了运行计算的成本。

尝试使用协程来分解您的计算和实例化。我认为这是针对这一特定背景任务的更好解决方案。

编辑根据以下评论进行一些测试。

  • 10k实例化取平均值(中位数)104毫秒。编辑器的帧速率很差,占据了我I7 CPU容量的15%左右。
  • 10k QueueUserWorkItem取平均值(中位数)23毫秒。编辑器锁定了几秒钟。我的cpu容量有99%的容量。

<强>结论 排队工作线程有一些成本,但不是很多。问题主要在于你的实例化。那,为什么我们为这样一个简单的计算而调整了1000个工作线程?

答案 1 :(得分:0)

我发现您的代码存在以下问题。

  1. 您正在创建太多的后台作业,精确到10,000。 .NET不会同时运行它们,但仍然可能不是最好的方法。在我的机器上(8个逻辑核心),通过ThreadPool.GetMaxThreads()的初始最大工作人员是1023

  2. 每项工作都相当复杂。 Sqrt的计算并不便宜,难怪需要这么长时间

  3. Unity提供了更新方法和绘图方法。这里的问题是你的工作正在进行,因此拖延了一切,包括更新;画画;以及介于两者之间而不是在Update()

  4. 期间发生的计算

    使用您的代码并在一个独立的.NET应用程序中运行它,花了 15秒来完成最大化所有8个内核

    然而,改变

    result = i * i2 * Mathf.Sqrt(i * i2 + 59)
    

    ......来:

    result = i * i2 * i * i2 + 59;
    

    ...也像以前一样最大化了我的所有8个核心,但这次耗时6秒。

    你可能会问,&#34;你带走了sqrt,你的观点是什么&#34; 。我的观点是,我不相信你意识到如何密集召唤Sqrt特别是这句话:

      

    它仍然很糟糕。我甚至将创建的对象数量从10000减少到100,同时增加了循环次数,因此仍需要一段时间。没有真正的区别

    此外,安排如此多的工作,无论技术如何,纯粹是为了更新游戏对象都不会扩展。游戏设计师分批更新。

    我的建议:

    设计提示

    通常,当必须对许多对象执行大量计算时,而不是在一个帧中执行此操作,将它们分组并随着时间的推移将它们展开。那么10,000个物体的批量大小可能是1000或100? 来源城市:天际线;

    告诉我更多

    enter image description here

    图片版权各自所有者