我之前已经问过这个问题,但没有提供代码,因为我没有这么简单的方法。然而,现在我已经在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。这是为什么 ?它不应该在后台运行吗?这背后的重点不是让主线程没有反应吗?
我真的很难弄明白我做错了什么,因为据我所知,它并没有比这简单得多。
答案 0 :(得分:0)
在第一帧上,您实例化10000个预制件。这对于单帧来说是相当大的负担。在第二帧上初始化10000个线程池。这是很多线程,我相信你会遇到一些前期初始化成本。
后台任务并不复杂。我使用后台任务进行长时间运行。例如Web调用和长时间运行的计算。我不认为你的任务真的适合。换句话说,前期成本超出了运行计算的成本。
尝试使用协程来分解您的计算和实例化。我认为这是针对这一特定背景任务的更好解决方案。
编辑根据以下评论进行一些测试。
<强>结论强> 排队工作线程有一些成本,但不是很多。问题主要在于你的实例化。那,为什么我们为这样一个简单的计算而调整了1000个工作线程?
答案 1 :(得分:0)
我发现您的代码存在以下问题。
您正在创建太多的后台作业,精确到10,000。 .NET不会同时运行它们,但仍然可能不是最好的方法。在我的机器上(8个逻辑核心),通过ThreadPool.GetMaxThreads()
的初始最大工作人员是1023
每项工作都相当复杂。 Sqrt的计算并不便宜,难怪需要这么长时间
Unity提供了更新方法和绘图方法。这里的问题是你的工作正在进行,因此拖延了一切,包括更新;画画;以及介于两者之间而不是在Update()
使用您的代码并在一个独立的.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? 来源:城市:天际线;
图片版权各自所有者