【问题标题】:C# create multiple tasks, execution per task is slower than one not parallelC#创建多个任务,每个任务的执行比一个不并行的要慢
【发布时间】:2019-09-24 14:30:37
【问题描述】:

我有这部分代码

bool hasData = true;
using (Context context = new Context())
{
    using (SemaphoreSlim concurrencySemaphore = new SemaphoreSlim(MAX_THREADS))
    {
        while (hasData)
        {
            Message message = context.Database.SqlQuery<Message>($@"
select top(1) * from Message  where 
( Status = {(int)MessageStatusEnum.Pending} ) or 
( Status = {(int)MessageStatusEnum.Paused } and ResumeOn < GETUTCDATE() )
            ").FirstOrDefault();

            if message == null)
            {
                hasData = false;
            }
            else
            {

                concurrencySemaphore.Wait();

                tasks.Add(Task.Factory.StartNew(() =>
                {
                    Process(message);

                    concurrencySemaphore.Release();

                }, this.CancellationToken));

            }
        }
        Task.WaitAll(tasks.ToArray());
    }
}

而我的 Process 函数是这样的

private void Process(Message message)
{
    System.Threading.Thread.Sleep(10000);
}

现在,如果我只有 1 个项目要处理,则总执行时间为 10 秒,每个项目(1 个项目)的执行时间为 10 秒。 好吧,例如,如果我有 10 个项目,那么每个项目的执行时间将增加到 15-20 秒。

我尝试更改 MAX_THREADS 的值,但总是如果我的队列中有超过 10 个项目并开始并行执行,那么每个项目的执行时间约为 15 秒。

我错过了什么?

【问题讨论】:

  • 您的“非并行”代码在哪里?我怀疑ProcessThread.Sleep,因为您正在其中做一些数据库访问(因为没有从select top(1) * from Message 收到相同的消息)... 真正的问题是什么,真正的代码在哪里?
  • 这是一个例子,你可以自己运行。我不是在寻找有关 Process 功能或选择查询的更好代码。我只是想知道,为什么如果我有很多项目正在运行,那么每个项目的执行速度会比我只有 1 个项目时慢。
  • 这是一个示例,您可以自己运行。 context.Database.SqlQuery&lt;Message&gt;
  • 好的。我编辑了 sql 查询。现在更容易理解更深层次的问题了吗?
  • 使用Parallel.ForEach,不要尝试推出自己的等价物。而且,如果您尝试跨 cpus 或线程实现队列,则需要原子的“从队列中获取和删除”操作,而不是选择。如果它不跨 CPU/线程,为什么一次只得到一个?

标签: c# multithreading parallel-processing execution-time thread-synchronization


【解决方案1】:

并不意外。 Parallel Slowdown 是一个非常现实的问题。一方面,我们有pleasingly parallel 操作。另一方面,本质上是串行的东西,比如计算斐波那契数列。而且中间有很多区域。

一般的多任务处理,尤其是多线程处理并不是让一切变得更快的灵丹妙药。我喜欢说:多任务处理必须仔细挑选它的问题。如果你在一个不是为它设计的问题上投入更多的任务,你最终得到的代码是:

  • 更复杂
  • 需要更多内存
  • 最重要的是然后是简单的顺序操作

充其量只是将所有任务管理开销添加到操作中。在最坏的情况下,您会陷入僵局和资源竞争。而且您的睡眠线程示例操作无论如何都不会从多任务处理中受益。请向我们展示您希望通过多任务/线程加速的实际操作。因此,我们可以告诉您是否有任何可行的机会。

【讨论】:

  • 这是一个例子,你可以自己运行。我不是在寻找有关 Process 功能或选择查询的更好代码。我只是想知道,为什么如果我有很多项目正在运行,那么每个项目的执行速度会比我只有 1 个项目时慢。
  • @GomuGomuNoRocket:“充其量只是将所有任务管理开销添加到操作中。”每个操作都会消耗 CPU 周期。这包括管理在单个线程中运行的一堆任务,或者管理一堆线程并在它们之间进行交换。您在没有任何加速的情况下添加了该开销。怎么可能需要更长的时间?
  • 那么,因为我添加了更多并行运行的任务,这种行为是否正常?每个项目的执行比单独执行慢是正常的吗,因为“我要求 c# 管理和安排所有这些任务?” .如何添加任何加速逻辑?
  • @GomuGomuNoRocket 加快速度的唯一方法是为实际问题提供实际代码,这将真正受益 从被分成任务。这不是我能用更笼统的术语来描述的事情。
猜你喜欢
  • 1970-01-01
  • 2016-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多