【问题标题】:Dynamic chunks of preferred list of sizes首选大小列表的动态块
【发布时间】:2018-07-30 18:41:58
【问题描述】:

所以我遇到了块平衡的小障碍。

我面临的问题是我有一个长度为 n 的列表(通常在 400 到 10000 之间)

我希望将其分块并发送给一组工作人员,同时成为进程。

这是我的要求。

块的数量应始终保持尽可能高,但最好不要超过 8,因为这是一次可以处理的最大数量,超过 8 个块将必须排队。

零件的块长度应保存在 250 到 1000 之间的甚至 50 个容器中(这使得跟踪日志中的块变得容易得多)

示例
列表长度为 1600
6 个 250 块和 1 个 100 块

列表长度为 3590
7 块 450 和 1 块 440

13000人名单
13 个 1000 块(因为工人最多只能处理 1000 个) 在我发送新的之前,我将不得不等待块完成。

我需要自动选择它以最大限度地提高效率。

下面是我正在做的简化基础

public async Task SartSendingJob(int entityId, string body, string reference, IEnumerable<ProcessObject> processingList)
    {
        var jobId = Guid.NewGuid();
        _jobs.Add(new Job {EntityId = entityId, Id = jobId, ProcessType = ProcessType.Demo});

        var chunks = Split(processingList);

        foreach (var chunk in chunks)
        {
            var process = new Process {JobId = jobId, Id = Guid.NewGuid()};
            _processes.Add(process);

            Sender.SendSimpleMessage("PressRelease", body, reference, chunk.ToList(), process.Id);
        }
    }

    private IEnumerable<IEnumerable<T>> Split<T>(IEnumerable<T> list)
    {
        var workList = list.ToList();
        int chunksize;
        if (list.Count() > 8000)
        {
            //We know that we can't get lett then 8 chunks of maxumum, so we will use maxumum chunk size
            chunksize = 1000;
        }
        else
        {
            chunksize = CalculateBestChunkSize(workList.Count);
        }

        var sections = (int)Math.Ceiling((double)workList.Count / chunksize);

        int i = 0;

        IEnumerable<IEnumerable<T>> splits = workList.GroupBy(item => i++ % sections).Select(part => part.AsEnumerable());
        return splits;

    }

    private int CalculateBestChunkSize(int length)
    {
        //Do some magic
        return 500; //dummy response
    }

【问题讨论】:

  • 如果您可以分享minimal reproducible example 与样本输入和这些样本输入的预期结果,那就太棒了。
  • 请添加一些代码,我们不是来实施您的解决方案的。
  • 在遇到此问题之前您做了哪些努力?
  • 我不明白为什么对于 1600、5 块 300 和 1 块 100 是最有效的。为什么不是 8 个 200 块?
  • @mjwills 但在 1600 的相同情况下,一个块是 100,小于 250。

标签: c# arrays list split


【解决方案1】:

尝试以下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.Xml.Serialization;
using System.IO;


namespace ConsoleApplication23
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] lengths = { 45, 200, 1600, 3500, 13000 };

            foreach (int len in lengths)
            {

                int totalLen = len;
                do
                {
                    int processLen = totalLen > 8000 ? 8000 : totalLen;
                    totalLen -= 8000;

                    int numChunks = 8;
                    int chunkSize = 0;
                    for (; (numChunks > 0) && (chunkSize < 50); numChunks--)
                    {
                        chunkSize = processLen / numChunks;
                    }
                    chunkSize = 50 * (chunkSize / 50);
                    int lastChunk = processLen - (chunkSize * numChunks);
                    Console.WriteLine(" Number of Chunks '{0}', Chunk Size = '{1}', Total Size = '{2}'", numChunks, chunkSize, (numChunks * chunkSize) + lastChunk);
                } while (totalLen > 0);



            }

        }
    }



}

【讨论】:

    【解决方案2】:

    我的大脑让这变得更加困难。

    它需要喝点咖啡来了解它实际上在做什么。

    处理它的解决方案(因为我们总是将块大小最大化超过最大线程数)

        private IEnumerable<IEnumerable<T>> Split<T>(List<T> list)
        {
            int chunkSize;
            if (list.Count() > _maxChunkSize * _maxSendingThreads )
            {
                //We know that we can't get lett then 8 chunks of maxumum, so we will use maxumum chunk size
                chunkSize = 1000;
            }
            else
            {
                //Get the exact number of needed chunksize needed, then round up to nearest 50
                chunkSize = (int) (Math.Ceiling(list.Count / _maxSendingThreads / 50.0) * 50.0);
                if (chunkSize < 250)
                {
                    chunkSize = 250;
                }
            }
    
            var sections = (int) Math.Ceiling((double) list.Count / chunkSize);
    
            int i = 0;
    
            IEnumerable<IEnumerable<T>> splits = list.GroupBy(item => i++ % sections).Select(part => part.AsEnumerable());
            return splits;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-10
      • 2016-06-29
      相关资源
      最近更新 更多