gpt4 book ai didi

c# - 管理许多重复的、CPU 密集型任务,并行运行?

转载 作者:太空狗 更新时间:2023-10-30 00:52:19 24 4
gpt4 key购买 nike

我需要尽可能快地不断执行 20 次重复的 CPU 密集型计算。所以有 20 个包含循环方法的任务:

while(!token.IsCancellationRequested) 

尽可能快地重复它们。所有计算同时进行。不幸的是,这使程序无响应,因此补充说:
await Task.Delay(15); 

此时程序没有挂起,但添加延迟不是正确的方法,它不必要地减慢了计算速度。它是没有 MVVM 的 WPF 程序。你建议用什么方法让所有 20 个任务同时工作?它们中的每一个都会在完成后不断重复。我想将 CPU(所有内核)利用率保持在最大值(或接近)以确保最佳效率。

编辑 :
有 20 个控件,用户可以在其中调整一些参数。计算在:
private async Task Calculate()
{
Task task001 = null;
task001 = Task.Run(async () =>
{
while (!CTSFor_task001.IsCancellationRequested)
{
await Task.Delay(15);
await CPUIntensiveMethod();
}
}, CTSFor_task001.Token);
}

每个控件都是独立的。计算 100% 受 CPU 限制,没有 I/O 事件。 (所有值都来自变量)在计算过程中,一些 UI 项的值发生了变化:
 this.Dispatcher.BeginInvoke(new Action(() =>
{
this.lbl_001.Content = "someString";
}));

最佳答案

让我把整个事情写下来作为答案。您混淆了两个相关但最终独立的概念(谢天谢地 - 这就是您可以从区别中受益的原因)。请注意,这些是我对这些概念的定义——您会听到大量相同事物的不同名称,反之亦然。

异步性是关于打破操作的强加同步性(即 op 1 等待 op 2,它等待 op 3,它等待 op 4 ......)。对我来说,这是更笼统的概念,但现在它更常用来表示我所说的“固有的异步性”——即。算法本身是异步的,我们只使用同步编程,因为我们必须这样做(感谢 awaitasync ,我们不再需要了,耶!)。

这里的关键思想是等待 .我不能在 CPU 上做任何事情,因为我在等待 I/O 操作的结果。这种异步编程基于异步操作几乎不占用 CPU 的思想——它们是 I/O 绑定(bind)的,而不是 CPU 绑定(bind)的。

并行性是一种特殊的一般异步性,其中操作不主要是相互等待。换句话说,我不是在等待,我是 工作 .如果我有四个 CPU 内核,理想情况下我可以使用四个计算线程来进行这种处理——在理想情况下,我的算法将随着可用内核的数量线性扩展。

由于异步性( 等待 ),无论可用逻辑内核的数量如何,使用更多线程都将提高明显速度。这是因为 99% 的时间,代码实际上并没有做任何工作,它只是在等待。

使用并行性( 工作 ),使用更多线程与可用工作核心的数量直接相关。

线条模糊了很多。那是因为你甚至可能不知道正在发生的事情,例如 CPU(和整个计算机)本身就是令人难以置信的异步 - 它显示的明显同步性只是为了让你同步编写代码;所有优化和异步性都受到这样一个事实的限制,即在输出时,一切都再次同步。如果每次执行 i ++ 时 CPU 都必须等待内存中的数据,您的 CPU 运行在 3 GHz 还是 100 MHz 都没有关系。您出色的 3 GHz CPU 将有 99% 的时间处于空闲状态。

话虽如此,您的计算任务受 CPU 限制。它们应该使用并行执行,因为它们正在工作。另一方面,UI 是 I/O 绑定(bind)的,它应该使用异步代码。

实际上,您所有的async Calculate方法的作用是它掩盖了它实际上并不是天生异步的事实。相反,您希望与 I/O 异步运行它。

换句话说,它不是 Calculate异步的方法。 UI 希望它与自身异步运行。删除所有 Task.Run从那里杂乱无章,它不属于。

接下来做什么?这取决于您的用例。基本上,有两种情况:

您希望任务始终在后台运行,始终从头到尾运行。在这种情况下,只需为它们每个创建一个线程,不要使用 Task一点也不。您可能还想探索一些选项,如生产者-消费者队列等,以优化不同可能计算任务的实际运行时间。实际的实现与您实际处理的内容紧密相关。

或者,您希望在 UI 操作上启动任务,然后在结果准备好时在启动它们的 UI 方法中使用结果值。在这种情况下,await终于来玩了:

private btn_Click(object sender, EventArgs e)
{
var result = await Task.Run(Calculate);

// Do some (little) work with the result once we get it
tbxResult.Text = result;
}
async关键字实际上在您的代码中根本没有位置。

希望这现在更清楚了,请随时提出更多问题。

关于c# - 管理许多重复的、CPU 密集型任务,并行运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21904292/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com