c# - 如何在某些任务非常昂贵的任务中负载平衡并行性?

标签 c# multithreading parallel-processing task-parallel-library

我有一个需要处理的对象列表。所以说该列表是所有客户的列表,我需要对所有客户执行 CPU 密集型计算。虽然在此计算之前和之后我需要获取数据并将其提交回数据库,因此它不仅仅是一个 CPU 任务。

所以我做的是

Parallel.ForEach(list, action);

Action 就是字面上的意思

1 Fetch customer data
2 Process calculate (time and memory intensive task)
3 Commit back customer data

代码过去运行良好,但最近有时当处理具有非常大量记录多个客户时,我们会导致系统内存不足。

那么有没有办法负载均衡呢?大多数客户都被快速处理,但很少有人能把所有资源都拿走。我能避免他们几个一起跑吗?

我可以实现这一点的一种方法是根据大小对列表进行排序,然后尝试选择第一个和最后一个项目并自己控制并行度,但我想看看我在这里有什么选择。

最佳答案

既然你说你在实际完成计算之前就有了计算大小的近似值,那么它大大简化了操作。那时你只需要一个同步原语,它不限制要执行的操作的数量,而是有一些总权重值,并确保所有当前运行的操作的总和小于比指定的重量值。然后,您可以请求使用给定的权重值运行给定的操作,并且在有足够的未使用权重值之前它不会真正运行。

没有现成的原语可以完全做到这一点(信号量非常接近,但还不完全存在)。但是,您可以相当容易地利用现有的同步原语制作一个。

public class WeightedSemaphore
{
    public WeightedSemaphore(int totalWeight)
    {
        currentWeight = TotalWeight = totalWeight;
    }

    private ManualResetEvent signal = new ManualResetEvent(false);
    private int currentWeight;
    public int TotalWeight { get; }
    public int CurrentWeight { get { lock (signal) return currentWeight; } }

    public void Wait(int weight)
    {
        while (true)
        {
            lock (signal)
            {
                if (currentWeight >= weight)
                {
                    currentWeight -= weight;
                    return;
                }
            }

            signal.Reset();
            signal.WaitOne();
        }
    }
    public void Release(int weight)
    {
        lock (signal)
        {
            currentWeight += weight;
            signal.Set();
        }
    }
}

现在您可以完成每个操作,确保在执行工作之前他们等待并提供他们的“大小”值。从那里开始,只需进行一些实验即可确定您当前系统可以支持的总重量。

请注意,这样做的副作用是您会发现越快的操作越容易获得优先级。当一些空间被释放时,较短的操作更有可能运行那里的内容,这意味着它会在更昂贵的操作甚至开始运行之前保留该空间。在许多情况下,这实际上是一个理想的属性,因为当您将更快的操作优先于更昂贵的操作时,平均响应时间实际上会下降

关于c# - 如何在某些任务非常昂贵的任务中负载平衡并行性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48890360/

相关文章:

c - OpenMP - 在 for 循环中生成和终止线程时的开销

BASH - 传输大文件并在传输后处理限制进程数量

时间:2019-03-17 标签:c#withdatabasemysqlworkbench

c# - 准确的 "Sieve of Erathostenes"在C#中判断BigInteger的素数

c# - 如何将多个选定的 Datagrid 值传递到 asp.net 中的另一个页面?

php - 在网络请求后运行后台进程

java - Spring MVC 如何从 Controller 使用 AsyncTaskExecutor

c# - 使用随机数时出现间歇性堆栈溢出异常

java - 什么时候并行执行任务是一种矫枉过正的行为?

python - python线程是如何工作的?