【发布时间】:2018-12-04 15:26:44
【问题描述】:
我需要什么:
我需要在多线程中运行一组方法,每个内核最多 1 个线程。这些线程中的每一个都需要具有限制功能才能限制所有线程的 CPU 使用率。如果我在运行 3 个线程的 4 个内核上指定 10%(因为我选择 3 个是最大值),那么所有 3 个线程每个内核的 CPU 使用率不得超过 10%。就像 Steam 这样的应用程序,您可以限制下载速度,但想象一下您将有多个 Internet 连接来表示多核。
我尝试了什么:
我尝试过使用Task,但我不知道如何管理它创建的最大线程数,甚至不知道它们各自使用哪个内核。
我最终得到了什么:
我最终找到了 Parallel.ForEach 和 ParallelOptions.MaxDegreeOfParallelism 的组合,这让我完全可以控制线程数量。我知道我有多少核心,我可以轻松地制作一些东西让用户选择要使用的核心数量。我的测试得出结论,Parallel.ForEach 属性按顺序在每个核心上工作,一旦所有核心都收到了一些东西,它就会循环回来并再次重新分配。这是完美的。如果我在 4 核上设置 3 的并行度,我会在 3 个不同的核上得到 3 个线程,而在 4 核上设置 5 的并行度则 3 核将有 1 个线程,1 核将有 2 个。这种行为正是我需要的。这种方法不是一成不变的,我愿意改变。
CPU 限制
现在使用Parallel.ForEach 使 cpu 100% 的时间工作,这在那种紧凑的环境中是一个大问题,在很长一段时间内,在许多计算机上任何超过 40-50% 的使用都会增加如此多的功耗它会在建筑物中触发严重警报,我们需要低于该警报。无论如何,除了在紧密循环中执行 thread.sleep 之外,我没有找到任何解决方案,但这仍然使 cpu 在几秒钟内运行 100%,然后在更长的时间内接近 0%,然后它一遍又一遍地这样做。这没有用。我在一个只有 150 台计算机的房间里进行了一项小型测试,其中一半在几乎相同的时间以 100% 的速度飙升,消耗了太多的电量。我的第二个测试是仅使用 8 个或更多内核并仅在 1 个内核上运行,这样可以大大减少使用量。
优先级
我终于测试了进程优先级,但这并没有更好。是的,该进程接收的 CPU 时间更少,但当我获得电源时,cpu 仍以 100% 运行。除非我在处理可能限制 CPU 的优先级时错过了关键选项。
终于
我感觉我与Parallel.ForEach 非常接近,我只是错过了每个内核的 CPU 限制。我只缺少一件事吗?我知道使用Thread.Sleep 是完全愚蠢的,因为它实际上限制了cpu 的使用时间而不是数量。
对于那些想要代码的人
这又是原型,所以代码几乎没用。它所做的一切都是在许多 cpu 上运行代码,直到完成
static void Main(string[] args)
{
var items = Enumerable.Range(0, int.MaxValue - 100);
Parallel.ForEach(
items,
new ParallelOptions { MaxDegreeOfParallelism = 4 },
value => { Calculate(value); }
);
}
private static void Calculate(int value)
{
System.Threading.Thread.SpinWait(100000);
var test = value;
test *= -1;
Console.WriteLine(test);
}
【问题讨论】:
-
SpinWait就是这样做的。 -
@DanielA.White 所以你的意思是技术上
SpinWait应该给我一种方法来减少我的 CPU 使用率?我发布的代码从 1000 开始并添加了零,直到我看到差异并且它没有改变任何东西。 CPU 仍然达到每核 60-70%。 -
没有我说旋转等待会加载。
-
@DanielA.White 好吧,我明白你的意思。无论如何
SpinWait我最初把它放在那里替换Thread.Sleep看看它是如何影响CPU 使用率的。也不好。
标签: c#