编程逻辑-在线程之间分配任务

| 假设您要5个线程同时处理数据。还假设您有89个任务要处理。 最终,您知道89/5 = 17,余数为4。最好的拆分任务的方法是让4个(余数)线程分别处理18(17 + 1)个任务,然后再拥有1(#个线程-余数)线程以处理17。 这将消除其余部分。只是为了验证:
Thread 1: Tasks  1-18  (18 tasks)
Thread 2: Tasks 19-36  (18 tasks)
Thread 3: Tasks 37-54  (18 tasks)
Thread 4: Tasks 55-72  (18 tasks)
Thread 5: Tasks 73-89  (17 tasks)
共完成89个任务。 我需要一种数学上/可编程性上获取每个线程的起始和终止范围的方法;下面应该打印出我上面列出的确切内容:
$NumTasks = 89
$NumThreads = 5
$Remainder = $NumTasks % $NumThreads 
$DefaultNumTasksAssigned = floor($NumTasks / $NumThreads)

For $i = 1 To $NumThreads
    if $i <= $Remainder Then
        $NumTasksAssigned = $DefaultNumTasksAssigned + 1
    else
        $NumTasksAssigned = $DefaultNumTasksAssigned
    endif
    $Start = ??????????
    $End = ??????????
    print Thread $i: Tasks $Start-$End ($NumTasksAssigned tasks)
Next
这也适用于任何数量的
$NumTasks
。 注意:请坚持回答当前的数学问题,并避免提出建议或假设情况。     
已邀请:
        我第二次请威尔·哈登发表讲话。您可能一次只给他们一个任务(或一次一次给几个任务,这取决于是否有很多开销,即,相对于启动/回收线程的成本,单个任务通常完成得很快) 。您随后的评论有效地解释了您的“线程”承担了沉重的创建成本,因此您希望通过尽可能多的工作来一次填充它们,而不是浪费时间创建每个线程少量的新“线程”工作。 无论如何...去
math question
... 如果您只想分配一次任务,请使用以下公式代替?????????按照您的逻辑,应该做到这一点:
$Start = 1 
         + (($i -1) * ($DefaultNumTasksAssigned + 1) 
        - (floor($i / ($Remainder + 1)) * ($i - $Remainder))
$End = $Start + $NumTasksAssigned -1
公式说明如下:    1是因为您的显示/逻辑是基于1而不是基于0的事实    第二项是因为我们通常在每次迭代中添加($ DefaultNumTasksAssigned + 1)。    第三项提供对最后几次迭代的更正。    它的第一部分,
(floor($i / ($Remainder + 1))
提供0,直到$ i到达第一个线程 不会再执行一项任务,此后再执行一项。 第二部分表示我们需要纠正多少。 $ End的公式更简单,唯一的窍门是减1,这是因为Start和End值是包含在内的(例如,在1到19之间,有19个任务而不是18个) 以下略作修改的逻辑也应该起作用,它通过保留$ Start变量的运行选项卡而不是每次都重新计算来避免\“ fancy \”公式。
$NumTasks = 89
$NumThreads = 5
$Remainder = $NumTasks % $NumThreads 
$DefaultNumTasksAssigned = floor($NumTasks / $NumThreads)
$Start = 1
For $i = 1 To $NumThreads
    if $i <= $Remainder Then    // fixed here!  need <= because $i is one-based
        $NumTasksAssigned = $DefaultNumTasksAssigned + 1
    else
        $NumTasksAssigned = $DefaultNumTasksAssigned
    endif
    $End = $Start + $NumTasksAssigned -1
    print Thread $i: Tasks $Start-$End ($NumTasksAssigned tasks)

    $Start = $Start + $NumTasksAssigned
Next
这是上面的Python转录
>>> def ShowWorkAllocation(NumTasks, NumThreads):
...   Remainder = NumTasks % NumThreads
...   DefaultNumTasksAssigned = math.floor(NumTasks / NumThreads)
...   Start = 1
...   for i in range(1, NumThreads + 1):
...     if i <= Remainder:
...        NumTasksAssigned = DefaultNumTasksAssigned + 1
...     else:
...        NumTasksAssigned = DefaultNumTasksAssigned
...     End = Start + NumTasksAssigned - 1
...     print(\"Thread \", i, \": Tasks \", Start, \"-\", End, \"(\", NumTasksAssigned,\")\")
...     Start = Start + NumTasksAssigned
...
>>>
>>> ShowWorkAllocation(89, 5)
Thread  1 : Tasks  1 - 18 ( 18 )
Thread  2 : Tasks  19 - 36 ( 18 )
Thread  3 : Tasks  37 - 54 ( 18 )
Thread  4 : Tasks  55 - 72 ( 18 )
Thread  5 : Tasks  73 - 89 ( 17 )

>>> ShowWorkAllocation(11, 5)
Thread  1 : Tasks  1 - 3 ( 3 )
Thread  2 : Tasks  4 - 5 ( 2 )
Thread  3 : Tasks  6 - 7 ( 2 )
Thread  4 : Tasks  8 - 9 ( 2 )
Thread  5 : Tasks  10 - 11 ( 2 )
>>>

>>> ShowWorkAllocation(89, 11)
Thread  1 : Tasks  1 - 9 ( 9 )
Thread  2 : Tasks  10 - 17 ( 8 )
Thread  3 : Tasks  18 - 25 ( 8 )
Thread  4 : Tasks  26 - 33 ( 8 )
Thread  5 : Tasks  34 - 41 ( 8 )
Thread  6 : Tasks  42 - 49 ( 8 )
Thread  7 : Tasks  50 - 57 ( 8 )
Thread  8 : Tasks  58 - 65 ( 8 )
Thread  9 : Tasks  66 - 73 ( 8 )
Thread  10 : Tasks  74 - 81 ( 8 )
Thread  11 : Tasks  82 - 89 ( 8 )
>>>
    
        为什么?而不是预先确定调度顺序,将所有任务放在队列中,然后让每个线程在就绪时将它们逐个拉出。然后,您的任务将基本上“尽可能快地”运行。 如果您已预先分配,则一个线程可能正在执行特别长的处理,并阻塞了滞留在其后的所有任务的运行。使用队列,当每个任务完成并释放一个线程时,它将抓取下一个任务并继续进行。 可以将其想像成一个银行,每个柜员只有1行,而一个柜员很多。在前者中,您可能会被困在放置硬币并逐一计数的人后面,而后者则到达下一个可用的出纳员,而PocketChange先生则不在。     
我认为您已经解决了错误的一半问题。 除非要满足以下所有条件,否则几乎不可能精确地确定完成所有任务所需的时间: 您的任务受100%CPU限制:也就是说,它们在运行时使用100%CPU,无需执行任何I / O 您的任何任务都不必以任何方式与任何其他任务同步 您拥有与CPU一样多的线程 运行这些任务的计算机不能同时执行任何其他有趣的任务 实际上,在大多数情况下,您的任务是I / O绑定的,而不是CPU绑定的:也就是说,您正在等待一些外部资源,例如从文件读取,从数据库获取或与远程计算机进行通信。在那种情况下,您只会通过添加更多线程来使情况变得更糟,因为它们都在争夺相同的稀缺资源。 最后,除非您有一些非常奇怪的硬件,否则实际上不可能同时运行五个线程。 (通常,处理器配置的倍数至少为2的倍数。)通常,如果任务非常受CPU限制,则最佳点是每个CPU大约1个线程,如果任务花费其一半的时间受CPU限制,则每个CPU大约2个线程,并且他们有一半的时间做IO等 tl; dr:我们需要进一步了解您的任务和硬件的外观,然后才能为您提供有关此问题的建议。     

要回复问题请先登录注册